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