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