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