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