github.com/ltltlt/go-source-code@v0.0.0-20190830023027-95be009773aa/runtime/os_windows.go (about) 1 // Copyright 2009 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package runtime 6 7 import ( 8 "runtime/internal/atomic" 9 "unsafe" 10 ) 11 12 // TODO(brainman): should not need those 13 const ( 14 _NSIG = 65 15 ) 16 17 //go:cgo_import_dynamic runtime._AddVectoredExceptionHandler AddVectoredExceptionHandler%2 "kernel32.dll" 18 //go:cgo_import_dynamic runtime._CloseHandle CloseHandle%1 "kernel32.dll" 19 //go:cgo_import_dynamic runtime._CreateEventA CreateEventA%4 "kernel32.dll" 20 //go:cgo_import_dynamic runtime._CreateIoCompletionPort CreateIoCompletionPort%4 "kernel32.dll" 21 //go:cgo_import_dynamic runtime._CreateThread CreateThread%6 "kernel32.dll" 22 //go:cgo_import_dynamic runtime._CreateWaitableTimerA CreateWaitableTimerA%3 "kernel32.dll" 23 //go:cgo_import_dynamic runtime._DuplicateHandle DuplicateHandle%7 "kernel32.dll" 24 //go:cgo_import_dynamic runtime._ExitProcess ExitProcess%1 "kernel32.dll" 25 //go:cgo_import_dynamic runtime._FreeEnvironmentStringsW FreeEnvironmentStringsW%1 "kernel32.dll" 26 //go:cgo_import_dynamic runtime._GetConsoleMode GetConsoleMode%2 "kernel32.dll" 27 //go:cgo_import_dynamic runtime._GetEnvironmentStringsW GetEnvironmentStringsW%0 "kernel32.dll" 28 //go:cgo_import_dynamic runtime._GetProcAddress GetProcAddress%2 "kernel32.dll" 29 //go:cgo_import_dynamic runtime._GetProcessAffinityMask GetProcessAffinityMask%3 "kernel32.dll" 30 //go:cgo_import_dynamic runtime._GetQueuedCompletionStatus GetQueuedCompletionStatus%5 "kernel32.dll" 31 //go:cgo_import_dynamic runtime._GetStdHandle GetStdHandle%1 "kernel32.dll" 32 //go:cgo_import_dynamic runtime._GetSystemInfo GetSystemInfo%1 "kernel32.dll" 33 //go:cgo_import_dynamic runtime._GetThreadContext GetThreadContext%2 "kernel32.dll" 34 //go:cgo_import_dynamic runtime._LoadLibraryW LoadLibraryW%1 "kernel32.dll" 35 //go:cgo_import_dynamic runtime._LoadLibraryA LoadLibraryA%1 "kernel32.dll" 36 //go:cgo_import_dynamic runtime._ResumeThread ResumeThread%1 "kernel32.dll" 37 //go:cgo_import_dynamic runtime._SetConsoleCtrlHandler SetConsoleCtrlHandler%2 "kernel32.dll" 38 //go:cgo_import_dynamic runtime._SetErrorMode SetErrorMode%1 "kernel32.dll" 39 //go:cgo_import_dynamic runtime._SetEvent SetEvent%1 "kernel32.dll" 40 //go:cgo_import_dynamic runtime._SetProcessPriorityBoost SetProcessPriorityBoost%2 "kernel32.dll" 41 //go:cgo_import_dynamic runtime._SetThreadPriority SetThreadPriority%2 "kernel32.dll" 42 //go:cgo_import_dynamic runtime._SetUnhandledExceptionFilter SetUnhandledExceptionFilter%1 "kernel32.dll" 43 //go:cgo_import_dynamic runtime._SetWaitableTimer SetWaitableTimer%6 "kernel32.dll" 44 //go:cgo_import_dynamic runtime._SuspendThread SuspendThread%1 "kernel32.dll" 45 //go:cgo_import_dynamic runtime._SwitchToThread SwitchToThread%0 "kernel32.dll" 46 //go:cgo_import_dynamic runtime._VirtualAlloc VirtualAlloc%4 "kernel32.dll" 47 //go:cgo_import_dynamic runtime._VirtualFree VirtualFree%3 "kernel32.dll" 48 //go:cgo_import_dynamic runtime._WSAGetOverlappedResult WSAGetOverlappedResult%5 "ws2_32.dll" 49 //go:cgo_import_dynamic runtime._WaitForSingleObject WaitForSingleObject%2 "kernel32.dll" 50 //go:cgo_import_dynamic runtime._WriteConsoleW WriteConsoleW%5 "kernel32.dll" 51 //go:cgo_import_dynamic runtime._WriteFile WriteFile%5 "kernel32.dll" 52 //go:cgo_import_dynamic runtime._timeBeginPeriod timeBeginPeriod%1 "winmm.dll" 53 //go:cgo_import_dynamic runtime._timeEndPeriod timeEndPeriod%1 "winmm.dll" 54 55 type stdFunction unsafe.Pointer 56 57 var ( 58 // Following syscalls are available on every Windows PC. 59 // All these variables are set by the Windows executable 60 // loader before the Go program starts. 61 _AddVectoredExceptionHandler, 62 _CloseHandle, 63 _CreateEventA, 64 _CreateIoCompletionPort, 65 _CreateThread, 66 _CreateWaitableTimerA, 67 _DuplicateHandle, 68 _ExitProcess, 69 _FreeEnvironmentStringsW, 70 _GetConsoleMode, 71 _GetEnvironmentStringsW, 72 _GetProcAddress, 73 _GetProcessAffinityMask, 74 _GetQueuedCompletionStatus, 75 _GetStdHandle, 76 _GetSystemInfo, 77 _GetSystemTimeAsFileTime, 78 _GetThreadContext, 79 _LoadLibraryW, 80 _LoadLibraryA, 81 _QueryPerformanceCounter, 82 _QueryPerformanceFrequency, 83 _ResumeThread, 84 _SetConsoleCtrlHandler, 85 _SetErrorMode, 86 _SetEvent, 87 _SetProcessPriorityBoost, 88 _SetThreadPriority, 89 _SetUnhandledExceptionFilter, 90 _SetWaitableTimer, 91 _SuspendThread, 92 _SwitchToThread, 93 _VirtualAlloc, 94 _VirtualFree, 95 _WSAGetOverlappedResult, 96 _WaitForSingleObject, 97 _WriteConsoleW, 98 _WriteFile, 99 _timeBeginPeriod, 100 _timeEndPeriod, 101 _ stdFunction 102 103 // Following syscalls are only available on some Windows PCs. 104 // We will load syscalls, if available, before using them. 105 _AddDllDirectory, 106 _AddVectoredContinueHandler, 107 _GetQueuedCompletionStatusEx, 108 _LoadLibraryExW, 109 _ stdFunction 110 111 // Use RtlGenRandom to generate cryptographically random data. 112 // This approach has been recommended by Microsoft (see issue 113 // 15589 for details). 114 // The RtlGenRandom is not listed in advapi32.dll, instead 115 // RtlGenRandom function can be found by searching for SystemFunction036. 116 // Also some versions of Mingw cannot link to SystemFunction036 117 // when building executable as Cgo. So load SystemFunction036 118 // manually during runtime startup. 119 _RtlGenRandom stdFunction 120 121 // Load ntdll.dll manually during startup, otherwise Mingw 122 // links wrong printf function to cgo executable (see issue 123 // 12030 for details). 124 _NtWaitForSingleObject stdFunction 125 ) 126 127 // Function to be called by windows CreateThread 128 // to start new os thread. 129 func tstart_stdcall(newm *m) uint32 130 131 func ctrlhandler(_type uint32) uint32 132 133 type mOS struct { 134 waitsema uintptr // semaphore for parking on locks 135 } 136 137 //go:linkname os_sigpipe os.sigpipe 138 func os_sigpipe() { 139 throw("too many writes on closed pipe") 140 } 141 142 // Stubs so tests can link correctly. These should never be called. 143 func open(name *byte, mode, perm int32) int32 { 144 throw("unimplemented") 145 return -1 146 } 147 func closefd(fd int32) int32 { 148 throw("unimplemented") 149 return -1 150 } 151 func read(fd int32, p unsafe.Pointer, n int32) int32 { 152 throw("unimplemented") 153 return -1 154 } 155 156 type sigset struct{} 157 158 // Call a Windows function with stdcall conventions, 159 // and switch to os stack during the call. 160 func asmstdcall(fn unsafe.Pointer) 161 162 var asmstdcallAddr unsafe.Pointer 163 164 func windowsFindfunc(lib uintptr, name []byte) stdFunction { 165 if name[len(name)-1] != 0 { 166 throw("usage") 167 } 168 f := stdcall2(_GetProcAddress, lib, uintptr(unsafe.Pointer(&name[0]))) 169 return stdFunction(unsafe.Pointer(f)) 170 } 171 172 func loadOptionalSyscalls() { 173 var kernel32dll = []byte("kernel32.dll\000") 174 k32 := stdcall1(_LoadLibraryA, uintptr(unsafe.Pointer(&kernel32dll[0]))) 175 if k32 == 0 { 176 throw("kernel32.dll not found") 177 } 178 _AddDllDirectory = windowsFindfunc(k32, []byte("AddDllDirectory\000")) 179 _AddVectoredContinueHandler = windowsFindfunc(k32, []byte("AddVectoredContinueHandler\000")) 180 _GetQueuedCompletionStatusEx = windowsFindfunc(k32, []byte("GetQueuedCompletionStatusEx\000")) 181 _LoadLibraryExW = windowsFindfunc(k32, []byte("LoadLibraryExW\000")) 182 183 var advapi32dll = []byte("advapi32.dll\000") 184 a32 := stdcall1(_LoadLibraryA, uintptr(unsafe.Pointer(&advapi32dll[0]))) 185 if a32 == 0 { 186 throw("advapi32.dll not found") 187 } 188 _RtlGenRandom = windowsFindfunc(a32, []byte("SystemFunction036\000")) 189 190 var ntdll = []byte("ntdll.dll\000") 191 n32 := stdcall1(_LoadLibraryA, uintptr(unsafe.Pointer(&ntdll[0]))) 192 if n32 == 0 { 193 throw("ntdll.dll not found") 194 } 195 _NtWaitForSingleObject = windowsFindfunc(n32, []byte("NtWaitForSingleObject\000")) 196 197 if windowsFindfunc(n32, []byte("wine_get_version\000")) != nil { 198 // running on Wine 199 initWine(k32) 200 } 201 } 202 203 //go:nosplit 204 func getLoadLibrary() uintptr { 205 return uintptr(unsafe.Pointer(_LoadLibraryW)) 206 } 207 208 //go:nosplit 209 func getLoadLibraryEx() uintptr { 210 return uintptr(unsafe.Pointer(_LoadLibraryExW)) 211 } 212 213 //go:nosplit 214 func getGetProcAddress() uintptr { 215 return uintptr(unsafe.Pointer(_GetProcAddress)) 216 } 217 218 func getproccount() int32 { 219 var mask, sysmask uintptr 220 ret := stdcall3(_GetProcessAffinityMask, currentProcess, uintptr(unsafe.Pointer(&mask)), uintptr(unsafe.Pointer(&sysmask))) 221 if ret != 0 { 222 n := 0 223 maskbits := int(unsafe.Sizeof(mask) * 8) 224 for i := 0; i < maskbits; i++ { 225 if mask&(1<<uint(i)) != 0 { 226 n++ 227 } 228 } 229 if n != 0 { 230 return int32(n) 231 } 232 } 233 // use GetSystemInfo if GetProcessAffinityMask fails 234 var info systeminfo 235 stdcall1(_GetSystemInfo, uintptr(unsafe.Pointer(&info))) 236 return int32(info.dwnumberofprocessors) 237 } 238 239 func getPageSize() uintptr { 240 var info systeminfo 241 stdcall1(_GetSystemInfo, uintptr(unsafe.Pointer(&info))) 242 return uintptr(info.dwpagesize) 243 } 244 245 const ( 246 currentProcess = ^uintptr(0) // -1 = current process 247 currentThread = ^uintptr(1) // -2 = current thread 248 ) 249 250 // in sys_windows_386.s and sys_windows_amd64.s: 251 func externalthreadhandler() 252 func getlasterror() uint32 253 func setlasterror(err uint32) 254 255 // When loading DLLs, we prefer to use LoadLibraryEx with 256 // LOAD_LIBRARY_SEARCH_* flags, if available. LoadLibraryEx is not 257 // available on old Windows, though, and the LOAD_LIBRARY_SEARCH_* 258 // flags are not available on some versions of Windows without a 259 // security patch. 260 // 261 // https://msdn.microsoft.com/en-us/library/ms684179(v=vs.85).aspx says: 262 // "Windows 7, Windows Server 2008 R2, Windows Vista, and Windows 263 // Server 2008: The LOAD_LIBRARY_SEARCH_* flags are available on 264 // systems that have KB2533623 installed. To determine whether the 265 // flags are available, use GetProcAddress to get the address of the 266 // AddDllDirectory, RemoveDllDirectory, or SetDefaultDllDirectories 267 // function. If GetProcAddress succeeds, the LOAD_LIBRARY_SEARCH_* 268 // flags can be used with LoadLibraryEx." 269 var useLoadLibraryEx bool 270 271 var timeBeginPeriodRetValue uint32 272 273 // osRelaxMinNS indicates that sysmon shouldn't osRelax if the next 274 // timer is less than 60 ms from now. Since osRelaxing may reduce 275 // timer resolution to 15.6 ms, this keeps timer error under roughly 1 276 // part in 4. 277 const osRelaxMinNS = 60 * 1e6 278 279 // osRelax is called by the scheduler when transitioning to and from 280 // all Ps being idle. 281 // 282 // On Windows, it adjusts the system-wide timer resolution. Go needs a 283 // high resolution timer while running and there's little extra cost 284 // if we're already using the CPU, but if all Ps are idle there's no 285 // need to consume extra power to drive the high-res timer. 286 func osRelax(relax bool) uint32 { 287 if relax { 288 return uint32(stdcall1(_timeEndPeriod, 1)) 289 } else { 290 return uint32(stdcall1(_timeBeginPeriod, 1)) 291 } 292 } 293 294 func osinit() { 295 asmstdcallAddr = unsafe.Pointer(funcPC(asmstdcall)) 296 usleep2Addr = unsafe.Pointer(funcPC(usleep2)) 297 switchtothreadAddr = unsafe.Pointer(funcPC(switchtothread)) 298 299 setBadSignalMsg() 300 301 loadOptionalSyscalls() 302 303 useLoadLibraryEx = (_LoadLibraryExW != nil && _AddDllDirectory != nil) 304 305 disableWER() 306 307 initExceptionHandler() 308 309 stdcall2(_SetConsoleCtrlHandler, funcPC(ctrlhandler), 1) 310 311 timeBeginPeriodRetValue = osRelax(false) 312 313 ncpu = getproccount() 314 315 physPageSize = getPageSize() 316 317 // Windows dynamic priority boosting assumes that a process has different types 318 // of dedicated threads -- GUI, IO, computational, etc. Go processes use 319 // equivalent threads that all do a mix of GUI, IO, computations, etc. 320 // In such context dynamic priority boosting does nothing but harm, so we turn it off. 321 stdcall2(_SetProcessPriorityBoost, currentProcess, 1) 322 } 323 324 func nanotime() int64 325 326 // useQPCTime controls whether time.now and nanotime use QueryPerformanceCounter. 327 // This is only set to 1 when running under Wine. 328 var useQPCTime uint8 329 330 var qpcStartCounter int64 331 var qpcMultiplier int64 332 333 //go:nosplit 334 func nanotimeQPC() int64 { 335 var counter int64 = 0 336 stdcall1(_QueryPerformanceCounter, uintptr(unsafe.Pointer(&counter))) 337 338 // returns number of nanoseconds 339 return (counter - qpcStartCounter) * qpcMultiplier 340 } 341 342 //go:nosplit 343 func nowQPC() (sec int64, nsec int32, mono int64) { 344 var ft int64 345 stdcall1(_GetSystemTimeAsFileTime, uintptr(unsafe.Pointer(&ft))) 346 347 t := (ft - 116444736000000000) * 100 348 349 sec = t / 1000000000 350 nsec = int32(t - sec*1000000000) 351 352 mono = nanotimeQPC() 353 return 354 } 355 356 func initWine(k32 uintptr) { 357 _GetSystemTimeAsFileTime = windowsFindfunc(k32, []byte("GetSystemTimeAsFileTime\000")) 358 if _GetSystemTimeAsFileTime == nil { 359 throw("could not find GetSystemTimeAsFileTime() syscall") 360 } 361 362 _QueryPerformanceCounter = windowsFindfunc(k32, []byte("QueryPerformanceCounter\000")) 363 _QueryPerformanceFrequency = windowsFindfunc(k32, []byte("QueryPerformanceFrequency\000")) 364 if _QueryPerformanceCounter == nil || _QueryPerformanceFrequency == nil { 365 throw("could not find QPC syscalls") 366 } 367 368 // We can not simply fallback to GetSystemTimeAsFileTime() syscall, since its time is not monotonic, 369 // instead we use QueryPerformanceCounter family of syscalls to implement monotonic timer 370 // https://msdn.microsoft.com/en-us/library/windows/desktop/dn553408(v=vs.85).aspx 371 372 var tmp int64 373 stdcall1(_QueryPerformanceFrequency, uintptr(unsafe.Pointer(&tmp))) 374 if tmp == 0 { 375 throw("QueryPerformanceFrequency syscall returned zero, running on unsupported hardware") 376 } 377 378 // This should not overflow, it is a number of ticks of the performance counter per second, 379 // its resolution is at most 10 per usecond (on Wine, even smaller on real hardware), so it will be at most 10 millions here, 380 // panic if overflows. 381 if tmp > (1<<31 - 1) { 382 throw("QueryPerformanceFrequency overflow 32 bit divider, check nosplit discussion to proceed") 383 } 384 qpcFrequency := int32(tmp) 385 stdcall1(_QueryPerformanceCounter, uintptr(unsafe.Pointer(&qpcStartCounter))) 386 387 // Since we are supposed to run this time calls only on Wine, it does not lose precision, 388 // since Wine's timer is kind of emulated at 10 Mhz, so it will be a nice round multiplier of 100 389 // but for general purpose system (like 3.3 Mhz timer on i7) it will not be very precise. 390 // We have to do it this way (or similar), since multiplying QPC counter by 100 millions overflows 391 // int64 and resulted time will always be invalid. 392 qpcMultiplier = int64(timediv(1000000000, qpcFrequency, nil)) 393 394 useQPCTime = 1 395 } 396 397 //go:nosplit 398 func getRandomData(r []byte) { 399 n := 0 400 if stdcall2(_RtlGenRandom, uintptr(unsafe.Pointer(&r[0])), uintptr(len(r)))&0xff != 0 { 401 n = len(r) 402 } 403 extendRandom(r, n) 404 } 405 406 func goenvs() { 407 // strings is a pointer to environment variable pairs in the form: 408 // "envA=valA\x00envB=valB\x00\x00" (in UTF-16) 409 // Two consecutive zero bytes end the list. 410 strings := unsafe.Pointer(stdcall0(_GetEnvironmentStringsW)) 411 p := (*[1 << 24]uint16)(strings)[:] 412 413 n := 0 414 for from, i := 0, 0; true; i++ { 415 if p[i] == 0 { 416 // empty string marks the end 417 if i == from { 418 break 419 } 420 from = i + 1 421 n++ 422 } 423 } 424 envs = make([]string, n) 425 426 for i := range envs { 427 envs[i] = gostringw(&p[0]) 428 for p[0] != 0 { 429 p = p[1:] 430 } 431 p = p[1:] // skip nil byte 432 } 433 434 stdcall1(_FreeEnvironmentStringsW, uintptr(strings)) 435 } 436 437 // exiting is set to non-zero when the process is exiting. 438 var exiting uint32 439 440 //go:nosplit 441 func exit(code int32) { 442 atomic.Store(&exiting, 1) 443 stdcall1(_ExitProcess, uintptr(code)) 444 } 445 446 //go:nosplit 447 func write(fd uintptr, buf unsafe.Pointer, n int32) int32 { 448 const ( 449 _STD_OUTPUT_HANDLE = ^uintptr(10) // -11 450 _STD_ERROR_HANDLE = ^uintptr(11) // -12 451 ) 452 var handle uintptr 453 switch fd { 454 case 1: 455 handle = stdcall1(_GetStdHandle, _STD_OUTPUT_HANDLE) 456 case 2: 457 handle = stdcall1(_GetStdHandle, _STD_ERROR_HANDLE) 458 default: 459 // assume fd is real windows handle. 460 handle = fd 461 } 462 isASCII := true 463 b := (*[1 << 30]byte)(buf)[:n] 464 for _, x := range b { 465 if x >= 0x80 { 466 isASCII = false 467 break 468 } 469 } 470 471 if !isASCII { 472 var m uint32 473 isConsole := stdcall2(_GetConsoleMode, handle, uintptr(unsafe.Pointer(&m))) != 0 474 // If this is a console output, various non-unicode code pages can be in use. 475 // Use the dedicated WriteConsole call to ensure unicode is printed correctly. 476 if isConsole { 477 return int32(writeConsole(handle, buf, n)) 478 } 479 } 480 var written uint32 481 stdcall5(_WriteFile, handle, uintptr(buf), uintptr(n), uintptr(unsafe.Pointer(&written)), 0) 482 return int32(written) 483 } 484 485 var ( 486 utf16ConsoleBack [1000]uint16 487 utf16ConsoleBackLock mutex 488 ) 489 490 // writeConsole writes bufLen bytes from buf to the console File. 491 // It returns the number of bytes written. 492 func writeConsole(handle uintptr, buf unsafe.Pointer, bufLen int32) int { 493 const surr2 = (surrogateMin + surrogateMax + 1) / 2 494 495 // Do not use defer for unlock. May cause issues when printing a panic. 496 lock(&utf16ConsoleBackLock) 497 498 b := (*[1 << 30]byte)(buf)[:bufLen] 499 s := *(*string)(unsafe.Pointer(&b)) 500 501 utf16tmp := utf16ConsoleBack[:] 502 503 total := len(s) 504 w := 0 505 for _, r := range s { 506 if w >= len(utf16tmp)-2 { 507 writeConsoleUTF16(handle, utf16tmp[:w]) 508 w = 0 509 } 510 if r < 0x10000 { 511 utf16tmp[w] = uint16(r) 512 w++ 513 } else { 514 r -= 0x10000 515 utf16tmp[w] = surrogateMin + uint16(r>>10)&0x3ff 516 utf16tmp[w+1] = surr2 + uint16(r)&0x3ff 517 w += 2 518 } 519 } 520 writeConsoleUTF16(handle, utf16tmp[:w]) 521 unlock(&utf16ConsoleBackLock) 522 return total 523 } 524 525 // writeConsoleUTF16 is the dedicated windows calls that correctly prints 526 // to the console regardless of the current code page. Input is utf-16 code points. 527 // The handle must be a console handle. 528 func writeConsoleUTF16(handle uintptr, b []uint16) { 529 l := uint32(len(b)) 530 if l == 0 { 531 return 532 } 533 var written uint32 534 stdcall5(_WriteConsoleW, 535 handle, 536 uintptr(unsafe.Pointer(&b[0])), 537 uintptr(l), 538 uintptr(unsafe.Pointer(&written)), 539 0, 540 ) 541 return 542 } 543 544 //go:nosplit 545 func semasleep(ns int64) int32 { 546 const ( 547 _WAIT_ABANDONED = 0x00000080 548 _WAIT_OBJECT_0 = 0x00000000 549 _WAIT_TIMEOUT = 0x00000102 550 _WAIT_FAILED = 0xFFFFFFFF 551 ) 552 553 // store ms in ns to save stack space 554 if ns < 0 { 555 ns = _INFINITE 556 } else { 557 ns = int64(timediv(ns, 1000000, nil)) 558 if ns == 0 { 559 ns = 1 560 } 561 } 562 563 result := stdcall2(_WaitForSingleObject, getg().m.waitsema, uintptr(ns)) 564 switch result { 565 case _WAIT_OBJECT_0: //signaled 566 return 0 567 568 case _WAIT_TIMEOUT: 569 return -1 570 571 case _WAIT_ABANDONED: 572 systemstack(func() { 573 throw("runtime.semasleep wait_abandoned") 574 }) 575 576 case _WAIT_FAILED: 577 systemstack(func() { 578 print("runtime: waitforsingleobject wait_failed; errno=", getlasterror(), "\n") 579 throw("runtime.semasleep wait_failed") 580 }) 581 582 default: 583 systemstack(func() { 584 print("runtime: waitforsingleobject unexpected; result=", result, "\n") 585 throw("runtime.semasleep unexpected") 586 }) 587 } 588 589 return -1 // unreachable 590 } 591 592 //go:nosplit 593 func semawakeup(mp *m) { 594 if stdcall1(_SetEvent, mp.waitsema) == 0 { 595 systemstack(func() { 596 print("runtime: setevent failed; errno=", getlasterror(), "\n") 597 throw("runtime.semawakeup") 598 }) 599 } 600 } 601 602 //go:nosplit 603 func semacreate(mp *m) { 604 if mp.waitsema != 0 { 605 return 606 } 607 mp.waitsema = stdcall4(_CreateEventA, 0, 0, 0, 0) 608 if mp.waitsema == 0 { 609 systemstack(func() { 610 print("runtime: createevent failed; errno=", getlasterror(), "\n") 611 throw("runtime.semacreate") 612 }) 613 } 614 } 615 616 // May run with m.p==nil, so write barriers are not allowed. This 617 // function is called by newosproc0, so it is also required to 618 // operate without stack guards. 619 //go:nowritebarrierrec 620 //go:nosplit 621 func newosproc(mp *m, stk unsafe.Pointer) { 622 const _STACK_SIZE_PARAM_IS_A_RESERVATION = 0x00010000 623 // stackSize must match SizeOfStackReserve in cmd/link/internal/ld/pe.go. 624 const stackSize = 0x00200000*_64bit + 0x00100000*(1-_64bit) 625 thandle := stdcall6(_CreateThread, 0, stackSize, 626 funcPC(tstart_stdcall), uintptr(unsafe.Pointer(mp)), 627 _STACK_SIZE_PARAM_IS_A_RESERVATION, 0) 628 629 if thandle == 0 { 630 if atomic.Load(&exiting) != 0 { 631 // CreateThread may fail if called 632 // concurrently with ExitProcess. If this 633 // happens, just freeze this thread and let 634 // the process exit. See issue #18253. 635 lock(&deadlock) 636 lock(&deadlock) 637 } 638 print("runtime: failed to create new OS thread (have ", mcount(), " already; errno=", getlasterror(), ")\n") 639 throw("runtime.newosproc") 640 } 641 642 // Close thandle to avoid leaking the thread object if it exits. 643 stdcall1(_CloseHandle, thandle) 644 } 645 646 // Used by the C library build mode. On Linux this function would allocate a 647 // stack, but that's not necessary for Windows. No stack guards are present 648 // and the GC has not been initialized, so write barriers will fail. 649 //go:nowritebarrierrec 650 //go:nosplit 651 func newosproc0(mp *m, stk unsafe.Pointer) { 652 newosproc(mp, stk) 653 } 654 655 func exitThread(wait *uint32) { 656 // We should never reach exitThread on Windows because we let 657 // the OS clean up threads. 658 throw("exitThread") 659 } 660 661 // Called to initialize a new m (including the bootstrap m). 662 // Called on the parent thread (main thread in case of bootstrap), can allocate memory. 663 func mpreinit(mp *m) { 664 } 665 666 //go:nosplit 667 func msigsave(mp *m) { 668 } 669 670 //go:nosplit 671 func msigrestore(sigmask sigset) { 672 } 673 674 //go:nosplit 675 //go:nowritebarrierrec 676 func clearSignalHandlers() { 677 } 678 679 //go:nosplit 680 func sigblock() { 681 } 682 683 // Called to initialize a new m (including the bootstrap m). 684 // Called on the new thread, cannot allocate memory. 685 func minit() { 686 var thandle uintptr 687 stdcall7(_DuplicateHandle, currentProcess, currentThread, currentProcess, uintptr(unsafe.Pointer(&thandle)), 0, 0, _DUPLICATE_SAME_ACCESS) 688 atomic.Storeuintptr(&getg().m.thread, thandle) 689 } 690 691 // Called from dropm to undo the effect of an minit. 692 //go:nosplit 693 func unminit() { 694 tp := &getg().m.thread 695 stdcall1(_CloseHandle, *tp) 696 *tp = 0 697 } 698 699 // Calling stdcall on os stack. 700 // May run during STW, so write barriers are not allowed. 701 //go:nowritebarrier 702 //go:nosplit 703 func stdcall(fn stdFunction) uintptr { 704 gp := getg() 705 mp := gp.m 706 mp.libcall.fn = uintptr(unsafe.Pointer(fn)) 707 708 if mp.profilehz != 0 { 709 // leave pc/sp for cpu profiler 710 mp.libcallg.set(gp) 711 mp.libcallpc = getcallerpc() 712 // sp must be the last, because once async cpu profiler finds 713 // all three values to be non-zero, it will use them 714 mp.libcallsp = getcallersp(unsafe.Pointer(&fn)) 715 } 716 asmcgocall(asmstdcallAddr, unsafe.Pointer(&mp.libcall)) 717 mp.libcallsp = 0 718 return mp.libcall.r1 719 } 720 721 //go:nosplit 722 func stdcall0(fn stdFunction) uintptr { 723 mp := getg().m 724 mp.libcall.n = 0 725 mp.libcall.args = uintptr(noescape(unsafe.Pointer(&fn))) // it's unused but must be non-nil, otherwise crashes 726 return stdcall(fn) 727 } 728 729 //go:nosplit 730 func stdcall1(fn stdFunction, a0 uintptr) uintptr { 731 mp := getg().m 732 mp.libcall.n = 1 733 mp.libcall.args = uintptr(noescape(unsafe.Pointer(&a0))) 734 return stdcall(fn) 735 } 736 737 //go:nosplit 738 func stdcall2(fn stdFunction, a0, a1 uintptr) uintptr { 739 mp := getg().m 740 mp.libcall.n = 2 741 mp.libcall.args = uintptr(noescape(unsafe.Pointer(&a0))) 742 return stdcall(fn) 743 } 744 745 //go:nosplit 746 func stdcall3(fn stdFunction, a0, a1, a2 uintptr) uintptr { 747 mp := getg().m 748 mp.libcall.n = 3 749 mp.libcall.args = uintptr(noescape(unsafe.Pointer(&a0))) 750 return stdcall(fn) 751 } 752 753 //go:nosplit 754 func stdcall4(fn stdFunction, a0, a1, a2, a3 uintptr) uintptr { 755 mp := getg().m 756 mp.libcall.n = 4 757 mp.libcall.args = uintptr(noescape(unsafe.Pointer(&a0))) 758 return stdcall(fn) 759 } 760 761 //go:nosplit 762 func stdcall5(fn stdFunction, a0, a1, a2, a3, a4 uintptr) uintptr { 763 mp := getg().m 764 mp.libcall.n = 5 765 mp.libcall.args = uintptr(noescape(unsafe.Pointer(&a0))) 766 return stdcall(fn) 767 } 768 769 //go:nosplit 770 func stdcall6(fn stdFunction, a0, a1, a2, a3, a4, a5 uintptr) uintptr { 771 mp := getg().m 772 mp.libcall.n = 6 773 mp.libcall.args = uintptr(noescape(unsafe.Pointer(&a0))) 774 return stdcall(fn) 775 } 776 777 //go:nosplit 778 func stdcall7(fn stdFunction, a0, a1, a2, a3, a4, a5, a6 uintptr) uintptr { 779 mp := getg().m 780 mp.libcall.n = 7 781 mp.libcall.args = uintptr(noescape(unsafe.Pointer(&a0))) 782 return stdcall(fn) 783 } 784 785 // in sys_windows_386.s and sys_windows_amd64.s 786 func onosstack(fn unsafe.Pointer, arg uint32) 787 func usleep2(usec uint32) 788 func switchtothread() 789 790 var usleep2Addr unsafe.Pointer 791 var switchtothreadAddr unsafe.Pointer 792 793 //go:nosplit 794 func osyield() { 795 onosstack(switchtothreadAddr, 0) 796 } 797 798 //go:nosplit 799 func usleep(us uint32) { 800 // Have 1us units; want 100ns units. 801 onosstack(usleep2Addr, 10*us) 802 } 803 804 func ctrlhandler1(_type uint32) uint32 { 805 var s uint32 806 807 switch _type { 808 case _CTRL_C_EVENT, _CTRL_BREAK_EVENT: 809 s = _SIGINT 810 default: 811 return 0 812 } 813 814 if sigsend(s) { 815 return 1 816 } 817 exit(2) // SIGINT, SIGTERM, etc 818 return 0 819 } 820 821 // in sys_windows_386.s and sys_windows_amd64.s 822 func profileloop() 823 824 var profiletimer uintptr 825 826 func profilem(mp *m) { 827 var r *context 828 rbuf := make([]byte, unsafe.Sizeof(*r)+15) 829 830 tls := &mp.tls[0] 831 gp := *((**g)(unsafe.Pointer(tls))) 832 833 // align Context to 16 bytes 834 r = (*context)(unsafe.Pointer((uintptr(unsafe.Pointer(&rbuf[15]))) &^ 15)) 835 r.contextflags = _CONTEXT_CONTROL 836 stdcall2(_GetThreadContext, mp.thread, uintptr(unsafe.Pointer(r))) 837 sigprof(r.ip(), r.sp(), 0, gp, mp) 838 } 839 840 func profileloop1(param uintptr) uint32 { 841 stdcall2(_SetThreadPriority, currentThread, _THREAD_PRIORITY_HIGHEST) 842 843 for { 844 stdcall2(_WaitForSingleObject, profiletimer, _INFINITE) 845 first := (*m)(atomic.Loadp(unsafe.Pointer(&allm))) 846 for mp := first; mp != nil; mp = mp.alllink { 847 thread := atomic.Loaduintptr(&mp.thread) 848 // Do not profile threads blocked on Notes, 849 // this includes idle worker threads, 850 // idle timer thread, idle heap scavenger, etc. 851 if thread == 0 || mp.profilehz == 0 || mp.blocked { 852 continue 853 } 854 stdcall1(_SuspendThread, thread) 855 if mp.profilehz != 0 && !mp.blocked { 856 profilem(mp) 857 } 858 stdcall1(_ResumeThread, thread) 859 } 860 } 861 } 862 863 func setProcessCPUProfiler(hz int32) { 864 if profiletimer == 0 { 865 timer := stdcall3(_CreateWaitableTimerA, 0, 0, 0) 866 atomic.Storeuintptr(&profiletimer, timer) 867 thread := stdcall6(_CreateThread, 0, 0, funcPC(profileloop), 0, 0, 0) 868 stdcall2(_SetThreadPriority, thread, _THREAD_PRIORITY_HIGHEST) 869 stdcall1(_CloseHandle, thread) 870 } 871 } 872 873 func setThreadCPUProfiler(hz int32) { 874 ms := int32(0) 875 due := ^int64(^uint64(1 << 63)) 876 if hz > 0 { 877 ms = 1000 / hz 878 if ms == 0 { 879 ms = 1 880 } 881 due = int64(ms) * -10000 882 } 883 stdcall6(_SetWaitableTimer, profiletimer, uintptr(unsafe.Pointer(&due)), uintptr(ms), 0, 0, 0) 884 atomic.Store((*uint32)(unsafe.Pointer(&getg().m.profilehz)), uint32(hz)) 885 } 886 887 func memlimit() uintptr { 888 return 0 889 }