github.com/sanprasirt/go@v0.0.0-20170607001320-a027466e4b6d/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 //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 // osRelax is called by the scheduler when transitioning to and from 274 // all Ps being idle. 275 // 276 // On Windows, it adjusts the system-wide timer resolution. Go needs a 277 // high resolution timer while running and there's little extra cost 278 // if we're already using the CPU, but if all Ps are idle there's no 279 // need to consume extra power to drive the high-res timer. 280 func osRelax(relax bool) uint32 { 281 if relax { 282 return uint32(stdcall1(_timeEndPeriod, 1)) 283 } else { 284 return uint32(stdcall1(_timeBeginPeriod, 1)) 285 } 286 } 287 288 func osinit() { 289 asmstdcallAddr = unsafe.Pointer(funcPC(asmstdcall)) 290 usleep2Addr = unsafe.Pointer(funcPC(usleep2)) 291 switchtothreadAddr = unsafe.Pointer(funcPC(switchtothread)) 292 293 setBadSignalMsg() 294 295 loadOptionalSyscalls() 296 297 useLoadLibraryEx = (_LoadLibraryExW != nil && _AddDllDirectory != nil) 298 299 disableWER() 300 301 externalthreadhandlerp = funcPC(externalthreadhandler) 302 303 initExceptionHandler() 304 305 stdcall2(_SetConsoleCtrlHandler, funcPC(ctrlhandler), 1) 306 307 timeBeginPeriodRetValue = osRelax(false) 308 309 ncpu = getproccount() 310 311 physPageSize = getPageSize() 312 313 // Windows dynamic priority boosting assumes that a process has different types 314 // of dedicated threads -- GUI, IO, computational, etc. Go processes use 315 // equivalent threads that all do a mix of GUI, IO, computations, etc. 316 // In such context dynamic priority boosting does nothing but harm, so we turn it off. 317 stdcall2(_SetProcessPriorityBoost, currentProcess, 1) 318 } 319 320 func nanotime() int64 321 322 // useQPCTime controls whether time.now and nanotime use QueryPerformanceCounter. 323 // This is only set to 1 when running under Wine. 324 var useQPCTime uint8 325 326 var qpcStartCounter int64 327 var qpcMultiplier int64 328 329 //go:nosplit 330 func nanotimeQPC() int64 { 331 var counter int64 = 0 332 stdcall1(_QueryPerformanceCounter, uintptr(unsafe.Pointer(&counter))) 333 334 // returns number of nanoseconds 335 return (counter - qpcStartCounter) * qpcMultiplier 336 } 337 338 //go:nosplit 339 func nowQPC() (sec int64, nsec int32, mono int64) { 340 var ft int64 341 stdcall1(_GetSystemTimeAsFileTime, uintptr(unsafe.Pointer(&ft))) 342 343 t := (ft - 116444736000000000) * 100 344 345 sec = t / 1000000000 346 nsec = int32(t - sec*1000000000) 347 348 mono = nanotimeQPC() 349 return 350 } 351 352 func initWine(k32 uintptr) { 353 _GetSystemTimeAsFileTime = windowsFindfunc(k32, []byte("GetSystemTimeAsFileTime\000")) 354 if _GetSystemTimeAsFileTime == nil { 355 throw("could not find GetSystemTimeAsFileTime() syscall") 356 } 357 358 _QueryPerformanceCounter = windowsFindfunc(k32, []byte("QueryPerformanceCounter\000")) 359 _QueryPerformanceFrequency = windowsFindfunc(k32, []byte("QueryPerformanceFrequency\000")) 360 if _QueryPerformanceCounter == nil || _QueryPerformanceFrequency == nil { 361 throw("could not find QPC syscalls") 362 } 363 364 // We can not simply fallback to GetSystemTimeAsFileTime() syscall, since its time is not monotonic, 365 // instead we use QueryPerformanceCounter family of syscalls to implement monotonic timer 366 // https://msdn.microsoft.com/en-us/library/windows/desktop/dn553408(v=vs.85).aspx 367 368 var tmp int64 369 stdcall1(_QueryPerformanceFrequency, uintptr(unsafe.Pointer(&tmp))) 370 if tmp == 0 { 371 throw("QueryPerformanceFrequency syscall returned zero, running on unsupported hardware") 372 } 373 374 // This should not overflow, it is a number of ticks of the performance counter per second, 375 // its resolution is at most 10 per usecond (on Wine, even smaller on real hardware), so it will be at most 10 millions here, 376 // panic if overflows. 377 if tmp > (1<<31 - 1) { 378 throw("QueryPerformanceFrequency overflow 32 bit divider, check nosplit discussion to proceed") 379 } 380 qpcFrequency := int32(tmp) 381 stdcall1(_QueryPerformanceCounter, uintptr(unsafe.Pointer(&qpcStartCounter))) 382 383 // Since we are supposed to run this time calls only on Wine, it does not lose precision, 384 // since Wine's timer is kind of emulated at 10 Mhz, so it will be a nice round multiplier of 100 385 // but for general purpose system (like 3.3 Mhz timer on i7) it will not be very precise. 386 // We have to do it this way (or similar), since multiplying QPC counter by 100 millions overflows 387 // int64 and resulted time will always be invalid. 388 qpcMultiplier = int64(timediv(1000000000, qpcFrequency, nil)) 389 390 useQPCTime = 1 391 } 392 393 //go:nosplit 394 func getRandomData(r []byte) { 395 n := 0 396 if stdcall2(_RtlGenRandom, uintptr(unsafe.Pointer(&r[0])), uintptr(len(r)))&0xff != 0 { 397 n = len(r) 398 } 399 extendRandom(r, n) 400 } 401 402 func goenvs() { 403 // strings is a pointer to environment variable pairs in the form: 404 // "envA=valA\x00envB=valB\x00\x00" (in UTF-16) 405 // Two consecutive zero bytes end the list. 406 strings := unsafe.Pointer(stdcall0(_GetEnvironmentStringsW)) 407 p := (*[1 << 24]uint16)(strings)[:] 408 409 n := 0 410 for from, i := 0, 0; true; i++ { 411 if p[i] == 0 { 412 // empty string marks the end 413 if i == from { 414 break 415 } 416 from = i + 1 417 n++ 418 } 419 } 420 envs = make([]string, n) 421 422 for i := range envs { 423 envs[i] = gostringw(&p[0]) 424 for p[0] != 0 { 425 p = p[1:] 426 } 427 p = p[1:] // skip nil byte 428 } 429 430 stdcall1(_FreeEnvironmentStringsW, uintptr(strings)) 431 } 432 433 // exiting is set to non-zero when the process is exiting. 434 var exiting uint32 435 436 //go:nosplit 437 func exit(code int32) { 438 atomic.Store(&exiting, 1) 439 stdcall1(_ExitProcess, uintptr(code)) 440 } 441 442 //go:nosplit 443 func write(fd uintptr, buf unsafe.Pointer, n int32) int32 { 444 const ( 445 _STD_OUTPUT_HANDLE = ^uintptr(10) // -11 446 _STD_ERROR_HANDLE = ^uintptr(11) // -12 447 ) 448 var handle uintptr 449 switch fd { 450 case 1: 451 handle = stdcall1(_GetStdHandle, _STD_OUTPUT_HANDLE) 452 case 2: 453 handle = stdcall1(_GetStdHandle, _STD_ERROR_HANDLE) 454 default: 455 // assume fd is real windows handle. 456 handle = fd 457 } 458 isASCII := true 459 b := (*[1 << 30]byte)(buf)[:n] 460 for _, x := range b { 461 if x >= 0x80 { 462 isASCII = false 463 break 464 } 465 } 466 467 if !isASCII { 468 var m uint32 469 isConsole := stdcall2(_GetConsoleMode, handle, uintptr(unsafe.Pointer(&m))) != 0 470 // If this is a console output, various non-unicode code pages can be in use. 471 // Use the dedicated WriteConsole call to ensure unicode is printed correctly. 472 if isConsole { 473 return int32(writeConsole(handle, buf, n)) 474 } 475 } 476 var written uint32 477 stdcall5(_WriteFile, handle, uintptr(buf), uintptr(n), uintptr(unsafe.Pointer(&written)), 0) 478 return int32(written) 479 } 480 481 var ( 482 utf16ConsoleBack [1000]uint16 483 utf16ConsoleBackLock mutex 484 ) 485 486 // writeConsole writes bufLen bytes from buf to the console File. 487 // It returns the number of bytes written. 488 func writeConsole(handle uintptr, buf unsafe.Pointer, bufLen int32) int { 489 const surr2 = (surrogateMin + surrogateMax + 1) / 2 490 491 // Do not use defer for unlock. May cause issues when printing a panic. 492 lock(&utf16ConsoleBackLock) 493 494 b := (*[1 << 30]byte)(buf)[:bufLen] 495 s := *(*string)(unsafe.Pointer(&b)) 496 497 utf16tmp := utf16ConsoleBack[:] 498 499 total := len(s) 500 w := 0 501 for _, r := range s { 502 if w >= len(utf16tmp)-2 { 503 writeConsoleUTF16(handle, utf16tmp[:w]) 504 w = 0 505 } 506 if r < 0x10000 { 507 utf16tmp[w] = uint16(r) 508 w++ 509 } else { 510 r -= 0x10000 511 utf16tmp[w] = surrogateMin + uint16(r>>10)&0x3ff 512 utf16tmp[w+1] = surr2 + uint16(r)&0x3ff 513 w += 2 514 } 515 } 516 writeConsoleUTF16(handle, utf16tmp[:w]) 517 unlock(&utf16ConsoleBackLock) 518 return total 519 } 520 521 // writeConsoleUTF16 is the dedicated windows calls that correctly prints 522 // to the console regardless of the current code page. Input is utf-16 code points. 523 // The handle must be a console handle. 524 func writeConsoleUTF16(handle uintptr, b []uint16) { 525 l := uint32(len(b)) 526 if l == 0 { 527 return 528 } 529 var written uint32 530 stdcall5(_WriteConsoleW, 531 handle, 532 uintptr(unsafe.Pointer(&b[0])), 533 uintptr(l), 534 uintptr(unsafe.Pointer(&written)), 535 0, 536 ) 537 return 538 } 539 540 //go:nosplit 541 func semasleep(ns int64) int32 { 542 const ( 543 _WAIT_ABANDONED = 0x00000080 544 _WAIT_OBJECT_0 = 0x00000000 545 _WAIT_TIMEOUT = 0x00000102 546 _WAIT_FAILED = 0xFFFFFFFF 547 ) 548 549 // store ms in ns to save stack space 550 if ns < 0 { 551 ns = _INFINITE 552 } else { 553 ns = int64(timediv(ns, 1000000, nil)) 554 if ns == 0 { 555 ns = 1 556 } 557 } 558 559 result := stdcall2(_WaitForSingleObject, getg().m.waitsema, uintptr(ns)) 560 switch result { 561 case _WAIT_OBJECT_0: //signaled 562 return 0 563 564 case _WAIT_TIMEOUT: 565 return -1 566 567 case _WAIT_ABANDONED: 568 systemstack(func() { 569 throw("runtime.semasleep wait_abandoned") 570 }) 571 572 case _WAIT_FAILED: 573 systemstack(func() { 574 print("runtime: waitforsingleobject wait_failed; errno=", getlasterror(), "\n") 575 throw("runtime.semasleep wait_failed") 576 }) 577 578 default: 579 systemstack(func() { 580 print("runtime: waitforsingleobject unexpected; result=", result, "\n") 581 throw("runtime.semasleep unexpected") 582 }) 583 } 584 585 return -1 // unreachable 586 } 587 588 //go:nosplit 589 func semawakeup(mp *m) { 590 if stdcall1(_SetEvent, mp.waitsema) == 0 { 591 systemstack(func() { 592 print("runtime: setevent failed; errno=", getlasterror(), "\n") 593 throw("runtime.semawakeup") 594 }) 595 } 596 } 597 598 //go:nosplit 599 func semacreate(mp *m) { 600 if mp.waitsema != 0 { 601 return 602 } 603 mp.waitsema = stdcall4(_CreateEventA, 0, 0, 0, 0) 604 if mp.waitsema == 0 { 605 systemstack(func() { 606 print("runtime: createevent failed; errno=", getlasterror(), "\n") 607 throw("runtime.semacreate") 608 }) 609 } 610 } 611 612 // May run with m.p==nil, so write barriers are not allowed. This 613 // function is called by newosproc0, so it is also required to 614 // operate without stack guards. 615 //go:nowritebarrierrec 616 //go:nosplit 617 func newosproc(mp *m, stk unsafe.Pointer) { 618 const _STACK_SIZE_PARAM_IS_A_RESERVATION = 0x00010000 619 thandle := stdcall6(_CreateThread, 0, 0x20000, 620 funcPC(tstart_stdcall), uintptr(unsafe.Pointer(mp)), 621 _STACK_SIZE_PARAM_IS_A_RESERVATION, 0) 622 623 if thandle == 0 { 624 if atomic.Load(&exiting) != 0 { 625 // CreateThread may fail if called 626 // concurrently with ExitProcess. If this 627 // happens, just freeze this thread and let 628 // the process exit. See issue #18253. 629 lock(&deadlock) 630 lock(&deadlock) 631 } 632 print("runtime: failed to create new OS thread (have ", mcount(), " already; errno=", getlasterror(), ")\n") 633 throw("runtime.newosproc") 634 } 635 } 636 637 // Used by the C library build mode. On Linux this function would allocate a 638 // stack, but that's not necessary for Windows. No stack guards are present 639 // and the GC has not been initialized, so write barriers will fail. 640 //go:nowritebarrierrec 641 //go:nosplit 642 func newosproc0(mp *m, stk unsafe.Pointer) { 643 newosproc(mp, stk) 644 } 645 646 // Called to initialize a new m (including the bootstrap m). 647 // Called on the parent thread (main thread in case of bootstrap), can allocate memory. 648 func mpreinit(mp *m) { 649 } 650 651 //go:nosplit 652 func msigsave(mp *m) { 653 } 654 655 //go:nosplit 656 func msigrestore(sigmask sigset) { 657 } 658 659 //go:nosplit 660 func sigblock() { 661 } 662 663 // Called to initialize a new m (including the bootstrap m). 664 // Called on the new thread, cannot allocate memory. 665 func minit() { 666 var thandle uintptr 667 stdcall7(_DuplicateHandle, currentProcess, currentThread, currentProcess, uintptr(unsafe.Pointer(&thandle)), 0, 0, _DUPLICATE_SAME_ACCESS) 668 atomic.Storeuintptr(&getg().m.thread, thandle) 669 } 670 671 // Called from dropm to undo the effect of an minit. 672 //go:nosplit 673 func unminit() { 674 tp := &getg().m.thread 675 stdcall1(_CloseHandle, *tp) 676 *tp = 0 677 } 678 679 // Calling stdcall on os stack. 680 // May run during STW, so write barriers are not allowed. 681 //go:nowritebarrier 682 //go:nosplit 683 func stdcall(fn stdFunction) uintptr { 684 gp := getg() 685 mp := gp.m 686 mp.libcall.fn = uintptr(unsafe.Pointer(fn)) 687 688 if mp.profilehz != 0 { 689 // leave pc/sp for cpu profiler 690 mp.libcallg.set(gp) 691 mp.libcallpc = getcallerpc(unsafe.Pointer(&fn)) 692 // sp must be the last, because once async cpu profiler finds 693 // all three values to be non-zero, it will use them 694 mp.libcallsp = getcallersp(unsafe.Pointer(&fn)) 695 } 696 asmcgocall(asmstdcallAddr, unsafe.Pointer(&mp.libcall)) 697 mp.libcallsp = 0 698 return mp.libcall.r1 699 } 700 701 //go:nosplit 702 func stdcall0(fn stdFunction) uintptr { 703 mp := getg().m 704 mp.libcall.n = 0 705 mp.libcall.args = uintptr(noescape(unsafe.Pointer(&fn))) // it's unused but must be non-nil, otherwise crashes 706 return stdcall(fn) 707 } 708 709 //go:nosplit 710 func stdcall1(fn stdFunction, a0 uintptr) uintptr { 711 mp := getg().m 712 mp.libcall.n = 1 713 mp.libcall.args = uintptr(noescape(unsafe.Pointer(&a0))) 714 return stdcall(fn) 715 } 716 717 //go:nosplit 718 func stdcall2(fn stdFunction, a0, a1 uintptr) uintptr { 719 mp := getg().m 720 mp.libcall.n = 2 721 mp.libcall.args = uintptr(noescape(unsafe.Pointer(&a0))) 722 return stdcall(fn) 723 } 724 725 //go:nosplit 726 func stdcall3(fn stdFunction, a0, a1, a2 uintptr) uintptr { 727 mp := getg().m 728 mp.libcall.n = 3 729 mp.libcall.args = uintptr(noescape(unsafe.Pointer(&a0))) 730 return stdcall(fn) 731 } 732 733 //go:nosplit 734 func stdcall4(fn stdFunction, a0, a1, a2, a3 uintptr) uintptr { 735 mp := getg().m 736 mp.libcall.n = 4 737 mp.libcall.args = uintptr(noescape(unsafe.Pointer(&a0))) 738 return stdcall(fn) 739 } 740 741 //go:nosplit 742 func stdcall5(fn stdFunction, a0, a1, a2, a3, a4 uintptr) uintptr { 743 mp := getg().m 744 mp.libcall.n = 5 745 mp.libcall.args = uintptr(noescape(unsafe.Pointer(&a0))) 746 return stdcall(fn) 747 } 748 749 //go:nosplit 750 func stdcall6(fn stdFunction, a0, a1, a2, a3, a4, a5 uintptr) uintptr { 751 mp := getg().m 752 mp.libcall.n = 6 753 mp.libcall.args = uintptr(noescape(unsafe.Pointer(&a0))) 754 return stdcall(fn) 755 } 756 757 //go:nosplit 758 func stdcall7(fn stdFunction, a0, a1, a2, a3, a4, a5, a6 uintptr) uintptr { 759 mp := getg().m 760 mp.libcall.n = 7 761 mp.libcall.args = uintptr(noescape(unsafe.Pointer(&a0))) 762 return stdcall(fn) 763 } 764 765 // in sys_windows_386.s and sys_windows_amd64.s 766 func onosstack(fn unsafe.Pointer, arg uint32) 767 func usleep2(usec uint32) 768 func switchtothread() 769 770 var usleep2Addr unsafe.Pointer 771 var switchtothreadAddr unsafe.Pointer 772 773 //go:nosplit 774 func osyield() { 775 onosstack(switchtothreadAddr, 0) 776 } 777 778 //go:nosplit 779 func usleep(us uint32) { 780 // Have 1us units; want 100ns units. 781 onosstack(usleep2Addr, 10*us) 782 } 783 784 func ctrlhandler1(_type uint32) uint32 { 785 var s uint32 786 787 switch _type { 788 case _CTRL_C_EVENT, _CTRL_BREAK_EVENT: 789 s = _SIGINT 790 default: 791 return 0 792 } 793 794 if sigsend(s) { 795 return 1 796 } 797 exit(2) // SIGINT, SIGTERM, etc 798 return 0 799 } 800 801 // in sys_windows_386.s and sys_windows_amd64.s 802 func profileloop() 803 804 var profiletimer uintptr 805 806 func profilem(mp *m) { 807 var r *context 808 rbuf := make([]byte, unsafe.Sizeof(*r)+15) 809 810 tls := &mp.tls[0] 811 gp := *((**g)(unsafe.Pointer(tls))) 812 813 // align Context to 16 bytes 814 r = (*context)(unsafe.Pointer((uintptr(unsafe.Pointer(&rbuf[15]))) &^ 15)) 815 r.contextflags = _CONTEXT_CONTROL 816 stdcall2(_GetThreadContext, mp.thread, uintptr(unsafe.Pointer(r))) 817 sigprof(r.ip(), r.sp(), 0, gp, mp) 818 } 819 820 func profileloop1(param uintptr) uint32 { 821 stdcall2(_SetThreadPriority, currentThread, _THREAD_PRIORITY_HIGHEST) 822 823 for { 824 stdcall2(_WaitForSingleObject, profiletimer, _INFINITE) 825 first := (*m)(atomic.Loadp(unsafe.Pointer(&allm))) 826 for mp := first; mp != nil; mp = mp.alllink { 827 thread := atomic.Loaduintptr(&mp.thread) 828 // Do not profile threads blocked on Notes, 829 // this includes idle worker threads, 830 // idle timer thread, idle heap scavenger, etc. 831 if thread == 0 || mp.profilehz == 0 || mp.blocked { 832 continue 833 } 834 stdcall1(_SuspendThread, thread) 835 if mp.profilehz != 0 && !mp.blocked { 836 profilem(mp) 837 } 838 stdcall1(_ResumeThread, thread) 839 } 840 } 841 } 842 843 func setProcessCPUProfiler(hz int32) { 844 if profiletimer == 0 { 845 timer := stdcall3(_CreateWaitableTimerA, 0, 0, 0) 846 atomic.Storeuintptr(&profiletimer, timer) 847 thread := stdcall6(_CreateThread, 0, 0, funcPC(profileloop), 0, 0, 0) 848 stdcall2(_SetThreadPriority, thread, _THREAD_PRIORITY_HIGHEST) 849 stdcall1(_CloseHandle, thread) 850 } 851 } 852 853 func setThreadCPUProfiler(hz int32) { 854 ms := int32(0) 855 due := ^int64(^uint64(1 << 63)) 856 if hz > 0 { 857 ms = 1000 / hz 858 if ms == 0 { 859 ms = 1 860 } 861 due = int64(ms) * -10000 862 } 863 stdcall6(_SetWaitableTimer, profiletimer, uintptr(unsafe.Pointer(&due)), uintptr(ms), 0, 0, 0) 864 atomic.Store((*uint32)(unsafe.Pointer(&getg().m.profilehz)), uint32(hz)) 865 } 866 867 func memlimit() uintptr { 868 return 0 869 }