github.com/x04/go/src@v0.0.0-20200202162449-3d481ceb3525/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  	"github.com/x04/go/src/runtime/internal/atomic"
     9  	"github.com/x04/go/src/runtime/internal/sys"
    10  	"github.com/x04/go/src/unsafe"
    11  )
    12  
    13  // TODO(brainman): should not need those
    14  const (
    15  	_NSIG = 65
    16  )
    17  
    18  //go:cgo_import_dynamic runtime._AddVectoredExceptionHandler AddVectoredExceptionHandler%2 "kernel32.dll"
    19  //go:cgo_import_dynamic runtime._CloseHandle CloseHandle%1 "kernel32.dll"
    20  //go:cgo_import_dynamic runtime._CreateEventA CreateEventA%4 "kernel32.dll"
    21  //go:cgo_import_dynamic runtime._CreateIoCompletionPort CreateIoCompletionPort%4 "kernel32.dll"
    22  //go:cgo_import_dynamic runtime._CreateThread CreateThread%6 "kernel32.dll"
    23  //go:cgo_import_dynamic runtime._CreateWaitableTimerA CreateWaitableTimerA%3 "kernel32.dll"
    24  //go:cgo_import_dynamic runtime._DuplicateHandle DuplicateHandle%7 "kernel32.dll"
    25  //go:cgo_import_dynamic runtime._ExitProcess ExitProcess%1 "kernel32.dll"
    26  //go:cgo_import_dynamic runtime._FreeEnvironmentStringsW FreeEnvironmentStringsW%1 "kernel32.dll"
    27  //go:cgo_import_dynamic runtime._GetConsoleMode GetConsoleMode%2 "kernel32.dll"
    28  //go:cgo_import_dynamic runtime._GetEnvironmentStringsW GetEnvironmentStringsW%0 "kernel32.dll"
    29  //go:cgo_import_dynamic runtime._GetProcAddress GetProcAddress%2 "kernel32.dll"
    30  //go:cgo_import_dynamic runtime._GetProcessAffinityMask GetProcessAffinityMask%3 "kernel32.dll"
    31  //go:cgo_import_dynamic runtime._GetQueuedCompletionStatus GetQueuedCompletionStatus%5 "kernel32.dll"
    32  //go:cgo_import_dynamic runtime._GetStdHandle GetStdHandle%1 "kernel32.dll"
    33  //go:cgo_import_dynamic runtime._GetSystemDirectoryA GetSystemDirectoryA%2 "kernel32.dll"
    34  //go:cgo_import_dynamic runtime._GetSystemInfo GetSystemInfo%1 "kernel32.dll"
    35  //go:cgo_import_dynamic runtime._GetThreadContext GetThreadContext%2 "kernel32.dll"
    36  //go:cgo_import_dynamic runtime._SetThreadContext SetThreadContext%2 "kernel32.dll"
    37  //go:cgo_import_dynamic runtime._LoadLibraryW LoadLibraryW%1 "kernel32.dll"
    38  //go:cgo_import_dynamic runtime._LoadLibraryA LoadLibraryA%1 "kernel32.dll"
    39  //go:cgo_import_dynamic runtime._PostQueuedCompletionStatus PostQueuedCompletionStatus%4 "kernel32.dll"
    40  //go:cgo_import_dynamic runtime._ResumeThread ResumeThread%1 "kernel32.dll"
    41  //go:cgo_import_dynamic runtime._SetConsoleCtrlHandler SetConsoleCtrlHandler%2 "kernel32.dll"
    42  //go:cgo_import_dynamic runtime._SetErrorMode SetErrorMode%1 "kernel32.dll"
    43  //go:cgo_import_dynamic runtime._SetEvent SetEvent%1 "kernel32.dll"
    44  //go:cgo_import_dynamic runtime._SetProcessPriorityBoost SetProcessPriorityBoost%2 "kernel32.dll"
    45  //go:cgo_import_dynamic runtime._SetThreadPriority SetThreadPriority%2 "kernel32.dll"
    46  //go:cgo_import_dynamic runtime._SetUnhandledExceptionFilter SetUnhandledExceptionFilter%1 "kernel32.dll"
    47  //go:cgo_import_dynamic runtime._SetWaitableTimer SetWaitableTimer%6 "kernel32.dll"
    48  //go:cgo_import_dynamic runtime._SuspendThread SuspendThread%1 "kernel32.dll"
    49  //go:cgo_import_dynamic runtime._SwitchToThread SwitchToThread%0 "kernel32.dll"
    50  //go:cgo_import_dynamic runtime._TlsAlloc TlsAlloc%0 "kernel32.dll"
    51  //go:cgo_import_dynamic runtime._VirtualAlloc VirtualAlloc%4 "kernel32.dll"
    52  //go:cgo_import_dynamic runtime._VirtualFree VirtualFree%3 "kernel32.dll"
    53  //go:cgo_import_dynamic runtime._VirtualQuery VirtualQuery%3 "kernel32.dll"
    54  //go:cgo_import_dynamic runtime._WaitForSingleObject WaitForSingleObject%2 "kernel32.dll"
    55  //go:cgo_import_dynamic runtime._WaitForMultipleObjects WaitForMultipleObjects%4 "kernel32.dll"
    56  //go:cgo_import_dynamic runtime._WriteConsoleW WriteConsoleW%5 "kernel32.dll"
    57  //go:cgo_import_dynamic runtime._WriteFile WriteFile%5 "kernel32.dll"
    58  
    59  type stdFunction unsafe.Pointer
    60  
    61  var (
    62  	// Following syscalls are available on every Windows PC.
    63  	// All these variables are set by the Windows executable
    64  	// loader before the Go program starts.
    65  	_AddVectoredExceptionHandler,
    66  	_CloseHandle,
    67  	_CreateEventA,
    68  	_CreateIoCompletionPort,
    69  	_CreateThread,
    70  	_CreateWaitableTimerA,
    71  	_DuplicateHandle,
    72  	_ExitProcess,
    73  	_FreeEnvironmentStringsW,
    74  	_GetConsoleMode,
    75  	_GetEnvironmentStringsW,
    76  	_GetProcAddress,
    77  	_GetProcessAffinityMask,
    78  	_GetQueuedCompletionStatus,
    79  	_GetStdHandle,
    80  	_GetSystemDirectoryA,
    81  	_GetSystemInfo,
    82  	_GetSystemTimeAsFileTime,
    83  	_GetThreadContext,
    84  	_SetThreadContext,
    85  	_LoadLibraryW,
    86  	_LoadLibraryA,
    87  	_PostQueuedCompletionStatus,
    88  	_QueryPerformanceCounter,
    89  	_QueryPerformanceFrequency,
    90  	_ResumeThread,
    91  	_SetConsoleCtrlHandler,
    92  	_SetErrorMode,
    93  	_SetEvent,
    94  	_SetProcessPriorityBoost,
    95  	_SetThreadPriority,
    96  	_SetUnhandledExceptionFilter,
    97  	_SetWaitableTimer,
    98  	_SuspendThread,
    99  	_SwitchToThread,
   100  	_TlsAlloc,
   101  	_VirtualAlloc,
   102  	_VirtualFree,
   103  	_VirtualQuery,
   104  	_WaitForSingleObject,
   105  	_WaitForMultipleObjects,
   106  	_WriteConsoleW,
   107  	_WriteFile,
   108  	_	stdFunction
   109  
   110  	// Following syscalls are only available on some Windows PCs.
   111  	// We will load syscalls, if available, before using them.
   112  	_AddDllDirectory,
   113  	_AddVectoredContinueHandler,
   114  	_GetQueuedCompletionStatusEx,
   115  	_LoadLibraryExA,
   116  	_LoadLibraryExW,
   117  	_	stdFunction
   118  
   119  	// Use RtlGenRandom to generate cryptographically random data.
   120  	// This approach has been recommended by Microsoft (see issue
   121  	// 15589 for details).
   122  	// The RtlGenRandom is not listed in advapi32.dll, instead
   123  	// RtlGenRandom function can be found by searching for SystemFunction036.
   124  	// Also some versions of Mingw cannot link to SystemFunction036
   125  	// when building executable as Cgo. So load SystemFunction036
   126  	// manually during runtime startup.
   127  	_RtlGenRandom	stdFunction
   128  
   129  	// Load ntdll.dll manually during startup, otherwise Mingw
   130  	// links wrong printf function to cgo executable (see issue
   131  	// 12030 for details).
   132  	_NtWaitForSingleObject	stdFunction
   133  
   134  	// These are from non-kernel32.dll, so we prefer to LoadLibraryEx them.
   135  	_timeBeginPeriod,
   136  	_timeEndPeriod,
   137  	_WSAGetOverlappedResult,
   138  	_	stdFunction
   139  )
   140  
   141  // Function to be called by windows CreateThread
   142  // to start new os thread.
   143  func tstart_stdcall(newm *m)
   144  
   145  // Called by OS using stdcall ABI.
   146  func ctrlhandler()
   147  
   148  type mOS struct {
   149  	threadLock	mutex	// protects "thread" and prevents closing
   150  	thread		uintptr	// thread handle
   151  
   152  	waitsema	uintptr	// semaphore for parking on locks
   153  	resumesema	uintptr	// semaphore to indicate suspend/resume
   154  
   155  	// preemptExtLock synchronizes preemptM with entry/exit from
   156  	// external C code.
   157  	//
   158  	// This protects against races between preemptM calling
   159  	// SuspendThread and external code on this thread calling
   160  	// ExitProcess. If these happen concurrently, it's possible to
   161  	// exit the suspending thread and suspend the exiting thread,
   162  	// leading to deadlock.
   163  	//
   164  	// 0 indicates this M is not being preempted or in external
   165  	// code. Entering external code CASes this from 0 to 1. If
   166  	// this fails, a preemption is in progress, so the thread must
   167  	// wait for the preemption. preemptM also CASes this from 0 to
   168  	// 1. If this fails, the preemption fails (as it would if the
   169  	// PC weren't in Go code). The value is reset to 0 when
   170  	// returning from external code or after a preemption is
   171  	// complete.
   172  	//
   173  	// TODO(austin): We may not need this if preemption were more
   174  	// tightly synchronized on the G/P status and preemption
   175  	// blocked transition into _Gsyscall/_Psyscall.
   176  	preemptExtLock	uint32
   177  }
   178  
   179  //go:linkname os_sigpipe os.sigpipe
   180  func os_sigpipe() {
   181  	throw("too many writes on closed pipe")
   182  }
   183  
   184  // Stubs so tests can link correctly. These should never be called.
   185  func open(name *byte, mode, perm int32) int32 {
   186  	throw("unimplemented")
   187  	return -1
   188  }
   189  func closefd(fd int32) int32 {
   190  	throw("unimplemented")
   191  	return -1
   192  }
   193  func read(fd int32, p unsafe.Pointer, n int32) int32 {
   194  	throw("unimplemented")
   195  	return -1
   196  }
   197  
   198  type sigset struct{}
   199  
   200  // Call a Windows function with stdcall conventions,
   201  // and switch to os stack during the call.
   202  func asmstdcall(fn unsafe.Pointer)
   203  
   204  var asmstdcallAddr unsafe.Pointer
   205  
   206  func windowsFindfunc(lib uintptr, name []byte) stdFunction {
   207  	if name[len(name)-1] != 0 {
   208  		throw("usage")
   209  	}
   210  	f := stdcall2(_GetProcAddress, lib, uintptr(unsafe.Pointer(&name[0])))
   211  	return stdFunction(unsafe.Pointer(f))
   212  }
   213  
   214  var sysDirectory [521]byte
   215  var sysDirectoryLen uintptr
   216  
   217  func windowsLoadSystemLib(name []byte) uintptr {
   218  	if useLoadLibraryEx {
   219  		return stdcall3(_LoadLibraryExA, uintptr(unsafe.Pointer(&name[0])), 0, _LOAD_LIBRARY_SEARCH_SYSTEM32)
   220  	} else {
   221  		if sysDirectoryLen == 0 {
   222  			l := stdcall2(_GetSystemDirectoryA, uintptr(unsafe.Pointer(&sysDirectory[0])), uintptr(len(sysDirectory)-1))
   223  			if l == 0 || l > uintptr(len(sysDirectory)-1) {
   224  				throw("Unable to determine system directory")
   225  			}
   226  			sysDirectory[l] = '\\'
   227  			sysDirectoryLen = l + 1
   228  		}
   229  		absName := append(sysDirectory[:sysDirectoryLen], name...)
   230  		return stdcall1(_LoadLibraryA, uintptr(unsafe.Pointer(&absName[0])))
   231  	}
   232  }
   233  
   234  func loadOptionalSyscalls() {
   235  	var kernel32dll = []byte("kernel32.dll\000")
   236  	k32 := stdcall1(_LoadLibraryA, uintptr(unsafe.Pointer(&kernel32dll[0])))
   237  	if k32 == 0 {
   238  		throw("kernel32.dll not found")
   239  	}
   240  	_AddDllDirectory = windowsFindfunc(k32, []byte("AddDllDirectory\000"))
   241  	_AddVectoredContinueHandler = windowsFindfunc(k32, []byte("AddVectoredContinueHandler\000"))
   242  	_GetQueuedCompletionStatusEx = windowsFindfunc(k32, []byte("GetQueuedCompletionStatusEx\000"))
   243  	_LoadLibraryExA = windowsFindfunc(k32, []byte("LoadLibraryExA\000"))
   244  	_LoadLibraryExW = windowsFindfunc(k32, []byte("LoadLibraryExW\000"))
   245  	useLoadLibraryEx = (_LoadLibraryExW != nil && _LoadLibraryExA != nil && _AddDllDirectory != nil)
   246  
   247  	var advapi32dll = []byte("advapi32.dll\000")
   248  	a32 := windowsLoadSystemLib(advapi32dll)
   249  	if a32 == 0 {
   250  		throw("advapi32.dll not found")
   251  	}
   252  	_RtlGenRandom = windowsFindfunc(a32, []byte("SystemFunction036\000"))
   253  
   254  	var ntdll = []byte("ntdll.dll\000")
   255  	n32 := windowsLoadSystemLib(ntdll)
   256  	if n32 == 0 {
   257  		throw("ntdll.dll not found")
   258  	}
   259  	_NtWaitForSingleObject = windowsFindfunc(n32, []byte("NtWaitForSingleObject\000"))
   260  
   261  	if GOARCH == "arm" {
   262  		_QueryPerformanceCounter = windowsFindfunc(k32, []byte("QueryPerformanceCounter\000"))
   263  		if _QueryPerformanceCounter == nil {
   264  			throw("could not find QPC syscalls")
   265  		}
   266  	}
   267  
   268  	var winmmdll = []byte("winmm.dll\000")
   269  	m32 := windowsLoadSystemLib(winmmdll)
   270  	if m32 == 0 {
   271  		throw("winmm.dll not found")
   272  	}
   273  	_timeBeginPeriod = windowsFindfunc(m32, []byte("timeBeginPeriod\000"))
   274  	_timeEndPeriod = windowsFindfunc(m32, []byte("timeEndPeriod\000"))
   275  	if _timeBeginPeriod == nil || _timeEndPeriod == nil {
   276  		throw("timeBegin/EndPeriod not found")
   277  	}
   278  
   279  	var ws232dll = []byte("ws2_32.dll\000")
   280  	ws232 := windowsLoadSystemLib(ws232dll)
   281  	if ws232 == 0 {
   282  		throw("ws2_32.dll not found")
   283  	}
   284  	_WSAGetOverlappedResult = windowsFindfunc(ws232, []byte("WSAGetOverlappedResult\000"))
   285  	if _WSAGetOverlappedResult == nil {
   286  		throw("WSAGetOverlappedResult not found")
   287  	}
   288  
   289  	if windowsFindfunc(n32, []byte("wine_get_version\000")) != nil {
   290  		// running on Wine
   291  		initWine(k32)
   292  	}
   293  }
   294  
   295  func monitorSuspendResume() {
   296  	const (
   297  		_DEVICE_NOTIFY_CALLBACK		= 2
   298  		_ERROR_FILE_NOT_FOUND		= 2
   299  		_ERROR_INVALID_PARAMETERS	= 87
   300  	)
   301  	type _DEVICE_NOTIFY_SUBSCRIBE_PARAMETERS struct {
   302  		callback	uintptr
   303  		context		uintptr
   304  	}
   305  
   306  	powrprof := windowsLoadSystemLib([]byte("powrprof.dll\000"))
   307  	if powrprof == 0 {
   308  		return	// Running on Windows 7, where we don't need it anyway.
   309  	}
   310  	powerRegisterSuspendResumeNotification := windowsFindfunc(powrprof, []byte("PowerRegisterSuspendResumeNotification\000"))
   311  	if powerRegisterSuspendResumeNotification == nil {
   312  		return	// Running on Windows 7, where we don't need it anyway.
   313  	}
   314  	var fn interface{} = func(context uintptr, changeType uint32, setting uintptr) uintptr {
   315  		for mp := (*m)(atomic.Loadp(unsafe.Pointer(&allm))); mp != nil; mp = mp.alllink {
   316  			if mp.resumesema != 0 {
   317  				stdcall1(_SetEvent, mp.resumesema)
   318  			}
   319  		}
   320  		return 0
   321  	}
   322  	params := _DEVICE_NOTIFY_SUBSCRIBE_PARAMETERS{
   323  		callback: compileCallback(*efaceOf(&fn), true),
   324  	}
   325  	handle := uintptr(0)
   326  	ret := stdcall3(powerRegisterSuspendResumeNotification, _DEVICE_NOTIFY_CALLBACK,
   327  		uintptr(unsafe.Pointer(&params)), uintptr(unsafe.Pointer(&handle)))
   328  	// This function doesn't use GetLastError(), so we use the return value directly.
   329  	switch ret {
   330  	case 0:
   331  		return	// Successful, nothing more to do.
   332  	case _ERROR_FILE_NOT_FOUND:
   333  		// Systems without access to the suspend/resume notifier
   334  		// also have their clock on "program time", and therefore
   335  		// don't want or need this anyway.
   336  		return
   337  	case _ERROR_INVALID_PARAMETERS:
   338  		// This is seen when running in Windows Docker.
   339  		// See issue 36557.
   340  		return
   341  	default:
   342  		println("runtime: PowerRegisterSuspendResumeNotification failed with errno=", ret)
   343  		throw("runtime: PowerRegisterSuspendResumeNotification failure")
   344  	}
   345  }
   346  
   347  //go:nosplit
   348  func getLoadLibrary() uintptr {
   349  	return uintptr(unsafe.Pointer(_LoadLibraryW))
   350  }
   351  
   352  //go:nosplit
   353  func getLoadLibraryEx() uintptr {
   354  	return uintptr(unsafe.Pointer(_LoadLibraryExW))
   355  }
   356  
   357  //go:nosplit
   358  func getGetProcAddress() uintptr {
   359  	return uintptr(unsafe.Pointer(_GetProcAddress))
   360  }
   361  
   362  func getproccount() int32 {
   363  	var mask, sysmask uintptr
   364  	ret := stdcall3(_GetProcessAffinityMask, currentProcess, uintptr(unsafe.Pointer(&mask)), uintptr(unsafe.Pointer(&sysmask)))
   365  	if ret != 0 {
   366  		n := 0
   367  		maskbits := int(unsafe.Sizeof(mask) * 8)
   368  		for i := 0; i < maskbits; i++ {
   369  			if mask&(1<<uint(i)) != 0 {
   370  				n++
   371  			}
   372  		}
   373  		if n != 0 {
   374  			return int32(n)
   375  		}
   376  	}
   377  	// use GetSystemInfo if GetProcessAffinityMask fails
   378  	var info systeminfo
   379  	stdcall1(_GetSystemInfo, uintptr(unsafe.Pointer(&info)))
   380  	return int32(info.dwnumberofprocessors)
   381  }
   382  
   383  func getPageSize() uintptr {
   384  	var info systeminfo
   385  	stdcall1(_GetSystemInfo, uintptr(unsafe.Pointer(&info)))
   386  	return uintptr(info.dwpagesize)
   387  }
   388  
   389  const (
   390  	currentProcess	= ^uintptr(0)	// -1 = current process
   391  	currentThread	= ^uintptr(1)	// -2 = current thread
   392  )
   393  
   394  // in sys_windows_386.s and sys_windows_amd64.s:
   395  func externalthreadhandler()
   396  func getlasterror() uint32
   397  func setlasterror(err uint32)
   398  
   399  // When loading DLLs, we prefer to use LoadLibraryEx with
   400  // LOAD_LIBRARY_SEARCH_* flags, if available. LoadLibraryEx is not
   401  // available on old Windows, though, and the LOAD_LIBRARY_SEARCH_*
   402  // flags are not available on some versions of Windows without a
   403  // security patch.
   404  //
   405  // https://msdn.microsoft.com/en-us/library/ms684179(v=vs.85).aspx says:
   406  // "Windows 7, Windows Server 2008 R2, Windows Vista, and Windows
   407  // Server 2008: The LOAD_LIBRARY_SEARCH_* flags are available on
   408  // systems that have KB2533623 installed. To determine whether the
   409  // flags are available, use GetProcAddress to get the address of the
   410  // AddDllDirectory, RemoveDllDirectory, or SetDefaultDllDirectories
   411  // function. If GetProcAddress succeeds, the LOAD_LIBRARY_SEARCH_*
   412  // flags can be used with LoadLibraryEx."
   413  var useLoadLibraryEx bool
   414  
   415  var timeBeginPeriodRetValue uint32
   416  
   417  // osRelaxMinNS indicates that sysmon shouldn't osRelax if the next
   418  // timer is less than 60 ms from now. Since osRelaxing may reduce
   419  // timer resolution to 15.6 ms, this keeps timer error under roughly 1
   420  // part in 4.
   421  const osRelaxMinNS = 60 * 1e6
   422  
   423  // osRelax is called by the scheduler when transitioning to and from
   424  // all Ps being idle.
   425  //
   426  // On Windows, it adjusts the system-wide timer resolution. Go needs a
   427  // high resolution timer while running and there's little extra cost
   428  // if we're already using the CPU, but if all Ps are idle there's no
   429  // need to consume extra power to drive the high-res timer.
   430  func osRelax(relax bool) uint32 {
   431  	if relax {
   432  		return uint32(stdcall1(_timeEndPeriod, 1))
   433  	} else {
   434  		return uint32(stdcall1(_timeBeginPeriod, 1))
   435  	}
   436  }
   437  
   438  func osinit() {
   439  	asmstdcallAddr = unsafe.Pointer(funcPC(asmstdcall))
   440  	usleep2Addr = unsafe.Pointer(funcPC(usleep2))
   441  	switchtothreadAddr = unsafe.Pointer(funcPC(switchtothread))
   442  
   443  	setBadSignalMsg()
   444  
   445  	loadOptionalSyscalls()
   446  
   447  	disableWER()
   448  
   449  	initExceptionHandler()
   450  
   451  	stdcall2(_SetConsoleCtrlHandler, funcPC(ctrlhandler), 1)
   452  
   453  	timeBeginPeriodRetValue = osRelax(false)
   454  
   455  	ncpu = getproccount()
   456  
   457  	physPageSize = getPageSize()
   458  
   459  	// Windows dynamic priority boosting assumes that a process has different types
   460  	// of dedicated threads -- GUI, IO, computational, etc. Go processes use
   461  	// equivalent threads that all do a mix of GUI, IO, computations, etc.
   462  	// In such context dynamic priority boosting does nothing but harm, so we turn it off.
   463  	stdcall2(_SetProcessPriorityBoost, currentProcess, 1)
   464  }
   465  
   466  // useQPCTime controls whether time.now and nanotime use QueryPerformanceCounter.
   467  // This is only set to 1 when running under Wine.
   468  var useQPCTime uint8
   469  
   470  var qpcStartCounter int64
   471  var qpcMultiplier int64
   472  
   473  //go:nosplit
   474  func nanotimeQPC() int64 {
   475  	var counter int64 = 0
   476  	stdcall1(_QueryPerformanceCounter, uintptr(unsafe.Pointer(&counter)))
   477  
   478  	// returns number of nanoseconds
   479  	return (counter - qpcStartCounter) * qpcMultiplier
   480  }
   481  
   482  //go:nosplit
   483  func nowQPC() (sec int64, nsec int32, mono int64) {
   484  	var ft int64
   485  	stdcall1(_GetSystemTimeAsFileTime, uintptr(unsafe.Pointer(&ft)))
   486  
   487  	t := (ft - 116444736000000000) * 100
   488  
   489  	sec = t / 1000000000
   490  	nsec = int32(t - sec*1000000000)
   491  
   492  	mono = nanotimeQPC()
   493  	return
   494  }
   495  
   496  func initWine(k32 uintptr) {
   497  	_GetSystemTimeAsFileTime = windowsFindfunc(k32, []byte("GetSystemTimeAsFileTime\000"))
   498  	if _GetSystemTimeAsFileTime == nil {
   499  		throw("could not find GetSystemTimeAsFileTime() syscall")
   500  	}
   501  
   502  	_QueryPerformanceCounter = windowsFindfunc(k32, []byte("QueryPerformanceCounter\000"))
   503  	_QueryPerformanceFrequency = windowsFindfunc(k32, []byte("QueryPerformanceFrequency\000"))
   504  	if _QueryPerformanceCounter == nil || _QueryPerformanceFrequency == nil {
   505  		throw("could not find QPC syscalls")
   506  	}
   507  
   508  	// We can not simply fallback to GetSystemTimeAsFileTime() syscall, since its time is not monotonic,
   509  	// instead we use QueryPerformanceCounter family of syscalls to implement monotonic timer
   510  	// https://msdn.microsoft.com/en-us/library/windows/desktop/dn553408(v=vs.85).aspx
   511  
   512  	var tmp int64
   513  	stdcall1(_QueryPerformanceFrequency, uintptr(unsafe.Pointer(&tmp)))
   514  	if tmp == 0 {
   515  		throw("QueryPerformanceFrequency syscall returned zero, running on unsupported hardware")
   516  	}
   517  
   518  	// This should not overflow, it is a number of ticks of the performance counter per second,
   519  	// its resolution is at most 10 per usecond (on Wine, even smaller on real hardware), so it will be at most 10 millions here,
   520  	// panic if overflows.
   521  	if tmp > (1<<31 - 1) {
   522  		throw("QueryPerformanceFrequency overflow 32 bit divider, check nosplit discussion to proceed")
   523  	}
   524  	qpcFrequency := int32(tmp)
   525  	stdcall1(_QueryPerformanceCounter, uintptr(unsafe.Pointer(&qpcStartCounter)))
   526  
   527  	// Since we are supposed to run this time calls only on Wine, it does not lose precision,
   528  	// since Wine's timer is kind of emulated at 10 Mhz, so it will be a nice round multiplier of 100
   529  	// but for general purpose system (like 3.3 Mhz timer on i7) it will not be very precise.
   530  	// We have to do it this way (or similar), since multiplying QPC counter by 100 millions overflows
   531  	// int64 and resulted time will always be invalid.
   532  	qpcMultiplier = int64(timediv(1000000000, qpcFrequency, nil))
   533  
   534  	useQPCTime = 1
   535  }
   536  
   537  //go:nosplit
   538  func getRandomData(r []byte) {
   539  	n := 0
   540  	if stdcall2(_RtlGenRandom, uintptr(unsafe.Pointer(&r[0])), uintptr(len(r)))&0xff != 0 {
   541  		n = len(r)
   542  	}
   543  	extendRandom(r, n)
   544  }
   545  
   546  func goenvs() {
   547  	// strings is a pointer to environment variable pairs in the form:
   548  	//     "envA=valA\x00envB=valB\x00\x00" (in UTF-16)
   549  	// Two consecutive zero bytes end the list.
   550  	strings := unsafe.Pointer(stdcall0(_GetEnvironmentStringsW))
   551  	p := (*[1 << 24]uint16)(strings)[:]
   552  
   553  	n := 0
   554  	for from, i := 0, 0; true; i++ {
   555  		if p[i] == 0 {
   556  			// empty string marks the end
   557  			if i == from {
   558  				break
   559  			}
   560  			from = i + 1
   561  			n++
   562  		}
   563  	}
   564  	envs = make([]string, n)
   565  
   566  	for i := range envs {
   567  		envs[i] = gostringw(&p[0])
   568  		for p[0] != 0 {
   569  			p = p[1:]
   570  		}
   571  		p = p[1:]	// skip nil byte
   572  	}
   573  
   574  	stdcall1(_FreeEnvironmentStringsW, uintptr(strings))
   575  
   576  	// We call this all the way here, late in init, so that malloc works
   577  	// for the callback function this generates.
   578  	monitorSuspendResume()
   579  }
   580  
   581  // exiting is set to non-zero when the process is exiting.
   582  var exiting uint32
   583  
   584  //go:nosplit
   585  func exit(code int32) {
   586  	// Disallow thread suspension for preemption. Otherwise,
   587  	// ExitProcess and SuspendThread can race: SuspendThread
   588  	// queues a suspension request for this thread, ExitProcess
   589  	// kills the suspending thread, and then this thread suspends.
   590  	lock(&suspendLock)
   591  	atomic.Store(&exiting, 1)
   592  	stdcall1(_ExitProcess, uintptr(code))
   593  }
   594  
   595  // write1 must be nosplit because it's used as a last resort in
   596  // functions like badmorestackg0. In such cases, we'll always take the
   597  // ASCII path.
   598  //
   599  //go:nosplit
   600  func write1(fd uintptr, buf unsafe.Pointer, n int32) int32 {
   601  	const (
   602  		_STD_OUTPUT_HANDLE	= ^uintptr(10)	// -11
   603  		_STD_ERROR_HANDLE	= ^uintptr(11)	// -12
   604  	)
   605  	var handle uintptr
   606  	switch fd {
   607  	case 1:
   608  		handle = stdcall1(_GetStdHandle, _STD_OUTPUT_HANDLE)
   609  	case 2:
   610  		handle = stdcall1(_GetStdHandle, _STD_ERROR_HANDLE)
   611  	default:
   612  		// assume fd is real windows handle.
   613  		handle = fd
   614  	}
   615  	isASCII := true
   616  	b := (*[1 << 30]byte)(buf)[:n]
   617  	for _, x := range b {
   618  		if x >= 0x80 {
   619  			isASCII = false
   620  			break
   621  		}
   622  	}
   623  
   624  	if !isASCII {
   625  		var m uint32
   626  		isConsole := stdcall2(_GetConsoleMode, handle, uintptr(unsafe.Pointer(&m))) != 0
   627  		// If this is a console output, various non-unicode code pages can be in use.
   628  		// Use the dedicated WriteConsole call to ensure unicode is printed correctly.
   629  		if isConsole {
   630  			return int32(writeConsole(handle, buf, n))
   631  		}
   632  	}
   633  	var written uint32
   634  	stdcall5(_WriteFile, handle, uintptr(buf), uintptr(n), uintptr(unsafe.Pointer(&written)), 0)
   635  	return int32(written)
   636  }
   637  
   638  var (
   639  	utf16ConsoleBack	[1000]uint16
   640  	utf16ConsoleBackLock	mutex
   641  )
   642  
   643  // writeConsole writes bufLen bytes from buf to the console File.
   644  // It returns the number of bytes written.
   645  func writeConsole(handle uintptr, buf unsafe.Pointer, bufLen int32) int {
   646  	const surr2 = (surrogateMin + surrogateMax + 1) / 2
   647  
   648  	// Do not use defer for unlock. May cause issues when printing a panic.
   649  	lock(&utf16ConsoleBackLock)
   650  
   651  	b := (*[1 << 30]byte)(buf)[:bufLen]
   652  	s := *(*string)(unsafe.Pointer(&b))
   653  
   654  	utf16tmp := utf16ConsoleBack[:]
   655  
   656  	total := len(s)
   657  	w := 0
   658  	for _, r := range s {
   659  		if w >= len(utf16tmp)-2 {
   660  			writeConsoleUTF16(handle, utf16tmp[:w])
   661  			w = 0
   662  		}
   663  		if r < 0x10000 {
   664  			utf16tmp[w] = uint16(r)
   665  			w++
   666  		} else {
   667  			r -= 0x10000
   668  			utf16tmp[w] = surrogateMin + uint16(r>>10)&0x3ff
   669  			utf16tmp[w+1] = surr2 + uint16(r)&0x3ff
   670  			w += 2
   671  		}
   672  	}
   673  	writeConsoleUTF16(handle, utf16tmp[:w])
   674  	unlock(&utf16ConsoleBackLock)
   675  	return total
   676  }
   677  
   678  // writeConsoleUTF16 is the dedicated windows calls that correctly prints
   679  // to the console regardless of the current code page. Input is utf-16 code points.
   680  // The handle must be a console handle.
   681  func writeConsoleUTF16(handle uintptr, b []uint16) {
   682  	l := uint32(len(b))
   683  	if l == 0 {
   684  		return
   685  	}
   686  	var written uint32
   687  	stdcall5(_WriteConsoleW,
   688  		handle,
   689  		uintptr(unsafe.Pointer(&b[0])),
   690  		uintptr(l),
   691  		uintptr(unsafe.Pointer(&written)),
   692  		0,
   693  	)
   694  	return
   695  }
   696  
   697  // walltime1 isn't implemented on Windows, but will never be called.
   698  func walltime1() (sec int64, nsec int32)
   699  
   700  //go:nosplit
   701  func semasleep(ns int64) int32 {
   702  	const (
   703  		_WAIT_ABANDONED	= 0x00000080
   704  		_WAIT_OBJECT_0	= 0x00000000
   705  		_WAIT_TIMEOUT	= 0x00000102
   706  		_WAIT_FAILED	= 0xFFFFFFFF
   707  	)
   708  
   709  	var result uintptr
   710  	if ns < 0 {
   711  		result = stdcall2(_WaitForSingleObject, getg().m.waitsema, uintptr(_INFINITE))
   712  	} else {
   713  		start := nanotime()
   714  		elapsed := int64(0)
   715  		for {
   716  			ms := int64(timediv(ns-elapsed, 1000000, nil))
   717  			if ms == 0 {
   718  				ms = 1
   719  			}
   720  			result = stdcall4(_WaitForMultipleObjects, 2,
   721  				uintptr(unsafe.Pointer(&[2]uintptr{getg().m.waitsema, getg().m.resumesema})),
   722  				0, uintptr(ms))
   723  			if result != _WAIT_OBJECT_0+1 {
   724  				// Not a suspend/resume event
   725  				break
   726  			}
   727  			elapsed = nanotime() - start
   728  			if elapsed >= ns {
   729  				return -1
   730  			}
   731  		}
   732  	}
   733  	switch result {
   734  	case _WAIT_OBJECT_0:	// Signaled
   735  		return 0
   736  
   737  	case _WAIT_TIMEOUT:
   738  		return -1
   739  
   740  	case _WAIT_ABANDONED:
   741  		systemstack(func() {
   742  			throw("runtime.semasleep wait_abandoned")
   743  		})
   744  
   745  	case _WAIT_FAILED:
   746  		systemstack(func() {
   747  			print("runtime: waitforsingleobject wait_failed; errno=", getlasterror(), "\n")
   748  			throw("runtime.semasleep wait_failed")
   749  		})
   750  
   751  	default:
   752  		systemstack(func() {
   753  			print("runtime: waitforsingleobject unexpected; result=", result, "\n")
   754  			throw("runtime.semasleep unexpected")
   755  		})
   756  	}
   757  
   758  	return -1	// unreachable
   759  }
   760  
   761  //go:nosplit
   762  func semawakeup(mp *m) {
   763  	if stdcall1(_SetEvent, mp.waitsema) == 0 {
   764  		systemstack(func() {
   765  			print("runtime: setevent failed; errno=", getlasterror(), "\n")
   766  			throw("runtime.semawakeup")
   767  		})
   768  	}
   769  }
   770  
   771  //go:nosplit
   772  func semacreate(mp *m) {
   773  	if mp.waitsema != 0 {
   774  		return
   775  	}
   776  	mp.waitsema = stdcall4(_CreateEventA, 0, 0, 0, 0)
   777  	if mp.waitsema == 0 {
   778  		systemstack(func() {
   779  			print("runtime: createevent failed; errno=", getlasterror(), "\n")
   780  			throw("runtime.semacreate")
   781  		})
   782  	}
   783  	mp.resumesema = stdcall4(_CreateEventA, 0, 0, 0, 0)
   784  	if mp.resumesema == 0 {
   785  		systemstack(func() {
   786  			print("runtime: createevent failed; errno=", getlasterror(), "\n")
   787  			throw("runtime.semacreate")
   788  		})
   789  		stdcall1(_CloseHandle, mp.waitsema)
   790  		mp.waitsema = 0
   791  	}
   792  }
   793  
   794  // May run with m.p==nil, so write barriers are not allowed. This
   795  // function is called by newosproc0, so it is also required to
   796  // operate without stack guards.
   797  //go:nowritebarrierrec
   798  //go:nosplit
   799  func newosproc(mp *m) {
   800  	// We pass 0 for the stack size to use the default for this binary.
   801  	thandle := stdcall6(_CreateThread, 0, 0,
   802  		funcPC(tstart_stdcall), uintptr(unsafe.Pointer(mp)),
   803  		0, 0)
   804  
   805  	if thandle == 0 {
   806  		if atomic.Load(&exiting) != 0 {
   807  			// CreateThread may fail if called
   808  			// concurrently with ExitProcess. If this
   809  			// happens, just freeze this thread and let
   810  			// the process exit. See issue #18253.
   811  			lock(&deadlock)
   812  			lock(&deadlock)
   813  		}
   814  		print("runtime: failed to create new OS thread (have ", mcount(), " already; errno=", getlasterror(), ")\n")
   815  		throw("runtime.newosproc")
   816  	}
   817  
   818  	// Close thandle to avoid leaking the thread object if it exits.
   819  	stdcall1(_CloseHandle, thandle)
   820  }
   821  
   822  // Used by the C library build mode. On Linux this function would allocate a
   823  // stack, but that's not necessary for Windows. No stack guards are present
   824  // and the GC has not been initialized, so write barriers will fail.
   825  //go:nowritebarrierrec
   826  //go:nosplit
   827  func newosproc0(mp *m, stk unsafe.Pointer) {
   828  	// TODO: this is completely broken. The args passed to newosproc0 (in asm_amd64.s)
   829  	// are stacksize and function, not *m and stack.
   830  	// Check os_linux.go for an implementation that might actually work.
   831  	throw("bad newosproc0")
   832  }
   833  
   834  func exitThread(wait *uint32) {
   835  	// We should never reach exitThread on Windows because we let
   836  	// the OS clean up threads.
   837  	throw("exitThread")
   838  }
   839  
   840  // Called to initialize a new m (including the bootstrap m).
   841  // Called on the parent thread (main thread in case of bootstrap), can allocate memory.
   842  func mpreinit(mp *m) {
   843  }
   844  
   845  //go:nosplit
   846  func msigsave(mp *m) {
   847  }
   848  
   849  //go:nosplit
   850  func msigrestore(sigmask sigset) {
   851  }
   852  
   853  //go:nosplit
   854  //go:nowritebarrierrec
   855  func clearSignalHandlers() {
   856  }
   857  
   858  //go:nosplit
   859  func sigblock() {
   860  }
   861  
   862  // Called to initialize a new m (including the bootstrap m).
   863  // Called on the new thread, cannot allocate memory.
   864  func minit() {
   865  	var thandle uintptr
   866  	stdcall7(_DuplicateHandle, currentProcess, currentThread, currentProcess, uintptr(unsafe.Pointer(&thandle)), 0, 0, _DUPLICATE_SAME_ACCESS)
   867  
   868  	mp := getg().m
   869  	lock(&mp.threadLock)
   870  	mp.thread = thandle
   871  	unlock(&mp.threadLock)
   872  
   873  	// Query the true stack base from the OS. Currently we're
   874  	// running on a small assumed stack.
   875  	var mbi memoryBasicInformation
   876  	res := stdcall3(_VirtualQuery, uintptr(unsafe.Pointer(&mbi)), uintptr(unsafe.Pointer(&mbi)), unsafe.Sizeof(mbi))
   877  	if res == 0 {
   878  		print("runtime: VirtualQuery failed; errno=", getlasterror(), "\n")
   879  		throw("VirtualQuery for stack base failed")
   880  	}
   881  	// The system leaves an 8K PAGE_GUARD region at the bottom of
   882  	// the stack (in theory VirtualQuery isn't supposed to include
   883  	// that, but it does). Add an additional 8K of slop for
   884  	// calling C functions that don't have stack checks and for
   885  	// lastcontinuehandler. We shouldn't be anywhere near this
   886  	// bound anyway.
   887  	base := mbi.allocationBase + 16<<10
   888  	// Sanity check the stack bounds.
   889  	g0 := getg()
   890  	if base > g0.stack.hi || g0.stack.hi-base > 64<<20 {
   891  		print("runtime: g0 stack [", hex(base), ",", hex(g0.stack.hi), ")\n")
   892  		throw("bad g0 stack")
   893  	}
   894  	g0.stack.lo = base
   895  	g0.stackguard0 = g0.stack.lo + _StackGuard
   896  	g0.stackguard1 = g0.stackguard0
   897  	// Sanity check the SP.
   898  	stackcheck()
   899  }
   900  
   901  // Called from dropm to undo the effect of an minit.
   902  //go:nosplit
   903  func unminit() {
   904  	mp := getg().m
   905  	lock(&mp.threadLock)
   906  	stdcall1(_CloseHandle, mp.thread)
   907  	mp.thread = 0
   908  	unlock(&mp.threadLock)
   909  }
   910  
   911  // Calling stdcall on os stack.
   912  // May run during STW, so write barriers are not allowed.
   913  //go:nowritebarrier
   914  //go:nosplit
   915  func stdcall(fn stdFunction) uintptr {
   916  	gp := getg()
   917  	mp := gp.m
   918  	mp.libcall.fn = uintptr(unsafe.Pointer(fn))
   919  	resetLibcall := false
   920  	if mp.profilehz != 0 && mp.libcallsp == 0 {
   921  		// leave pc/sp for cpu profiler
   922  		mp.libcallg.set(gp)
   923  		mp.libcallpc = getcallerpc()
   924  		// sp must be the last, because once async cpu profiler finds
   925  		// all three values to be non-zero, it will use them
   926  		mp.libcallsp = getcallersp()
   927  		resetLibcall = true	// See comment in sys_darwin.go:libcCall
   928  	}
   929  	asmcgocall(asmstdcallAddr, unsafe.Pointer(&mp.libcall))
   930  	if resetLibcall {
   931  		mp.libcallsp = 0
   932  	}
   933  	return mp.libcall.r1
   934  }
   935  
   936  //go:nosplit
   937  func stdcall0(fn stdFunction) uintptr {
   938  	mp := getg().m
   939  	mp.libcall.n = 0
   940  	mp.libcall.args = uintptr(noescape(unsafe.Pointer(&fn)))	// it's unused but must be non-nil, otherwise crashes
   941  	return stdcall(fn)
   942  }
   943  
   944  //go:nosplit
   945  func stdcall1(fn stdFunction, a0 uintptr) uintptr {
   946  	mp := getg().m
   947  	mp.libcall.n = 1
   948  	mp.libcall.args = uintptr(noescape(unsafe.Pointer(&a0)))
   949  	return stdcall(fn)
   950  }
   951  
   952  //go:nosplit
   953  func stdcall2(fn stdFunction, a0, a1 uintptr) uintptr {
   954  	mp := getg().m
   955  	mp.libcall.n = 2
   956  	mp.libcall.args = uintptr(noescape(unsafe.Pointer(&a0)))
   957  	return stdcall(fn)
   958  }
   959  
   960  //go:nosplit
   961  func stdcall3(fn stdFunction, a0, a1, a2 uintptr) uintptr {
   962  	mp := getg().m
   963  	mp.libcall.n = 3
   964  	mp.libcall.args = uintptr(noescape(unsafe.Pointer(&a0)))
   965  	return stdcall(fn)
   966  }
   967  
   968  //go:nosplit
   969  func stdcall4(fn stdFunction, a0, a1, a2, a3 uintptr) uintptr {
   970  	mp := getg().m
   971  	mp.libcall.n = 4
   972  	mp.libcall.args = uintptr(noescape(unsafe.Pointer(&a0)))
   973  	return stdcall(fn)
   974  }
   975  
   976  //go:nosplit
   977  func stdcall5(fn stdFunction, a0, a1, a2, a3, a4 uintptr) uintptr {
   978  	mp := getg().m
   979  	mp.libcall.n = 5
   980  	mp.libcall.args = uintptr(noescape(unsafe.Pointer(&a0)))
   981  	return stdcall(fn)
   982  }
   983  
   984  //go:nosplit
   985  func stdcall6(fn stdFunction, a0, a1, a2, a3, a4, a5 uintptr) uintptr {
   986  	mp := getg().m
   987  	mp.libcall.n = 6
   988  	mp.libcall.args = uintptr(noescape(unsafe.Pointer(&a0)))
   989  	return stdcall(fn)
   990  }
   991  
   992  //go:nosplit
   993  func stdcall7(fn stdFunction, a0, a1, a2, a3, a4, a5, a6 uintptr) uintptr {
   994  	mp := getg().m
   995  	mp.libcall.n = 7
   996  	mp.libcall.args = uintptr(noescape(unsafe.Pointer(&a0)))
   997  	return stdcall(fn)
   998  }
   999  
  1000  // in sys_windows_386.s and sys_windows_amd64.s
  1001  func onosstack(fn unsafe.Pointer, arg uint32)
  1002  func usleep2(usec uint32)
  1003  func switchtothread()
  1004  
  1005  var usleep2Addr unsafe.Pointer
  1006  var switchtothreadAddr unsafe.Pointer
  1007  
  1008  //go:nosplit
  1009  func osyield() {
  1010  	onosstack(switchtothreadAddr, 0)
  1011  }
  1012  
  1013  //go:nosplit
  1014  func usleep(us uint32) {
  1015  	// Have 1us units; want 100ns units.
  1016  	onosstack(usleep2Addr, 10*us)
  1017  }
  1018  
  1019  func ctrlhandler1(_type uint32) uint32 {
  1020  	var s uint32
  1021  
  1022  	switch _type {
  1023  	case _CTRL_C_EVENT, _CTRL_BREAK_EVENT:
  1024  		s = _SIGINT
  1025  	case _CTRL_CLOSE_EVENT, _CTRL_LOGOFF_EVENT, _CTRL_SHUTDOWN_EVENT:
  1026  		s = _SIGTERM
  1027  	default:
  1028  		return 0
  1029  	}
  1030  
  1031  	if sigsend(s) {
  1032  		return 1
  1033  	}
  1034  	exit(2)	// SIGINT, SIGTERM, etc
  1035  	return 0
  1036  }
  1037  
  1038  // in sys_windows_386.s and sys_windows_amd64.s
  1039  func profileloop()
  1040  
  1041  // called from zcallback_windows_*.s to sys_windows_*.s
  1042  func callbackasm1()
  1043  
  1044  var profiletimer uintptr
  1045  
  1046  func profilem(mp *m, thread uintptr) {
  1047  	var r *context
  1048  	rbuf := make([]byte, unsafe.Sizeof(*r)+15)
  1049  
  1050  	// align Context to 16 bytes
  1051  	r = (*context)(unsafe.Pointer((uintptr(unsafe.Pointer(&rbuf[15]))) &^ 15))
  1052  	r.contextflags = _CONTEXT_CONTROL
  1053  	stdcall2(_GetThreadContext, thread, uintptr(unsafe.Pointer(r)))
  1054  
  1055  	gp := gFromTLS(mp)
  1056  
  1057  	sigprof(r.ip(), r.sp(), r.lr(), gp, mp)
  1058  }
  1059  
  1060  func gFromTLS(mp *m) *g {
  1061  	switch GOARCH {
  1062  	case "arm":
  1063  		tls := &mp.tls[0]
  1064  		return **((***g)(unsafe.Pointer(tls)))
  1065  	case "386", "amd64":
  1066  		tls := &mp.tls[0]
  1067  		return *((**g)(unsafe.Pointer(tls)))
  1068  	}
  1069  	throw("unsupported architecture")
  1070  	return nil
  1071  }
  1072  
  1073  func profileloop1(param uintptr) uint32 {
  1074  	stdcall2(_SetThreadPriority, currentThread, _THREAD_PRIORITY_HIGHEST)
  1075  
  1076  	for {
  1077  		stdcall2(_WaitForSingleObject, profiletimer, _INFINITE)
  1078  		first := (*m)(atomic.Loadp(unsafe.Pointer(&allm)))
  1079  		for mp := first; mp != nil; mp = mp.alllink {
  1080  			lock(&mp.threadLock)
  1081  			// Do not profile threads blocked on Notes,
  1082  			// this includes idle worker threads,
  1083  			// idle timer thread, idle heap scavenger, etc.
  1084  			if mp.thread == 0 || mp.profilehz == 0 || mp.blocked {
  1085  				unlock(&mp.threadLock)
  1086  				continue
  1087  			}
  1088  			// Acquire our own handle to the thread.
  1089  			var thread uintptr
  1090  			stdcall7(_DuplicateHandle, currentProcess, mp.thread, currentProcess, uintptr(unsafe.Pointer(&thread)), 0, 0, _DUPLICATE_SAME_ACCESS)
  1091  			unlock(&mp.threadLock)
  1092  			// mp may exit between the DuplicateHandle
  1093  			// above and the SuspendThread. The handle
  1094  			// will remain valid, but SuspendThread may
  1095  			// fail.
  1096  			if int32(stdcall1(_SuspendThread, thread)) == -1 {
  1097  				// The thread no longer exists.
  1098  				stdcall1(_CloseHandle, thread)
  1099  				continue
  1100  			}
  1101  			if mp.profilehz != 0 && !mp.blocked {
  1102  				// Pass the thread handle in case mp
  1103  				// was in the process of shutting down.
  1104  				profilem(mp, thread)
  1105  			}
  1106  			stdcall1(_ResumeThread, thread)
  1107  			stdcall1(_CloseHandle, thread)
  1108  		}
  1109  	}
  1110  }
  1111  
  1112  func setProcessCPUProfiler(hz int32) {
  1113  	if profiletimer == 0 {
  1114  		timer := stdcall3(_CreateWaitableTimerA, 0, 0, 0)
  1115  		atomic.Storeuintptr(&profiletimer, timer)
  1116  		thread := stdcall6(_CreateThread, 0, 0, funcPC(profileloop), 0, 0, 0)
  1117  		stdcall2(_SetThreadPriority, thread, _THREAD_PRIORITY_HIGHEST)
  1118  		stdcall1(_CloseHandle, thread)
  1119  	}
  1120  }
  1121  
  1122  func setThreadCPUProfiler(hz int32) {
  1123  	ms := int32(0)
  1124  	due := ^int64(^uint64(1 << 63))
  1125  	if hz > 0 {
  1126  		ms = 1000 / hz
  1127  		if ms == 0 {
  1128  			ms = 1
  1129  		}
  1130  		due = int64(ms) * -10000
  1131  	}
  1132  	stdcall6(_SetWaitableTimer, profiletimer, uintptr(unsafe.Pointer(&due)), uintptr(ms), 0, 0, 0)
  1133  	atomic.Store((*uint32)(unsafe.Pointer(&getg().m.profilehz)), uint32(hz))
  1134  }
  1135  
  1136  const preemptMSupported = GOARCH != "arm"
  1137  
  1138  // suspendLock protects simultaneous SuspendThread operations from
  1139  // suspending each other.
  1140  var suspendLock mutex
  1141  
  1142  func preemptM(mp *m) {
  1143  	if GOARCH == "arm" {
  1144  		// TODO: Implement call injection
  1145  		return
  1146  	}
  1147  
  1148  	if mp == getg().m {
  1149  		throw("self-preempt")
  1150  	}
  1151  
  1152  	// Synchronize with external code that may try to ExitProcess.
  1153  	if !atomic.Cas(&mp.preemptExtLock, 0, 1) {
  1154  		// External code is running. Fail the preemption
  1155  		// attempt.
  1156  		atomic.Xadd(&mp.preemptGen, 1)
  1157  		return
  1158  	}
  1159  
  1160  	// Acquire our own handle to mp's thread.
  1161  	lock(&mp.threadLock)
  1162  	if mp.thread == 0 {
  1163  		// The M hasn't been minit'd yet (or was just unminit'd).
  1164  		unlock(&mp.threadLock)
  1165  		atomic.Store(&mp.preemptExtLock, 0)
  1166  		atomic.Xadd(&mp.preemptGen, 1)
  1167  		return
  1168  	}
  1169  	var thread uintptr
  1170  	stdcall7(_DuplicateHandle, currentProcess, mp.thread, currentProcess, uintptr(unsafe.Pointer(&thread)), 0, 0, _DUPLICATE_SAME_ACCESS)
  1171  	unlock(&mp.threadLock)
  1172  
  1173  	// Prepare thread context buffer.
  1174  	var c *context
  1175  	cbuf := make([]byte, unsafe.Sizeof(*c)+15)
  1176  	// Align Context to 16 bytes.
  1177  	c = (*context)(unsafe.Pointer((uintptr(unsafe.Pointer(&cbuf[15]))) &^ 15))
  1178  	c.contextflags = _CONTEXT_CONTROL
  1179  
  1180  	// Serialize thread suspension. SuspendThread is asynchronous,
  1181  	// so it's otherwise possible for two threads to suspend each
  1182  	// other and deadlock. We must hold this lock until after
  1183  	// GetThreadContext, since that blocks until the thread is
  1184  	// actually suspended.
  1185  	lock(&suspendLock)
  1186  
  1187  	// Suspend the thread.
  1188  	if int32(stdcall1(_SuspendThread, thread)) == -1 {
  1189  		unlock(&suspendLock)
  1190  		stdcall1(_CloseHandle, thread)
  1191  		atomic.Store(&mp.preemptExtLock, 0)
  1192  		// The thread no longer exists. This shouldn't be
  1193  		// possible, but just acknowledge the request.
  1194  		atomic.Xadd(&mp.preemptGen, 1)
  1195  		return
  1196  	}
  1197  
  1198  	// We have to be very careful between this point and once
  1199  	// we've shown mp is at an async safe-point. This is like a
  1200  	// signal handler in the sense that mp could have been doing
  1201  	// anything when we stopped it, including holding arbitrary
  1202  	// locks.
  1203  
  1204  	// We have to get the thread context before inspecting the M
  1205  	// because SuspendThread only requests a suspend.
  1206  	// GetThreadContext actually blocks until it's suspended.
  1207  	stdcall2(_GetThreadContext, thread, uintptr(unsafe.Pointer(c)))
  1208  
  1209  	unlock(&suspendLock)
  1210  
  1211  	// Does it want a preemption and is it safe to preempt?
  1212  	gp := gFromTLS(mp)
  1213  	if wantAsyncPreempt(gp) && isAsyncSafePoint(gp, c.ip(), c.sp(), c.lr()) {
  1214  		// Inject call to asyncPreempt
  1215  		targetPC := funcPC(asyncPreempt)
  1216  		switch GOARCH {
  1217  		default:
  1218  			throw("unsupported architecture")
  1219  		case "386", "amd64":
  1220  			// Make it look like the thread called targetPC.
  1221  			pc := c.ip()
  1222  			sp := c.sp()
  1223  			sp -= sys.PtrSize
  1224  			*(*uintptr)(unsafe.Pointer(sp)) = pc
  1225  			c.set_sp(sp)
  1226  			c.set_ip(targetPC)
  1227  		}
  1228  
  1229  		stdcall2(_SetThreadContext, thread, uintptr(unsafe.Pointer(c)))
  1230  	}
  1231  
  1232  	atomic.Store(&mp.preemptExtLock, 0)
  1233  
  1234  	// Acknowledge the preemption.
  1235  	atomic.Xadd(&mp.preemptGen, 1)
  1236  
  1237  	stdcall1(_ResumeThread, thread)
  1238  	stdcall1(_CloseHandle, thread)
  1239  }
  1240  
  1241  // osPreemptExtEnter is called before entering external code that may
  1242  // call ExitProcess.
  1243  //
  1244  // This must be nosplit because it may be called from a syscall with
  1245  // untyped stack slots, so the stack must not be grown or scanned.
  1246  //
  1247  //go:nosplit
  1248  func osPreemptExtEnter(mp *m) {
  1249  	for !atomic.Cas(&mp.preemptExtLock, 0, 1) {
  1250  		// An asynchronous preemption is in progress. It's not
  1251  		// safe to enter external code because it may call
  1252  		// ExitProcess and deadlock with SuspendThread.
  1253  		// Ideally we would do the preemption ourselves, but
  1254  		// can't since there may be untyped syscall arguments
  1255  		// on the stack. Instead, just wait and encourage the
  1256  		// SuspendThread APC to run. The preemption should be
  1257  		// done shortly.
  1258  		osyield()
  1259  	}
  1260  	// Asynchronous preemption is now blocked.
  1261  }
  1262  
  1263  // osPreemptExtExit is called after returning from external code that
  1264  // may call ExitProcess.
  1265  //
  1266  // See osPreemptExtEnter for why this is nosplit.
  1267  //
  1268  //go:nosplit
  1269  func osPreemptExtExit(mp *m) {
  1270  	atomic.Store(&mp.preemptExtLock, 0)
  1271  }