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