github.com/dannin/go@v0.0.0-20161031215817-d35dfd405eaa/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 _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 //go:nosplit 336 func exit(code int32) { 337 stdcall1(_ExitProcess, uintptr(code)) 338 } 339 340 //go:nosplit 341 func write(fd uintptr, buf unsafe.Pointer, n int32) int32 { 342 const ( 343 _STD_OUTPUT_HANDLE = ^uintptr(10) // -11 344 _STD_ERROR_HANDLE = ^uintptr(11) // -12 345 ) 346 var handle uintptr 347 switch fd { 348 case 1: 349 handle = stdcall1(_GetStdHandle, _STD_OUTPUT_HANDLE) 350 case 2: 351 handle = stdcall1(_GetStdHandle, _STD_ERROR_HANDLE) 352 default: 353 // assume fd is real windows handle. 354 handle = fd 355 } 356 isASCII := true 357 b := (*[1 << 30]byte)(buf)[:n] 358 for _, x := range b { 359 if x >= 0x80 { 360 isASCII = false 361 break 362 } 363 } 364 365 if !isASCII { 366 var m uint32 367 isConsole := stdcall2(_GetConsoleMode, handle, uintptr(unsafe.Pointer(&m))) != 0 368 // If this is a console output, various non-unicode code pages can be in use. 369 // Use the dedicated WriteConsole call to ensure unicode is printed correctly. 370 if isConsole { 371 return int32(writeConsole(handle, buf, n)) 372 } 373 } 374 var written uint32 375 stdcall5(_WriteFile, handle, uintptr(buf), uintptr(n), uintptr(unsafe.Pointer(&written)), 0) 376 return int32(written) 377 } 378 379 var ( 380 utf16ConsoleBack [1000]uint16 381 utf16ConsoleBackLock mutex 382 ) 383 384 // writeConsole writes bufLen bytes from buf to the console File. 385 // It returns the number of bytes written. 386 func writeConsole(handle uintptr, buf unsafe.Pointer, bufLen int32) int { 387 const surr2 = (surrogateMin + surrogateMax + 1) / 2 388 389 // Do not use defer for unlock. May cause issues when printing a panic. 390 lock(&utf16ConsoleBackLock) 391 392 b := (*[1 << 30]byte)(buf)[:bufLen] 393 s := *(*string)(unsafe.Pointer(&b)) 394 395 utf16tmp := utf16ConsoleBack[:] 396 397 total := len(s) 398 w := 0 399 for _, r := range s { 400 if w >= len(utf16tmp)-2 { 401 writeConsoleUTF16(handle, utf16tmp[:w]) 402 w = 0 403 } 404 if r < 0x10000 { 405 utf16tmp[w] = uint16(r) 406 w++ 407 } else { 408 r -= 0x10000 409 utf16tmp[w] = surrogateMin + uint16(r>>10)&0x3ff 410 utf16tmp[w+1] = surr2 + uint16(r)&0x3ff 411 w += 2 412 } 413 } 414 writeConsoleUTF16(handle, utf16tmp[:w]) 415 unlock(&utf16ConsoleBackLock) 416 return total 417 } 418 419 // writeConsoleUTF16 is the dedicated windows calls that correctly prints 420 // to the console regardless of the current code page. Input is utf-16 code points. 421 // The handle must be a console handle. 422 func writeConsoleUTF16(handle uintptr, b []uint16) { 423 l := uint32(len(b)) 424 if l == 0 { 425 return 426 } 427 var written uint32 428 stdcall5(_WriteConsoleW, 429 handle, 430 uintptr(unsafe.Pointer(&b[0])), 431 uintptr(l), 432 uintptr(unsafe.Pointer(&written)), 433 0, 434 ) 435 return 436 } 437 438 //go:nosplit 439 func semasleep(ns int64) int32 { 440 const ( 441 _WAIT_ABANDONED = 0x00000080 442 _WAIT_OBJECT_0 = 0x00000000 443 _WAIT_TIMEOUT = 0x00000102 444 _WAIT_FAILED = 0xFFFFFFFF 445 ) 446 447 // store ms in ns to save stack space 448 if ns < 0 { 449 ns = _INFINITE 450 } else { 451 ns = int64(timediv(ns, 1000000, nil)) 452 if ns == 0 { 453 ns = 1 454 } 455 } 456 457 result := stdcall2(_WaitForSingleObject, getg().m.waitsema, uintptr(ns)) 458 switch result { 459 case _WAIT_OBJECT_0: //signaled 460 return 0 461 462 case _WAIT_TIMEOUT: 463 return -1 464 465 case _WAIT_ABANDONED: 466 systemstack(func() { 467 throw("runtime.semasleep wait_abandoned") 468 }) 469 470 case _WAIT_FAILED: 471 systemstack(func() { 472 print("runtime: waitforsingleobject wait_failed; errno=", getlasterror(), "\n") 473 throw("runtime.semasleep wait_failed") 474 }) 475 476 default: 477 systemstack(func() { 478 print("runtime: waitforsingleobject unexpected; result=", result, "\n") 479 throw("runtime.semasleep unexpected") 480 }) 481 } 482 483 return -1 // unreachable 484 } 485 486 //go:nosplit 487 func semawakeup(mp *m) { 488 if stdcall1(_SetEvent, mp.waitsema) == 0 { 489 systemstack(func() { 490 print("runtime: setevent failed; errno=", getlasterror(), "\n") 491 throw("runtime.semawakeup") 492 }) 493 } 494 } 495 496 //go:nosplit 497 func semacreate(mp *m) { 498 if mp.waitsema != 0 { 499 return 500 } 501 mp.waitsema = stdcall4(_CreateEventA, 0, 0, 0, 0) 502 if mp.waitsema == 0 { 503 systemstack(func() { 504 print("runtime: createevent failed; errno=", getlasterror(), "\n") 505 throw("runtime.semacreate") 506 }) 507 } 508 } 509 510 // May run with m.p==nil, so write barriers are not allowed. This 511 // function is called by newosproc0, so it is also required to 512 // operate without stack guards. 513 //go:nowritebarrierc 514 //go:nosplit 515 func newosproc(mp *m, stk unsafe.Pointer) { 516 const _STACK_SIZE_PARAM_IS_A_RESERVATION = 0x00010000 517 thandle := stdcall6(_CreateThread, 0, 0x20000, 518 funcPC(tstart_stdcall), uintptr(unsafe.Pointer(mp)), 519 _STACK_SIZE_PARAM_IS_A_RESERVATION, 0) 520 521 if thandle == 0 { 522 print("runtime: failed to create new OS thread (have ", mcount(), " already; errno=", getlasterror(), ")\n") 523 throw("runtime.newosproc") 524 } 525 } 526 527 // Used by the C library build mode. On Linux this function would allocate a 528 // stack, but that's not necessary for Windows. No stack guards are present 529 // and the GC has not been initialized, so write barriers will fail. 530 //go:nowritebarrierc 531 //go:nosplit 532 func newosproc0(mp *m, stk unsafe.Pointer) { 533 newosproc(mp, stk) 534 } 535 536 // Called to initialize a new m (including the bootstrap m). 537 // Called on the parent thread (main thread in case of bootstrap), can allocate memory. 538 func mpreinit(mp *m) { 539 } 540 541 //go:nosplit 542 func msigsave(mp *m) { 543 } 544 545 //go:nosplit 546 func msigrestore(sigmask sigset) { 547 } 548 549 //go:nosplit 550 func sigblock() { 551 } 552 553 // Called to initialize a new m (including the bootstrap m). 554 // Called on the new thread, cannot allocate memory. 555 func minit() { 556 var thandle uintptr 557 stdcall7(_DuplicateHandle, currentProcess, currentThread, currentProcess, uintptr(unsafe.Pointer(&thandle)), 0, 0, _DUPLICATE_SAME_ACCESS) 558 atomic.Storeuintptr(&getg().m.thread, thandle) 559 } 560 561 // Called from dropm to undo the effect of an minit. 562 //go:nosplit 563 func unminit() { 564 tp := &getg().m.thread 565 stdcall1(_CloseHandle, *tp) 566 *tp = 0 567 } 568 569 // Described in http://www.dcl.hpi.uni-potsdam.de/research/WRK/2007/08/getting-os-information-the-kuser_shared_data-structure/ 570 type _KSYSTEM_TIME struct { 571 LowPart uint32 572 High1Time int32 573 High2Time int32 574 } 575 576 const ( 577 _INTERRUPT_TIME = 0x7ffe0008 578 _SYSTEM_TIME = 0x7ffe0014 579 ) 580 581 //go:nosplit 582 func systime(addr uintptr) int64 { 583 timeaddr := (*_KSYSTEM_TIME)(unsafe.Pointer(addr)) 584 585 var t _KSYSTEM_TIME 586 for i := 1; i < 10000; i++ { 587 // these fields must be read in that order (see URL above) 588 t.High1Time = timeaddr.High1Time 589 t.LowPart = timeaddr.LowPart 590 t.High2Time = timeaddr.High2Time 591 if t.High1Time == t.High2Time { 592 return int64(t.High1Time)<<32 | int64(t.LowPart) 593 } 594 if (i % 100) == 0 { 595 osyield() 596 } 597 } 598 systemstack(func() { 599 throw("interrupt/system time is changing too fast") 600 }) 601 return 0 602 } 603 604 //go:nosplit 605 func unixnano() int64 { 606 return (systime(_SYSTEM_TIME) - 116444736000000000) * 100 607 } 608 609 //go:nosplit 610 func nanotime() int64 { 611 return systime(_INTERRUPT_TIME) * 100 612 } 613 614 // Calling stdcall on os stack. 615 // May run during STW, so write barriers are not allowed. 616 //go:nowritebarrier 617 //go:nosplit 618 func stdcall(fn stdFunction) uintptr { 619 gp := getg() 620 mp := gp.m 621 mp.libcall.fn = uintptr(unsafe.Pointer(fn)) 622 623 if mp.profilehz != 0 { 624 // leave pc/sp for cpu profiler 625 mp.libcallg.set(gp) 626 mp.libcallpc = getcallerpc(unsafe.Pointer(&fn)) 627 // sp must be the last, because once async cpu profiler finds 628 // all three values to be non-zero, it will use them 629 mp.libcallsp = getcallersp(unsafe.Pointer(&fn)) 630 } 631 asmcgocall(asmstdcallAddr, unsafe.Pointer(&mp.libcall)) 632 mp.libcallsp = 0 633 return mp.libcall.r1 634 } 635 636 //go:nosplit 637 func stdcall0(fn stdFunction) uintptr { 638 mp := getg().m 639 mp.libcall.n = 0 640 mp.libcall.args = uintptr(noescape(unsafe.Pointer(&fn))) // it's unused but must be non-nil, otherwise crashes 641 return stdcall(fn) 642 } 643 644 //go:nosplit 645 func stdcall1(fn stdFunction, a0 uintptr) uintptr { 646 mp := getg().m 647 mp.libcall.n = 1 648 mp.libcall.args = uintptr(noescape(unsafe.Pointer(&a0))) 649 return stdcall(fn) 650 } 651 652 //go:nosplit 653 func stdcall2(fn stdFunction, a0, a1 uintptr) uintptr { 654 mp := getg().m 655 mp.libcall.n = 2 656 mp.libcall.args = uintptr(noescape(unsafe.Pointer(&a0))) 657 return stdcall(fn) 658 } 659 660 //go:nosplit 661 func stdcall3(fn stdFunction, a0, a1, a2 uintptr) uintptr { 662 mp := getg().m 663 mp.libcall.n = 3 664 mp.libcall.args = uintptr(noescape(unsafe.Pointer(&a0))) 665 return stdcall(fn) 666 } 667 668 //go:nosplit 669 func stdcall4(fn stdFunction, a0, a1, a2, a3 uintptr) uintptr { 670 mp := getg().m 671 mp.libcall.n = 4 672 mp.libcall.args = uintptr(noescape(unsafe.Pointer(&a0))) 673 return stdcall(fn) 674 } 675 676 //go:nosplit 677 func stdcall5(fn stdFunction, a0, a1, a2, a3, a4 uintptr) uintptr { 678 mp := getg().m 679 mp.libcall.n = 5 680 mp.libcall.args = uintptr(noescape(unsafe.Pointer(&a0))) 681 return stdcall(fn) 682 } 683 684 //go:nosplit 685 func stdcall6(fn stdFunction, a0, a1, a2, a3, a4, a5 uintptr) uintptr { 686 mp := getg().m 687 mp.libcall.n = 6 688 mp.libcall.args = uintptr(noescape(unsafe.Pointer(&a0))) 689 return stdcall(fn) 690 } 691 692 //go:nosplit 693 func stdcall7(fn stdFunction, a0, a1, a2, a3, a4, a5, a6 uintptr) uintptr { 694 mp := getg().m 695 mp.libcall.n = 7 696 mp.libcall.args = uintptr(noescape(unsafe.Pointer(&a0))) 697 return stdcall(fn) 698 } 699 700 // in sys_windows_386.s and sys_windows_amd64.s 701 func onosstack(fn unsafe.Pointer, arg uint32) 702 func usleep2(usec uint32) 703 func switchtothread() 704 705 var usleep2Addr unsafe.Pointer 706 var switchtothreadAddr unsafe.Pointer 707 708 //go:nosplit 709 func osyield() { 710 onosstack(switchtothreadAddr, 0) 711 } 712 713 //go:nosplit 714 func usleep(us uint32) { 715 // Have 1us units; want 100ns units. 716 onosstack(usleep2Addr, 10*us) 717 } 718 719 func ctrlhandler1(_type uint32) uint32 { 720 var s uint32 721 722 switch _type { 723 case _CTRL_C_EVENT, _CTRL_BREAK_EVENT: 724 s = _SIGINT 725 default: 726 return 0 727 } 728 729 if sigsend(s) { 730 return 1 731 } 732 exit(2) // SIGINT, SIGTERM, etc 733 return 0 734 } 735 736 // in sys_windows_386.s and sys_windows_amd64.s 737 func profileloop() 738 739 var profiletimer uintptr 740 741 func profilem(mp *m) { 742 var r *context 743 rbuf := make([]byte, unsafe.Sizeof(*r)+15) 744 745 tls := &mp.tls[0] 746 gp := *((**g)(unsafe.Pointer(tls))) 747 748 // align Context to 16 bytes 749 r = (*context)(unsafe.Pointer((uintptr(unsafe.Pointer(&rbuf[15]))) &^ 15)) 750 r.contextflags = _CONTEXT_CONTROL 751 stdcall2(_GetThreadContext, mp.thread, uintptr(unsafe.Pointer(r))) 752 sigprof(r.ip(), r.sp(), 0, gp, mp) 753 } 754 755 func profileloop1(param uintptr) uint32 { 756 stdcall2(_SetThreadPriority, currentThread, _THREAD_PRIORITY_HIGHEST) 757 758 for { 759 stdcall2(_WaitForSingleObject, profiletimer, _INFINITE) 760 first := (*m)(atomic.Loadp(unsafe.Pointer(&allm))) 761 for mp := first; mp != nil; mp = mp.alllink { 762 thread := atomic.Loaduintptr(&mp.thread) 763 // Do not profile threads blocked on Notes, 764 // this includes idle worker threads, 765 // idle timer thread, idle heap scavenger, etc. 766 if thread == 0 || mp.profilehz == 0 || mp.blocked { 767 continue 768 } 769 stdcall1(_SuspendThread, thread) 770 if mp.profilehz != 0 && !mp.blocked { 771 profilem(mp) 772 } 773 stdcall1(_ResumeThread, thread) 774 } 775 } 776 } 777 778 var cpuprofilerlock mutex 779 780 func resetcpuprofiler(hz int32) { 781 lock(&cpuprofilerlock) 782 if profiletimer == 0 { 783 timer := stdcall3(_CreateWaitableTimerA, 0, 0, 0) 784 atomic.Storeuintptr(&profiletimer, timer) 785 thread := stdcall6(_CreateThread, 0, 0, funcPC(profileloop), 0, 0, 0) 786 stdcall2(_SetThreadPriority, thread, _THREAD_PRIORITY_HIGHEST) 787 stdcall1(_CloseHandle, thread) 788 } 789 unlock(&cpuprofilerlock) 790 791 ms := int32(0) 792 due := ^int64(^uint64(1 << 63)) 793 if hz > 0 { 794 ms = 1000 / hz 795 if ms == 0 { 796 ms = 1 797 } 798 due = int64(ms) * -10000 799 } 800 stdcall6(_SetWaitableTimer, profiletimer, uintptr(unsafe.Pointer(&due)), uintptr(ms), 0, 0, 0) 801 atomic.Store((*uint32)(unsafe.Pointer(&getg().m.profilehz)), uint32(hz)) 802 } 803 804 func memlimit() uintptr { 805 return 0 806 }