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