github.com/AESNooper/go/src@v0.0.0-20220218095104-b56a4ab1bbbb/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 interface{} = 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 interface{} = 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 //go:nowritebarrierrec 906 //go:nosplit 907 func newosproc(mp *m) { 908 // We pass 0 for the stack size to use the default for this binary. 909 thandle := stdcall6(_CreateThread, 0, 0, 910 abi.FuncPCABI0(tstart_stdcall), uintptr(unsafe.Pointer(mp)), 911 0, 0) 912 913 if thandle == 0 { 914 if atomic.Load(&exiting) != 0 { 915 // CreateThread may fail if called 916 // concurrently with ExitProcess. If this 917 // happens, just freeze this thread and let 918 // the process exit. See issue #18253. 919 lock(&deadlock) 920 lock(&deadlock) 921 } 922 print("runtime: failed to create new OS thread (have ", mcount(), " already; errno=", getlasterror(), ")\n") 923 throw("runtime.newosproc") 924 } 925 926 // Close thandle to avoid leaking the thread object if it exits. 927 stdcall1(_CloseHandle, thandle) 928 } 929 930 // Used by the C library build mode. On Linux this function would allocate a 931 // stack, but that's not necessary for Windows. No stack guards are present 932 // and the GC has not been initialized, so write barriers will fail. 933 //go:nowritebarrierrec 934 //go:nosplit 935 func newosproc0(mp *m, stk unsafe.Pointer) { 936 // TODO: this is completely broken. The args passed to newosproc0 (in asm_amd64.s) 937 // are stacksize and function, not *m and stack. 938 // Check os_linux.go for an implementation that might actually work. 939 throw("bad newosproc0") 940 } 941 942 func exitThread(wait *uint32) { 943 // We should never reach exitThread on Windows because we let 944 // the OS clean up threads. 945 throw("exitThread") 946 } 947 948 // Called to initialize a new m (including the bootstrap m). 949 // Called on the parent thread (main thread in case of bootstrap), can allocate memory. 950 func mpreinit(mp *m) { 951 } 952 953 //go:nosplit 954 func sigsave(p *sigset) { 955 } 956 957 //go:nosplit 958 func msigrestore(sigmask sigset) { 959 } 960 961 //go:nosplit 962 //go:nowritebarrierrec 963 func clearSignalHandlers() { 964 } 965 966 //go:nosplit 967 func sigblock(exiting bool) { 968 } 969 970 // Called to initialize a new m (including the bootstrap m). 971 // Called on the new thread, cannot allocate memory. 972 func minit() { 973 var thandle uintptr 974 if stdcall7(_DuplicateHandle, currentProcess, currentThread, currentProcess, uintptr(unsafe.Pointer(&thandle)), 0, 0, _DUPLICATE_SAME_ACCESS) == 0 { 975 print("runtime.minit: duplicatehandle failed; errno=", getlasterror(), "\n") 976 throw("runtime.minit: duplicatehandle failed") 977 } 978 979 mp := getg().m 980 lock(&mp.threadLock) 981 mp.thread = thandle 982 983 // Configure usleep timer, if possible. 984 if mp.highResTimer == 0 && haveHighResTimer { 985 mp.highResTimer = createHighResTimer() 986 if mp.highResTimer == 0 { 987 print("runtime: CreateWaitableTimerEx failed; errno=", getlasterror(), "\n") 988 throw("CreateWaitableTimerEx when creating timer failed") 989 } 990 } 991 unlock(&mp.threadLock) 992 993 // Query the true stack base from the OS. Currently we're 994 // running on a small assumed stack. 995 var mbi memoryBasicInformation 996 res := stdcall3(_VirtualQuery, uintptr(unsafe.Pointer(&mbi)), uintptr(unsafe.Pointer(&mbi)), unsafe.Sizeof(mbi)) 997 if res == 0 { 998 print("runtime: VirtualQuery failed; errno=", getlasterror(), "\n") 999 throw("VirtualQuery for stack base failed") 1000 } 1001 // The system leaves an 8K PAGE_GUARD region at the bottom of 1002 // the stack (in theory VirtualQuery isn't supposed to include 1003 // that, but it does). Add an additional 8K of slop for 1004 // calling C functions that don't have stack checks and for 1005 // lastcontinuehandler. We shouldn't be anywhere near this 1006 // bound anyway. 1007 base := mbi.allocationBase + 16<<10 1008 // Sanity check the stack bounds. 1009 g0 := getg() 1010 if base > g0.stack.hi || g0.stack.hi-base > 64<<20 { 1011 print("runtime: g0 stack [", hex(base), ",", hex(g0.stack.hi), ")\n") 1012 throw("bad g0 stack") 1013 } 1014 g0.stack.lo = base 1015 g0.stackguard0 = g0.stack.lo + _StackGuard 1016 g0.stackguard1 = g0.stackguard0 1017 // Sanity check the SP. 1018 stackcheck() 1019 } 1020 1021 // Called from dropm to undo the effect of an minit. 1022 //go:nosplit 1023 func unminit() { 1024 mp := getg().m 1025 lock(&mp.threadLock) 1026 if mp.thread != 0 { 1027 stdcall1(_CloseHandle, mp.thread) 1028 mp.thread = 0 1029 } 1030 unlock(&mp.threadLock) 1031 } 1032 1033 // Called from exitm, but not from drop, to undo the effect of thread-owned 1034 // resources in minit, semacreate, or elsewhere. Do not take locks after calling this. 1035 //go:nosplit 1036 func mdestroy(mp *m) { 1037 if mp.highResTimer != 0 { 1038 stdcall1(_CloseHandle, mp.highResTimer) 1039 mp.highResTimer = 0 1040 } 1041 if mp.waitsema != 0 { 1042 stdcall1(_CloseHandle, mp.waitsema) 1043 mp.waitsema = 0 1044 } 1045 if mp.resumesema != 0 { 1046 stdcall1(_CloseHandle, mp.resumesema) 1047 mp.resumesema = 0 1048 } 1049 } 1050 1051 // Calling stdcall on os stack. 1052 // May run during STW, so write barriers are not allowed. 1053 //go:nowritebarrier 1054 //go:nosplit 1055 func stdcall(fn stdFunction) uintptr { 1056 gp := getg() 1057 mp := gp.m 1058 mp.libcall.fn = uintptr(unsafe.Pointer(fn)) 1059 resetLibcall := false 1060 if mp.profilehz != 0 && mp.libcallsp == 0 { 1061 // leave pc/sp for cpu profiler 1062 mp.libcallg.set(gp) 1063 mp.libcallpc = getcallerpc() 1064 // sp must be the last, because once async cpu profiler finds 1065 // all three values to be non-zero, it will use them 1066 mp.libcallsp = getcallersp() 1067 resetLibcall = true // See comment in sys_darwin.go:libcCall 1068 } 1069 asmcgocall(asmstdcallAddr, unsafe.Pointer(&mp.libcall)) 1070 if resetLibcall { 1071 mp.libcallsp = 0 1072 } 1073 return mp.libcall.r1 1074 } 1075 1076 //go:nosplit 1077 func stdcall0(fn stdFunction) uintptr { 1078 mp := getg().m 1079 mp.libcall.n = 0 1080 mp.libcall.args = uintptr(noescape(unsafe.Pointer(&fn))) // it's unused but must be non-nil, otherwise crashes 1081 return stdcall(fn) 1082 } 1083 1084 //go:nosplit 1085 //go:cgo_unsafe_args 1086 func stdcall1(fn stdFunction, a0 uintptr) uintptr { 1087 mp := getg().m 1088 mp.libcall.n = 1 1089 mp.libcall.args = uintptr(noescape(unsafe.Pointer(&a0))) 1090 return stdcall(fn) 1091 } 1092 1093 //go:nosplit 1094 //go:cgo_unsafe_args 1095 func stdcall2(fn stdFunction, a0, a1 uintptr) uintptr { 1096 mp := getg().m 1097 mp.libcall.n = 2 1098 mp.libcall.args = uintptr(noescape(unsafe.Pointer(&a0))) 1099 return stdcall(fn) 1100 } 1101 1102 //go:nosplit 1103 //go:cgo_unsafe_args 1104 func stdcall3(fn stdFunction, a0, a1, a2 uintptr) uintptr { 1105 mp := getg().m 1106 mp.libcall.n = 3 1107 mp.libcall.args = uintptr(noescape(unsafe.Pointer(&a0))) 1108 return stdcall(fn) 1109 } 1110 1111 //go:nosplit 1112 //go:cgo_unsafe_args 1113 func stdcall4(fn stdFunction, a0, a1, a2, a3 uintptr) uintptr { 1114 mp := getg().m 1115 mp.libcall.n = 4 1116 mp.libcall.args = uintptr(noescape(unsafe.Pointer(&a0))) 1117 return stdcall(fn) 1118 } 1119 1120 //go:nosplit 1121 //go:cgo_unsafe_args 1122 func stdcall5(fn stdFunction, a0, a1, a2, a3, a4 uintptr) uintptr { 1123 mp := getg().m 1124 mp.libcall.n = 5 1125 mp.libcall.args = uintptr(noescape(unsafe.Pointer(&a0))) 1126 return stdcall(fn) 1127 } 1128 1129 //go:nosplit 1130 //go:cgo_unsafe_args 1131 func stdcall6(fn stdFunction, a0, a1, a2, a3, a4, a5 uintptr) uintptr { 1132 mp := getg().m 1133 mp.libcall.n = 6 1134 mp.libcall.args = uintptr(noescape(unsafe.Pointer(&a0))) 1135 return stdcall(fn) 1136 } 1137 1138 //go:nosplit 1139 //go:cgo_unsafe_args 1140 func stdcall7(fn stdFunction, a0, a1, a2, a3, a4, a5, a6 uintptr) uintptr { 1141 mp := getg().m 1142 mp.libcall.n = 7 1143 mp.libcall.args = uintptr(noescape(unsafe.Pointer(&a0))) 1144 return stdcall(fn) 1145 } 1146 1147 // These must run on the system stack only. 1148 func usleep2(dt int32) 1149 func usleep2HighRes(dt int32) 1150 func switchtothread() 1151 1152 //go:nosplit 1153 func osyield_no_g() { 1154 switchtothread() 1155 } 1156 1157 //go:nosplit 1158 func osyield() { 1159 systemstack(switchtothread) 1160 } 1161 1162 //go:nosplit 1163 func usleep_no_g(us uint32) { 1164 dt := -10 * int32(us) // relative sleep (negative), 100ns units 1165 usleep2(dt) 1166 } 1167 1168 //go:nosplit 1169 func usleep(us uint32) { 1170 systemstack(func() { 1171 dt := -10 * int32(us) // relative sleep (negative), 100ns units 1172 // If the high-res timer is available and its handle has been allocated for this m, use it. 1173 // Otherwise fall back to the low-res one, which doesn't need a handle. 1174 if haveHighResTimer && getg().m.highResTimer != 0 { 1175 usleep2HighRes(dt) 1176 } else { 1177 usleep2(dt) 1178 } 1179 }) 1180 } 1181 1182 func ctrlHandler(_type uint32) uintptr { 1183 var s uint32 1184 1185 switch _type { 1186 case _CTRL_C_EVENT, _CTRL_BREAK_EVENT: 1187 s = _SIGINT 1188 case _CTRL_CLOSE_EVENT, _CTRL_LOGOFF_EVENT, _CTRL_SHUTDOWN_EVENT: 1189 s = _SIGTERM 1190 default: 1191 return 0 1192 } 1193 1194 if sigsend(s) { 1195 if s == _SIGTERM { 1196 // Windows terminates the process after this handler returns. 1197 // Block indefinitely to give signal handlers a chance to clean up, 1198 // but make sure to be properly parked first, so the rest of the 1199 // program can continue executing. 1200 block() 1201 } 1202 return 1 1203 } 1204 return 0 1205 } 1206 1207 // called from zcallback_windows_*.s to sys_windows_*.s 1208 func callbackasm1() 1209 1210 var profiletimer uintptr 1211 1212 func profilem(mp *m, thread uintptr) { 1213 // Align Context to 16 bytes. 1214 var c *context 1215 var cbuf [unsafe.Sizeof(*c) + 15]byte 1216 c = (*context)(unsafe.Pointer((uintptr(unsafe.Pointer(&cbuf[15]))) &^ 15)) 1217 1218 c.contextflags = _CONTEXT_CONTROL 1219 stdcall2(_GetThreadContext, thread, uintptr(unsafe.Pointer(c))) 1220 1221 gp := gFromSP(mp, c.sp()) 1222 1223 sigprof(c.ip(), c.sp(), c.lr(), gp, mp) 1224 } 1225 1226 func gFromSP(mp *m, sp uintptr) *g { 1227 if gp := mp.g0; gp != nil && gp.stack.lo < sp && sp < gp.stack.hi { 1228 return gp 1229 } 1230 if gp := mp.gsignal; gp != nil && gp.stack.lo < sp && sp < gp.stack.hi { 1231 return gp 1232 } 1233 if gp := mp.curg; gp != nil && gp.stack.lo < sp && sp < gp.stack.hi { 1234 return gp 1235 } 1236 return nil 1237 } 1238 1239 func profileLoop() { 1240 stdcall2(_SetThreadPriority, currentThread, _THREAD_PRIORITY_HIGHEST) 1241 1242 for { 1243 stdcall2(_WaitForSingleObject, profiletimer, _INFINITE) 1244 first := (*m)(atomic.Loadp(unsafe.Pointer(&allm))) 1245 for mp := first; mp != nil; mp = mp.alllink { 1246 if mp == getg().m { 1247 // Don't profile ourselves. 1248 continue 1249 } 1250 1251 lock(&mp.threadLock) 1252 // Do not profile threads blocked on Notes, 1253 // this includes idle worker threads, 1254 // idle timer thread, idle heap scavenger, etc. 1255 if mp.thread == 0 || mp.profilehz == 0 || mp.blocked { 1256 unlock(&mp.threadLock) 1257 continue 1258 } 1259 // Acquire our own handle to the thread. 1260 var thread uintptr 1261 if stdcall7(_DuplicateHandle, currentProcess, mp.thread, currentProcess, uintptr(unsafe.Pointer(&thread)), 0, 0, _DUPLICATE_SAME_ACCESS) == 0 { 1262 print("runtime: duplicatehandle failed; errno=", getlasterror(), "\n") 1263 throw("duplicatehandle failed") 1264 } 1265 unlock(&mp.threadLock) 1266 1267 // mp may exit between the DuplicateHandle 1268 // above and the SuspendThread. The handle 1269 // will remain valid, but SuspendThread may 1270 // fail. 1271 if int32(stdcall1(_SuspendThread, thread)) == -1 { 1272 // The thread no longer exists. 1273 stdcall1(_CloseHandle, thread) 1274 continue 1275 } 1276 if mp.profilehz != 0 && !mp.blocked { 1277 // Pass the thread handle in case mp 1278 // was in the process of shutting down. 1279 profilem(mp, thread) 1280 } 1281 stdcall1(_ResumeThread, thread) 1282 stdcall1(_CloseHandle, thread) 1283 } 1284 } 1285 } 1286 1287 func setProcessCPUProfiler(hz int32) { 1288 if profiletimer == 0 { 1289 timer := stdcall3(_CreateWaitableTimerA, 0, 0, 0) 1290 atomic.Storeuintptr(&profiletimer, timer) 1291 newm(profileLoop, nil, -1) 1292 } 1293 } 1294 1295 func setThreadCPUProfiler(hz int32) { 1296 ms := int32(0) 1297 due := ^int64(^uint64(1 << 63)) 1298 if hz > 0 { 1299 ms = 1000 / hz 1300 if ms == 0 { 1301 ms = 1 1302 } 1303 due = int64(ms) * -10000 1304 } 1305 stdcall6(_SetWaitableTimer, profiletimer, uintptr(unsafe.Pointer(&due)), uintptr(ms), 0, 0, 0) 1306 atomic.Store((*uint32)(unsafe.Pointer(&getg().m.profilehz)), uint32(hz)) 1307 } 1308 1309 const preemptMSupported = true 1310 1311 // suspendLock protects simultaneous SuspendThread operations from 1312 // suspending each other. 1313 var suspendLock mutex 1314 1315 func preemptM(mp *m) { 1316 if mp == getg().m { 1317 throw("self-preempt") 1318 } 1319 1320 // Synchronize with external code that may try to ExitProcess. 1321 if !atomic.Cas(&mp.preemptExtLock, 0, 1) { 1322 // External code is running. Fail the preemption 1323 // attempt. 1324 atomic.Xadd(&mp.preemptGen, 1) 1325 return 1326 } 1327 1328 // Acquire our own handle to mp's thread. 1329 lock(&mp.threadLock) 1330 if mp.thread == 0 { 1331 // The M hasn't been minit'd yet (or was just unminit'd). 1332 unlock(&mp.threadLock) 1333 atomic.Store(&mp.preemptExtLock, 0) 1334 atomic.Xadd(&mp.preemptGen, 1) 1335 return 1336 } 1337 var thread uintptr 1338 if stdcall7(_DuplicateHandle, currentProcess, mp.thread, currentProcess, uintptr(unsafe.Pointer(&thread)), 0, 0, _DUPLICATE_SAME_ACCESS) == 0 { 1339 print("runtime.preemptM: duplicatehandle failed; errno=", getlasterror(), "\n") 1340 throw("runtime.preemptM: duplicatehandle failed") 1341 } 1342 unlock(&mp.threadLock) 1343 1344 // Prepare thread context buffer. This must be aligned to 16 bytes. 1345 var c *context 1346 var cbuf [unsafe.Sizeof(*c) + 15]byte 1347 c = (*context)(unsafe.Pointer((uintptr(unsafe.Pointer(&cbuf[15]))) &^ 15)) 1348 c.contextflags = _CONTEXT_CONTROL 1349 1350 // Serialize thread suspension. SuspendThread is asynchronous, 1351 // so it's otherwise possible for two threads to suspend each 1352 // other and deadlock. We must hold this lock until after 1353 // GetThreadContext, since that blocks until the thread is 1354 // actually suspended. 1355 lock(&suspendLock) 1356 1357 // Suspend the thread. 1358 if int32(stdcall1(_SuspendThread, thread)) == -1 { 1359 unlock(&suspendLock) 1360 stdcall1(_CloseHandle, thread) 1361 atomic.Store(&mp.preemptExtLock, 0) 1362 // The thread no longer exists. This shouldn't be 1363 // possible, but just acknowledge the request. 1364 atomic.Xadd(&mp.preemptGen, 1) 1365 return 1366 } 1367 1368 // We have to be very careful between this point and once 1369 // we've shown mp is at an async safe-point. This is like a 1370 // signal handler in the sense that mp could have been doing 1371 // anything when we stopped it, including holding arbitrary 1372 // locks. 1373 1374 // We have to get the thread context before inspecting the M 1375 // because SuspendThread only requests a suspend. 1376 // GetThreadContext actually blocks until it's suspended. 1377 stdcall2(_GetThreadContext, thread, uintptr(unsafe.Pointer(c))) 1378 1379 unlock(&suspendLock) 1380 1381 // Does it want a preemption and is it safe to preempt? 1382 gp := gFromSP(mp, c.sp()) 1383 if gp != nil && wantAsyncPreempt(gp) { 1384 if ok, newpc := isAsyncSafePoint(gp, c.ip(), c.sp(), c.lr()); ok { 1385 // Inject call to asyncPreempt 1386 targetPC := abi.FuncPCABI0(asyncPreempt) 1387 switch GOARCH { 1388 default: 1389 throw("unsupported architecture") 1390 case "386", "amd64": 1391 // Make it look like the thread called targetPC. 1392 sp := c.sp() 1393 sp -= goarch.PtrSize 1394 *(*uintptr)(unsafe.Pointer(sp)) = newpc 1395 c.set_sp(sp) 1396 c.set_ip(targetPC) 1397 1398 case "arm": 1399 // Push LR. The injected call is responsible 1400 // for restoring LR. gentraceback is aware of 1401 // this extra slot. See sigctxt.pushCall in 1402 // signal_arm.go, which is similar except we 1403 // subtract 1 from IP here. 1404 sp := c.sp() 1405 sp -= goarch.PtrSize 1406 c.set_sp(sp) 1407 *(*uint32)(unsafe.Pointer(sp)) = uint32(c.lr()) 1408 c.set_lr(newpc - 1) 1409 c.set_ip(targetPC) 1410 1411 case "arm64": 1412 // Push LR. The injected call is responsible 1413 // for restoring LR. gentraceback is aware of 1414 // this extra slot. See sigctxt.pushCall in 1415 // signal_arm64.go. 1416 sp := c.sp() - 16 // SP needs 16-byte alignment 1417 c.set_sp(sp) 1418 *(*uint64)(unsafe.Pointer(sp)) = uint64(c.lr()) 1419 c.set_lr(newpc) 1420 c.set_ip(targetPC) 1421 } 1422 stdcall2(_SetThreadContext, thread, uintptr(unsafe.Pointer(c))) 1423 } 1424 } 1425 1426 atomic.Store(&mp.preemptExtLock, 0) 1427 1428 // Acknowledge the preemption. 1429 atomic.Xadd(&mp.preemptGen, 1) 1430 1431 stdcall1(_ResumeThread, thread) 1432 stdcall1(_CloseHandle, thread) 1433 } 1434 1435 // osPreemptExtEnter is called before entering external code that may 1436 // call ExitProcess. 1437 // 1438 // This must be nosplit because it may be called from a syscall with 1439 // untyped stack slots, so the stack must not be grown or scanned. 1440 // 1441 //go:nosplit 1442 func osPreemptExtEnter(mp *m) { 1443 for !atomic.Cas(&mp.preemptExtLock, 0, 1) { 1444 // An asynchronous preemption is in progress. It's not 1445 // safe to enter external code because it may call 1446 // ExitProcess and deadlock with SuspendThread. 1447 // Ideally we would do the preemption ourselves, but 1448 // can't since there may be untyped syscall arguments 1449 // on the stack. Instead, just wait and encourage the 1450 // SuspendThread APC to run. The preemption should be 1451 // done shortly. 1452 osyield() 1453 } 1454 // Asynchronous preemption is now blocked. 1455 } 1456 1457 // osPreemptExtExit is called after returning from external code that 1458 // may call ExitProcess. 1459 // 1460 // See osPreemptExtEnter for why this is nosplit. 1461 // 1462 //go:nosplit 1463 func osPreemptExtExit(mp *m) { 1464 atomic.Store(&mp.preemptExtLock, 0) 1465 }