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