github.com/riscv/riscv-go@v0.0.0-20200123204226-124ebd6fcc8e/src/runtime/os_windows.go (about)

     1  // Copyright 2009 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package runtime
     6  
     7  import (
     8  	"runtime/internal/atomic"
     9  	"unsafe"
    10  )
    11  
    12  // TODO(brainman): should not need those
    13  const (
    14  	_NSIG = 65
    15  )
    16  
    17  //go:cgo_import_dynamic runtime._AddVectoredExceptionHandler AddVectoredExceptionHandler%2 "kernel32.dll"
    18  //go:cgo_import_dynamic runtime._CloseHandle CloseHandle%1 "kernel32.dll"
    19  //go:cgo_import_dynamic runtime._CreateEventA CreateEventA%4 "kernel32.dll"
    20  //go:cgo_import_dynamic runtime._CreateIoCompletionPort CreateIoCompletionPort%4 "kernel32.dll"
    21  //go:cgo_import_dynamic runtime._CreateThread CreateThread%6 "kernel32.dll"
    22  //go:cgo_import_dynamic runtime._CreateWaitableTimerA CreateWaitableTimerA%3 "kernel32.dll"
    23  //go:cgo_import_dynamic runtime._DuplicateHandle DuplicateHandle%7 "kernel32.dll"
    24  //go:cgo_import_dynamic runtime._ExitProcess ExitProcess%1 "kernel32.dll"
    25  //go:cgo_import_dynamic runtime._FreeEnvironmentStringsW FreeEnvironmentStringsW%1 "kernel32.dll"
    26  //go:cgo_import_dynamic runtime._GetConsoleMode GetConsoleMode%2 "kernel32.dll"
    27  //go:cgo_import_dynamic runtime._GetEnvironmentStringsW GetEnvironmentStringsW%0 "kernel32.dll"
    28  //go:cgo_import_dynamic runtime._GetProcAddress GetProcAddress%2 "kernel32.dll"
    29  //go:cgo_import_dynamic runtime._GetProcessAffinityMask GetProcessAffinityMask%3 "kernel32.dll"
    30  //go:cgo_import_dynamic runtime._GetQueuedCompletionStatus GetQueuedCompletionStatus%5 "kernel32.dll"
    31  //go:cgo_import_dynamic runtime._GetStdHandle GetStdHandle%1 "kernel32.dll"
    32  //go:cgo_import_dynamic runtime._GetSystemInfo GetSystemInfo%1 "kernel32.dll"
    33  //go:cgo_import_dynamic runtime._GetThreadContext GetThreadContext%2 "kernel32.dll"
    34  //go:cgo_import_dynamic runtime._LoadLibraryW LoadLibraryW%1 "kernel32.dll"
    35  //go:cgo_import_dynamic runtime._LoadLibraryA LoadLibraryA%1 "kernel32.dll"
    36  //go:cgo_import_dynamic runtime._ResumeThread ResumeThread%1 "kernel32.dll"
    37  //go:cgo_import_dynamic runtime._SetConsoleCtrlHandler SetConsoleCtrlHandler%2 "kernel32.dll"
    38  //go:cgo_import_dynamic runtime._SetErrorMode SetErrorMode%1 "kernel32.dll"
    39  //go:cgo_import_dynamic runtime._SetEvent SetEvent%1 "kernel32.dll"
    40  //go:cgo_import_dynamic runtime._SetProcessPriorityBoost SetProcessPriorityBoost%2 "kernel32.dll"
    41  //go:cgo_import_dynamic runtime._SetThreadPriority SetThreadPriority%2 "kernel32.dll"
    42  //go:cgo_import_dynamic runtime._SetUnhandledExceptionFilter SetUnhandledExceptionFilter%1 "kernel32.dll"
    43  //go:cgo_import_dynamic runtime._SetWaitableTimer SetWaitableTimer%6 "kernel32.dll"
    44  //go:cgo_import_dynamic runtime._SuspendThread SuspendThread%1 "kernel32.dll"
    45  //go:cgo_import_dynamic runtime._SwitchToThread SwitchToThread%0 "kernel32.dll"
    46  //go:cgo_import_dynamic runtime._VirtualAlloc VirtualAlloc%4 "kernel32.dll"
    47  //go:cgo_import_dynamic runtime._VirtualFree VirtualFree%3 "kernel32.dll"
    48  //go:cgo_import_dynamic runtime._WSAGetOverlappedResult WSAGetOverlappedResult%5 "ws2_32.dll"
    49  //go:cgo_import_dynamic runtime._WaitForSingleObject WaitForSingleObject%2 "kernel32.dll"
    50  //go:cgo_import_dynamic runtime._WriteConsoleW WriteConsoleW%5 "kernel32.dll"
    51  //go:cgo_import_dynamic runtime._WriteFile WriteFile%5 "kernel32.dll"
    52  //go:cgo_import_dynamic runtime._timeBeginPeriod timeBeginPeriod%1 "winmm.dll"
    53  
    54  type stdFunction unsafe.Pointer
    55  
    56  var (
    57  	// Following syscalls are available on every Windows PC.
    58  	// All these variables are set by the Windows executable
    59  	// loader before the Go program starts.
    60  	_AddVectoredExceptionHandler,
    61  	_CloseHandle,
    62  	_CreateEventA,
    63  	_CreateIoCompletionPort,
    64  	_CreateThread,
    65  	_CreateWaitableTimerA,
    66  	_DuplicateHandle,
    67  	_ExitProcess,
    68  	_FreeEnvironmentStringsW,
    69  	_GetConsoleMode,
    70  	_GetEnvironmentStringsW,
    71  	_GetProcAddress,
    72  	_GetProcessAffinityMask,
    73  	_GetQueuedCompletionStatus,
    74  	_GetStdHandle,
    75  	_GetSystemInfo,
    76  	_GetThreadContext,
    77  	_LoadLibraryW,
    78  	_LoadLibraryA,
    79  	_ResumeThread,
    80  	_SetConsoleCtrlHandler,
    81  	_SetErrorMode,
    82  	_SetEvent,
    83  	_SetProcessPriorityBoost,
    84  	_SetThreadPriority,
    85  	_SetUnhandledExceptionFilter,
    86  	_SetWaitableTimer,
    87  	_SuspendThread,
    88  	_SwitchToThread,
    89  	_VirtualAlloc,
    90  	_VirtualFree,
    91  	_WSAGetOverlappedResult,
    92  	_WaitForSingleObject,
    93  	_WriteConsoleW,
    94  	_WriteFile,
    95  	_timeBeginPeriod,
    96  	_ stdFunction
    97  
    98  	// Following syscalls are only available on some Windows PCs.
    99  	// We will load syscalls, if available, before using them.
   100  	_AddDllDirectory,
   101  	_AddVectoredContinueHandler,
   102  	_GetQueuedCompletionStatusEx,
   103  	_LoadLibraryExW,
   104  	_ stdFunction
   105  
   106  	// Use RtlGenRandom to generate cryptographically random data.
   107  	// This approach has been recommended by Microsoft (see issue
   108  	// 15589 for details).
   109  	// The RtlGenRandom is not listed in advapi32.dll, instead
   110  	// RtlGenRandom function can be found by searching for SystemFunction036.
   111  	// Also some versions of Mingw cannot link to SystemFunction036
   112  	// when building executable as Cgo. So load SystemFunction036
   113  	// manually during runtime startup.
   114  	_RtlGenRandom stdFunction
   115  
   116  	// Load ntdll.dll manually during startup, otherwise Mingw
   117  	// links wrong printf function to cgo executable (see issue
   118  	// 12030 for details).
   119  	_NtWaitForSingleObject stdFunction
   120  )
   121  
   122  // Function to be called by windows CreateThread
   123  // to start new os thread.
   124  func tstart_stdcall(newm *m) uint32
   125  
   126  func ctrlhandler(_type uint32) uint32
   127  
   128  type mOS struct {
   129  	waitsema uintptr // semaphore for parking on locks
   130  }
   131  
   132  //go:linkname os_sigpipe os.sigpipe
   133  func os_sigpipe() {
   134  	throw("too many writes on closed pipe")
   135  }
   136  
   137  // Stubs so tests can link correctly. These should never be called.
   138  func open(name *byte, mode, perm int32) int32 {
   139  	throw("unimplemented")
   140  	return -1
   141  }
   142  func closefd(fd int32) int32 {
   143  	throw("unimplemented")
   144  	return -1
   145  }
   146  func read(fd int32, p unsafe.Pointer, n int32) int32 {
   147  	throw("unimplemented")
   148  	return -1
   149  }
   150  
   151  type sigset struct{}
   152  
   153  // Call a Windows function with stdcall conventions,
   154  // and switch to os stack during the call.
   155  func asmstdcall(fn unsafe.Pointer)
   156  
   157  var asmstdcallAddr unsafe.Pointer
   158  
   159  func windowsFindfunc(lib uintptr, name []byte) stdFunction {
   160  	if name[len(name)-1] != 0 {
   161  		throw("usage")
   162  	}
   163  	f := stdcall2(_GetProcAddress, lib, uintptr(unsafe.Pointer(&name[0])))
   164  	return stdFunction(unsafe.Pointer(f))
   165  }
   166  
   167  func loadOptionalSyscalls() {
   168  	var kernel32dll = []byte("kernel32.dll\000")
   169  	k32 := stdcall1(_LoadLibraryA, uintptr(unsafe.Pointer(&kernel32dll[0])))
   170  	if k32 == 0 {
   171  		throw("kernel32.dll not found")
   172  	}
   173  	_AddDllDirectory = windowsFindfunc(k32, []byte("AddDllDirectory\000"))
   174  	_AddVectoredContinueHandler = windowsFindfunc(k32, []byte("AddVectoredContinueHandler\000"))
   175  	_GetQueuedCompletionStatusEx = windowsFindfunc(k32, []byte("GetQueuedCompletionStatusEx\000"))
   176  	_LoadLibraryExW = windowsFindfunc(k32, []byte("LoadLibraryExW\000"))
   177  
   178  	var advapi32dll = []byte("advapi32.dll\000")
   179  	a32 := stdcall1(_LoadLibraryA, uintptr(unsafe.Pointer(&advapi32dll[0])))
   180  	if a32 == 0 {
   181  		throw("advapi32.dll not found")
   182  	}
   183  	_RtlGenRandom = windowsFindfunc(a32, []byte("SystemFunction036\000"))
   184  
   185  	var ntdll = []byte("ntdll.dll\000")
   186  	n32 := stdcall1(_LoadLibraryA, uintptr(unsafe.Pointer(&ntdll[0])))
   187  	if n32 == 0 {
   188  		throw("ntdll.dll not found")
   189  	}
   190  	_NtWaitForSingleObject = windowsFindfunc(n32, []byte("NtWaitForSingleObject\000"))
   191  }
   192  
   193  //go:nosplit
   194  func getLoadLibrary() uintptr {
   195  	return uintptr(unsafe.Pointer(_LoadLibraryW))
   196  }
   197  
   198  //go:nosplit
   199  func getLoadLibraryEx() uintptr {
   200  	return uintptr(unsafe.Pointer(_LoadLibraryExW))
   201  }
   202  
   203  //go:nosplit
   204  func getGetProcAddress() uintptr {
   205  	return uintptr(unsafe.Pointer(_GetProcAddress))
   206  }
   207  
   208  func getproccount() int32 {
   209  	var mask, sysmask uintptr
   210  	ret := stdcall3(_GetProcessAffinityMask, currentProcess, uintptr(unsafe.Pointer(&mask)), uintptr(unsafe.Pointer(&sysmask)))
   211  	if ret != 0 {
   212  		n := 0
   213  		maskbits := int(unsafe.Sizeof(mask) * 8)
   214  		for i := 0; i < maskbits; i++ {
   215  			if mask&(1<<uint(i)) != 0 {
   216  				n++
   217  			}
   218  		}
   219  		if n != 0 {
   220  			return int32(n)
   221  		}
   222  	}
   223  	// use GetSystemInfo if GetProcessAffinityMask fails
   224  	var info systeminfo
   225  	stdcall1(_GetSystemInfo, uintptr(unsafe.Pointer(&info)))
   226  	return int32(info.dwnumberofprocessors)
   227  }
   228  
   229  func getPageSize() uintptr {
   230  	var info systeminfo
   231  	stdcall1(_GetSystemInfo, uintptr(unsafe.Pointer(&info)))
   232  	return uintptr(info.dwpagesize)
   233  }
   234  
   235  const (
   236  	currentProcess = ^uintptr(0) // -1 = current process
   237  	currentThread  = ^uintptr(1) // -2 = current thread
   238  )
   239  
   240  // in sys_windows_386.s and sys_windows_amd64.s:
   241  func externalthreadhandler()
   242  func getlasterror() uint32
   243  func setlasterror(err uint32)
   244  
   245  // When loading DLLs, we prefer to use LoadLibraryEx with
   246  // LOAD_LIBRARY_SEARCH_* flags, if available. LoadLibraryEx is not
   247  // available on old Windows, though, and the LOAD_LIBRARY_SEARCH_*
   248  // flags are not available on some versions of Windows without a
   249  // security patch.
   250  //
   251  // https://msdn.microsoft.com/en-us/library/ms684179(v=vs.85).aspx says:
   252  // "Windows 7, Windows Server 2008 R2, Windows Vista, and Windows
   253  // Server 2008: The LOAD_LIBRARY_SEARCH_* flags are available on
   254  // systems that have KB2533623 installed. To determine whether the
   255  // flags are available, use GetProcAddress to get the address of the
   256  // AddDllDirectory, RemoveDllDirectory, or SetDefaultDllDirectories
   257  // function. If GetProcAddress succeeds, the LOAD_LIBRARY_SEARCH_*
   258  // flags can be used with LoadLibraryEx."
   259  var useLoadLibraryEx bool
   260  
   261  var timeBeginPeriodRetValue uint32
   262  
   263  func osinit() {
   264  	asmstdcallAddr = unsafe.Pointer(funcPC(asmstdcall))
   265  	usleep2Addr = unsafe.Pointer(funcPC(usleep2))
   266  	switchtothreadAddr = unsafe.Pointer(funcPC(switchtothread))
   267  
   268  	setBadSignalMsg()
   269  
   270  	loadOptionalSyscalls()
   271  
   272  	useLoadLibraryEx = (_LoadLibraryExW != nil && _AddDllDirectory != nil)
   273  
   274  	disableWER()
   275  
   276  	externalthreadhandlerp = funcPC(externalthreadhandler)
   277  
   278  	initExceptionHandler()
   279  
   280  	stdcall2(_SetConsoleCtrlHandler, funcPC(ctrlhandler), 1)
   281  
   282  	timeBeginPeriodRetValue = uint32(stdcall1(_timeBeginPeriod, 1))
   283  
   284  	ncpu = getproccount()
   285  
   286  	physPageSize = getPageSize()
   287  
   288  	// Windows dynamic priority boosting assumes that a process has different types
   289  	// of dedicated threads -- GUI, IO, computational, etc. Go processes use
   290  	// equivalent threads that all do a mix of GUI, IO, computations, etc.
   291  	// In such context dynamic priority boosting does nothing but harm, so we turn it off.
   292  	stdcall2(_SetProcessPriorityBoost, currentProcess, 1)
   293  }
   294  
   295  //go:nosplit
   296  func getRandomData(r []byte) {
   297  	n := 0
   298  	if stdcall2(_RtlGenRandom, uintptr(unsafe.Pointer(&r[0])), uintptr(len(r)))&0xff != 0 {
   299  		n = len(r)
   300  	}
   301  	extendRandom(r, n)
   302  }
   303  
   304  func goenvs() {
   305  	// strings is a pointer to environment variable pairs in the form:
   306  	//     "envA=valA\x00envB=valB\x00\x00" (in UTF-16)
   307  	// Two consecutive zero bytes end the list.
   308  	strings := unsafe.Pointer(stdcall0(_GetEnvironmentStringsW))
   309  	p := (*[1 << 24]uint16)(strings)[:]
   310  
   311  	n := 0
   312  	for from, i := 0, 0; true; i++ {
   313  		if p[i] == 0 {
   314  			// empty string marks the end
   315  			if i == from {
   316  				break
   317  			}
   318  			from = i + 1
   319  			n++
   320  		}
   321  	}
   322  	envs = make([]string, n)
   323  
   324  	for i := range envs {
   325  		envs[i] = gostringw(&p[0])
   326  		for p[0] != 0 {
   327  			p = p[1:]
   328  		}
   329  		p = p[1:] // skip nil byte
   330  	}
   331  
   332  	stdcall1(_FreeEnvironmentStringsW, uintptr(strings))
   333  }
   334  
   335  // exiting is set to non-zero when the process is exiting.
   336  var exiting uint32
   337  
   338  //go:nosplit
   339  func exit(code int32) {
   340  	atomic.Store(&exiting, 1)
   341  	stdcall1(_ExitProcess, uintptr(code))
   342  }
   343  
   344  //go:nosplit
   345  func write(fd uintptr, buf unsafe.Pointer, n int32) int32 {
   346  	const (
   347  		_STD_OUTPUT_HANDLE = ^uintptr(10) // -11
   348  		_STD_ERROR_HANDLE  = ^uintptr(11) // -12
   349  	)
   350  	var handle uintptr
   351  	switch fd {
   352  	case 1:
   353  		handle = stdcall1(_GetStdHandle, _STD_OUTPUT_HANDLE)
   354  	case 2:
   355  		handle = stdcall1(_GetStdHandle, _STD_ERROR_HANDLE)
   356  	default:
   357  		// assume fd is real windows handle.
   358  		handle = fd
   359  	}
   360  	isASCII := true
   361  	b := (*[1 << 30]byte)(buf)[:n]
   362  	for _, x := range b {
   363  		if x >= 0x80 {
   364  			isASCII = false
   365  			break
   366  		}
   367  	}
   368  
   369  	if !isASCII {
   370  		var m uint32
   371  		isConsole := stdcall2(_GetConsoleMode, handle, uintptr(unsafe.Pointer(&m))) != 0
   372  		// If this is a console output, various non-unicode code pages can be in use.
   373  		// Use the dedicated WriteConsole call to ensure unicode is printed correctly.
   374  		if isConsole {
   375  			return int32(writeConsole(handle, buf, n))
   376  		}
   377  	}
   378  	var written uint32
   379  	stdcall5(_WriteFile, handle, uintptr(buf), uintptr(n), uintptr(unsafe.Pointer(&written)), 0)
   380  	return int32(written)
   381  }
   382  
   383  var (
   384  	utf16ConsoleBack     [1000]uint16
   385  	utf16ConsoleBackLock mutex
   386  )
   387  
   388  // writeConsole writes bufLen bytes from buf to the console File.
   389  // It returns the number of bytes written.
   390  func writeConsole(handle uintptr, buf unsafe.Pointer, bufLen int32) int {
   391  	const surr2 = (surrogateMin + surrogateMax + 1) / 2
   392  
   393  	// Do not use defer for unlock. May cause issues when printing a panic.
   394  	lock(&utf16ConsoleBackLock)
   395  
   396  	b := (*[1 << 30]byte)(buf)[:bufLen]
   397  	s := *(*string)(unsafe.Pointer(&b))
   398  
   399  	utf16tmp := utf16ConsoleBack[:]
   400  
   401  	total := len(s)
   402  	w := 0
   403  	for _, r := range s {
   404  		if w >= len(utf16tmp)-2 {
   405  			writeConsoleUTF16(handle, utf16tmp[:w])
   406  			w = 0
   407  		}
   408  		if r < 0x10000 {
   409  			utf16tmp[w] = uint16(r)
   410  			w++
   411  		} else {
   412  			r -= 0x10000
   413  			utf16tmp[w] = surrogateMin + uint16(r>>10)&0x3ff
   414  			utf16tmp[w+1] = surr2 + uint16(r)&0x3ff
   415  			w += 2
   416  		}
   417  	}
   418  	writeConsoleUTF16(handle, utf16tmp[:w])
   419  	unlock(&utf16ConsoleBackLock)
   420  	return total
   421  }
   422  
   423  // writeConsoleUTF16 is the dedicated windows calls that correctly prints
   424  // to the console regardless of the current code page. Input is utf-16 code points.
   425  // The handle must be a console handle.
   426  func writeConsoleUTF16(handle uintptr, b []uint16) {
   427  	l := uint32(len(b))
   428  	if l == 0 {
   429  		return
   430  	}
   431  	var written uint32
   432  	stdcall5(_WriteConsoleW,
   433  		handle,
   434  		uintptr(unsafe.Pointer(&b[0])),
   435  		uintptr(l),
   436  		uintptr(unsafe.Pointer(&written)),
   437  		0,
   438  	)
   439  	return
   440  }
   441  
   442  //go:nosplit
   443  func semasleep(ns int64) int32 {
   444  	const (
   445  		_WAIT_ABANDONED = 0x00000080
   446  		_WAIT_OBJECT_0  = 0x00000000
   447  		_WAIT_TIMEOUT   = 0x00000102
   448  		_WAIT_FAILED    = 0xFFFFFFFF
   449  	)
   450  
   451  	// store ms in ns to save stack space
   452  	if ns < 0 {
   453  		ns = _INFINITE
   454  	} else {
   455  		ns = int64(timediv(ns, 1000000, nil))
   456  		if ns == 0 {
   457  			ns = 1
   458  		}
   459  	}
   460  
   461  	result := stdcall2(_WaitForSingleObject, getg().m.waitsema, uintptr(ns))
   462  	switch result {
   463  	case _WAIT_OBJECT_0: //signaled
   464  		return 0
   465  
   466  	case _WAIT_TIMEOUT:
   467  		return -1
   468  
   469  	case _WAIT_ABANDONED:
   470  		systemstack(func() {
   471  			throw("runtime.semasleep wait_abandoned")
   472  		})
   473  
   474  	case _WAIT_FAILED:
   475  		systemstack(func() {
   476  			print("runtime: waitforsingleobject wait_failed; errno=", getlasterror(), "\n")
   477  			throw("runtime.semasleep wait_failed")
   478  		})
   479  
   480  	default:
   481  		systemstack(func() {
   482  			print("runtime: waitforsingleobject unexpected; result=", result, "\n")
   483  			throw("runtime.semasleep unexpected")
   484  		})
   485  	}
   486  
   487  	return -1 // unreachable
   488  }
   489  
   490  //go:nosplit
   491  func semawakeup(mp *m) {
   492  	if stdcall1(_SetEvent, mp.waitsema) == 0 {
   493  		systemstack(func() {
   494  			print("runtime: setevent failed; errno=", getlasterror(), "\n")
   495  			throw("runtime.semawakeup")
   496  		})
   497  	}
   498  }
   499  
   500  //go:nosplit
   501  func semacreate(mp *m) {
   502  	if mp.waitsema != 0 {
   503  		return
   504  	}
   505  	mp.waitsema = stdcall4(_CreateEventA, 0, 0, 0, 0)
   506  	if mp.waitsema == 0 {
   507  		systemstack(func() {
   508  			print("runtime: createevent failed; errno=", getlasterror(), "\n")
   509  			throw("runtime.semacreate")
   510  		})
   511  	}
   512  }
   513  
   514  // May run with m.p==nil, so write barriers are not allowed. This
   515  // function is called by newosproc0, so it is also required to
   516  // operate without stack guards.
   517  //go:nowritebarrierrec
   518  //go:nosplit
   519  func newosproc(mp *m, stk unsafe.Pointer) {
   520  	const _STACK_SIZE_PARAM_IS_A_RESERVATION = 0x00010000
   521  	thandle := stdcall6(_CreateThread, 0, 0x20000,
   522  		funcPC(tstart_stdcall), uintptr(unsafe.Pointer(mp)),
   523  		_STACK_SIZE_PARAM_IS_A_RESERVATION, 0)
   524  
   525  	if thandle == 0 {
   526  		if atomic.Load(&exiting) != 0 {
   527  			// CreateThread may fail if called
   528  			// concurrently with ExitProcess. If this
   529  			// happens, just freeze this thread and let
   530  			// the process exit. See issue #18253.
   531  			lock(&deadlock)
   532  			lock(&deadlock)
   533  		}
   534  		print("runtime: failed to create new OS thread (have ", mcount(), " already; errno=", getlasterror(), ")\n")
   535  		throw("runtime.newosproc")
   536  	}
   537  }
   538  
   539  // Used by the C library build mode. On Linux this function would allocate a
   540  // stack, but that's not necessary for Windows. No stack guards are present
   541  // and the GC has not been initialized, so write barriers will fail.
   542  //go:nowritebarrierrec
   543  //go:nosplit
   544  func newosproc0(mp *m, stk unsafe.Pointer) {
   545  	newosproc(mp, stk)
   546  }
   547  
   548  // Called to initialize a new m (including the bootstrap m).
   549  // Called on the parent thread (main thread in case of bootstrap), can allocate memory.
   550  func mpreinit(mp *m) {
   551  }
   552  
   553  //go:nosplit
   554  func msigsave(mp *m) {
   555  }
   556  
   557  //go:nosplit
   558  func msigrestore(sigmask sigset) {
   559  }
   560  
   561  //go:nosplit
   562  func sigblock() {
   563  }
   564  
   565  // Called to initialize a new m (including the bootstrap m).
   566  // Called on the new thread, cannot allocate memory.
   567  func minit() {
   568  	var thandle uintptr
   569  	stdcall7(_DuplicateHandle, currentProcess, currentThread, currentProcess, uintptr(unsafe.Pointer(&thandle)), 0, 0, _DUPLICATE_SAME_ACCESS)
   570  	atomic.Storeuintptr(&getg().m.thread, thandle)
   571  }
   572  
   573  // Called from dropm to undo the effect of an minit.
   574  //go:nosplit
   575  func unminit() {
   576  	tp := &getg().m.thread
   577  	stdcall1(_CloseHandle, *tp)
   578  	*tp = 0
   579  }
   580  
   581  // Described in http://www.dcl.hpi.uni-potsdam.de/research/WRK/2007/08/getting-os-information-the-kuser_shared_data-structure/
   582  type _KSYSTEM_TIME struct {
   583  	LowPart   uint32
   584  	High1Time int32
   585  	High2Time int32
   586  }
   587  
   588  const (
   589  	_INTERRUPT_TIME = 0x7ffe0008
   590  	_SYSTEM_TIME    = 0x7ffe0014
   591  )
   592  
   593  //go:nosplit
   594  func systime(addr uintptr) int64 {
   595  	timeaddr := (*_KSYSTEM_TIME)(unsafe.Pointer(addr))
   596  
   597  	var t _KSYSTEM_TIME
   598  	for i := 1; i < 10000; i++ {
   599  		// these fields must be read in that order (see URL above)
   600  		t.High1Time = timeaddr.High1Time
   601  		t.LowPart = timeaddr.LowPart
   602  		t.High2Time = timeaddr.High2Time
   603  		if t.High1Time == t.High2Time {
   604  			return int64(t.High1Time)<<32 | int64(t.LowPart)
   605  		}
   606  		if (i % 100) == 0 {
   607  			osyield()
   608  		}
   609  	}
   610  	systemstack(func() {
   611  		throw("interrupt/system time is changing too fast")
   612  	})
   613  	return 0
   614  }
   615  
   616  //go:nosplit
   617  func unixnano() int64 {
   618  	return (systime(_SYSTEM_TIME) - 116444736000000000) * 100
   619  }
   620  
   621  //go:nosplit
   622  func nanotime() int64 {
   623  	return systime(_INTERRUPT_TIME) * 100
   624  }
   625  
   626  // Calling stdcall on os stack.
   627  // May run during STW, so write barriers are not allowed.
   628  //go:nowritebarrier
   629  //go:nosplit
   630  func stdcall(fn stdFunction) uintptr {
   631  	gp := getg()
   632  	mp := gp.m
   633  	mp.libcall.fn = uintptr(unsafe.Pointer(fn))
   634  
   635  	if mp.profilehz != 0 {
   636  		// leave pc/sp for cpu profiler
   637  		mp.libcallg.set(gp)
   638  		mp.libcallpc = getcallerpc(unsafe.Pointer(&fn))
   639  		// sp must be the last, because once async cpu profiler finds
   640  		// all three values to be non-zero, it will use them
   641  		mp.libcallsp = getcallersp(unsafe.Pointer(&fn))
   642  	}
   643  	asmcgocall(asmstdcallAddr, unsafe.Pointer(&mp.libcall))
   644  	mp.libcallsp = 0
   645  	return mp.libcall.r1
   646  }
   647  
   648  //go:nosplit
   649  func stdcall0(fn stdFunction) uintptr {
   650  	mp := getg().m
   651  	mp.libcall.n = 0
   652  	mp.libcall.args = uintptr(noescape(unsafe.Pointer(&fn))) // it's unused but must be non-nil, otherwise crashes
   653  	return stdcall(fn)
   654  }
   655  
   656  //go:nosplit
   657  func stdcall1(fn stdFunction, a0 uintptr) uintptr {
   658  	mp := getg().m
   659  	mp.libcall.n = 1
   660  	mp.libcall.args = uintptr(noescape(unsafe.Pointer(&a0)))
   661  	return stdcall(fn)
   662  }
   663  
   664  //go:nosplit
   665  func stdcall2(fn stdFunction, a0, a1 uintptr) uintptr {
   666  	mp := getg().m
   667  	mp.libcall.n = 2
   668  	mp.libcall.args = uintptr(noescape(unsafe.Pointer(&a0)))
   669  	return stdcall(fn)
   670  }
   671  
   672  //go:nosplit
   673  func stdcall3(fn stdFunction, a0, a1, a2 uintptr) uintptr {
   674  	mp := getg().m
   675  	mp.libcall.n = 3
   676  	mp.libcall.args = uintptr(noescape(unsafe.Pointer(&a0)))
   677  	return stdcall(fn)
   678  }
   679  
   680  //go:nosplit
   681  func stdcall4(fn stdFunction, a0, a1, a2, a3 uintptr) uintptr {
   682  	mp := getg().m
   683  	mp.libcall.n = 4
   684  	mp.libcall.args = uintptr(noescape(unsafe.Pointer(&a0)))
   685  	return stdcall(fn)
   686  }
   687  
   688  //go:nosplit
   689  func stdcall5(fn stdFunction, a0, a1, a2, a3, a4 uintptr) uintptr {
   690  	mp := getg().m
   691  	mp.libcall.n = 5
   692  	mp.libcall.args = uintptr(noescape(unsafe.Pointer(&a0)))
   693  	return stdcall(fn)
   694  }
   695  
   696  //go:nosplit
   697  func stdcall6(fn stdFunction, a0, a1, a2, a3, a4, a5 uintptr) uintptr {
   698  	mp := getg().m
   699  	mp.libcall.n = 6
   700  	mp.libcall.args = uintptr(noescape(unsafe.Pointer(&a0)))
   701  	return stdcall(fn)
   702  }
   703  
   704  //go:nosplit
   705  func stdcall7(fn stdFunction, a0, a1, a2, a3, a4, a5, a6 uintptr) uintptr {
   706  	mp := getg().m
   707  	mp.libcall.n = 7
   708  	mp.libcall.args = uintptr(noescape(unsafe.Pointer(&a0)))
   709  	return stdcall(fn)
   710  }
   711  
   712  // in sys_windows_386.s and sys_windows_amd64.s
   713  func onosstack(fn unsafe.Pointer, arg uint32)
   714  func usleep2(usec uint32)
   715  func switchtothread()
   716  
   717  var usleep2Addr unsafe.Pointer
   718  var switchtothreadAddr unsafe.Pointer
   719  
   720  //go:nosplit
   721  func osyield() {
   722  	onosstack(switchtothreadAddr, 0)
   723  }
   724  
   725  //go:nosplit
   726  func usleep(us uint32) {
   727  	// Have 1us units; want 100ns units.
   728  	onosstack(usleep2Addr, 10*us)
   729  }
   730  
   731  func ctrlhandler1(_type uint32) uint32 {
   732  	var s uint32
   733  
   734  	switch _type {
   735  	case _CTRL_C_EVENT, _CTRL_BREAK_EVENT:
   736  		s = _SIGINT
   737  	default:
   738  		return 0
   739  	}
   740  
   741  	if sigsend(s) {
   742  		return 1
   743  	}
   744  	exit(2) // SIGINT, SIGTERM, etc
   745  	return 0
   746  }
   747  
   748  // in sys_windows_386.s and sys_windows_amd64.s
   749  func profileloop()
   750  
   751  var profiletimer uintptr
   752  
   753  func profilem(mp *m) {
   754  	var r *context
   755  	rbuf := make([]byte, unsafe.Sizeof(*r)+15)
   756  
   757  	tls := &mp.tls[0]
   758  	gp := *((**g)(unsafe.Pointer(tls)))
   759  
   760  	// align Context to 16 bytes
   761  	r = (*context)(unsafe.Pointer((uintptr(unsafe.Pointer(&rbuf[15]))) &^ 15))
   762  	r.contextflags = _CONTEXT_CONTROL
   763  	stdcall2(_GetThreadContext, mp.thread, uintptr(unsafe.Pointer(r)))
   764  	sigprof(r.ip(), r.sp(), 0, gp, mp)
   765  }
   766  
   767  func profileloop1(param uintptr) uint32 {
   768  	stdcall2(_SetThreadPriority, currentThread, _THREAD_PRIORITY_HIGHEST)
   769  
   770  	for {
   771  		stdcall2(_WaitForSingleObject, profiletimer, _INFINITE)
   772  		first := (*m)(atomic.Loadp(unsafe.Pointer(&allm)))
   773  		for mp := first; mp != nil; mp = mp.alllink {
   774  			thread := atomic.Loaduintptr(&mp.thread)
   775  			// Do not profile threads blocked on Notes,
   776  			// this includes idle worker threads,
   777  			// idle timer thread, idle heap scavenger, etc.
   778  			if thread == 0 || mp.profilehz == 0 || mp.blocked {
   779  				continue
   780  			}
   781  			stdcall1(_SuspendThread, thread)
   782  			if mp.profilehz != 0 && !mp.blocked {
   783  				profilem(mp)
   784  			}
   785  			stdcall1(_ResumeThread, thread)
   786  		}
   787  	}
   788  }
   789  
   790  var cpuprofilerlock mutex
   791  
   792  func resetcpuprofiler(hz int32) {
   793  	lock(&cpuprofilerlock)
   794  	if profiletimer == 0 {
   795  		timer := stdcall3(_CreateWaitableTimerA, 0, 0, 0)
   796  		atomic.Storeuintptr(&profiletimer, timer)
   797  		thread := stdcall6(_CreateThread, 0, 0, funcPC(profileloop), 0, 0, 0)
   798  		stdcall2(_SetThreadPriority, thread, _THREAD_PRIORITY_HIGHEST)
   799  		stdcall1(_CloseHandle, thread)
   800  	}
   801  	unlock(&cpuprofilerlock)
   802  
   803  	ms := int32(0)
   804  	due := ^int64(^uint64(1 << 63))
   805  	if hz > 0 {
   806  		ms = 1000 / hz
   807  		if ms == 0 {
   808  			ms = 1
   809  		}
   810  		due = int64(ms) * -10000
   811  	}
   812  	stdcall6(_SetWaitableTimer, profiletimer, uintptr(unsafe.Pointer(&due)), uintptr(ms), 0, 0, 0)
   813  	atomic.Store((*uint32)(unsafe.Pointer(&getg().m.profilehz)), uint32(hz))
   814  }
   815  
   816  func memlimit() uintptr {
   817  	return 0
   818  }