Source file
src/runtime/os_windows.go
1
2
3
4
5 package runtime
6
7 import (
8 "internal/abi"
9 "internal/runtime/atomic"
10 "internal/runtime/sys"
11 "internal/runtime/syscall/windows"
12 "unsafe"
13 )
14
15
16 const (
17 _NSIG = 65
18 )
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72 type stdFunction unsafe.Pointer
73
74 var (
75
76
77
78 _AddVectoredContinueHandler,
79 _AddVectoredExceptionHandler,
80 _CloseHandle,
81 _CreateEventA,
82 _CreateIoCompletionPort,
83 _CreateThread,
84 _CreateWaitableTimerA,
85 _CreateWaitableTimerExW,
86 _DuplicateHandle,
87 _ExitProcess,
88 _FreeEnvironmentStringsW,
89 _GetConsoleMode,
90 _GetCurrentThreadId,
91 _GetEnvironmentStringsW,
92 _GetErrorMode,
93 _GetProcAddress,
94 _GetProcessAffinityMask,
95 _GetQueuedCompletionStatusEx,
96 _GetStdHandle,
97 _GetSystemDirectoryA,
98 _GetSystemInfo,
99 _GetThreadContext,
100 _IsProcessorFeaturePresent,
101 _SetThreadContext,
102 _LoadLibraryExW,
103 _PostQueuedCompletionStatus,
104 _QueryPerformanceCounter,
105 _QueryPerformanceFrequency,
106 _RaiseFailFastException,
107 _ResumeThread,
108 _RtlLookupFunctionEntry,
109 _RtlVirtualUnwind,
110 _SetConsoleCtrlHandler,
111 _SetErrorMode,
112 _SetEvent,
113 _SetProcessPriorityBoost,
114 _SetThreadPriority,
115 _SetUnhandledExceptionFilter,
116 _SetWaitableTimer,
117 _SuspendThread,
118 _SwitchToThread,
119 _TlsAlloc,
120 _VirtualAlloc,
121 _VirtualFree,
122 _VirtualQuery,
123 _WaitForSingleObject,
124 _WaitForMultipleObjects,
125 _WerGetFlags,
126 _WerSetFlags,
127 _WriteConsoleW,
128 _WriteFile,
129 _ stdFunction
130
131
132 _ProcessPrng stdFunction
133
134
135
136
137 _NtCreateWaitCompletionPacket stdFunction
138 _NtAssociateWaitCompletionPacket stdFunction
139 _NtCancelWaitCompletionPacket stdFunction
140 _RtlGetCurrentPeb stdFunction
141 _RtlGetVersion stdFunction
142
143
144 _timeBeginPeriod,
145 _timeEndPeriod,
146 _ stdFunction
147 )
148
149 var (
150 bcryptprimitivesdll = [...]uint16{'b', 'c', 'r', 'y', 'p', 't', 'p', 'r', 'i', 'm', 'i', 't', 'i', 'v', 'e', 's', '.', 'd', 'l', 'l', 0}
151 ntdlldll = [...]uint16{'n', 't', 'd', 'l', 'l', '.', 'd', 'l', 'l', 0}
152 powrprofdll = [...]uint16{'p', 'o', 'w', 'r', 'p', 'r', 'o', 'f', '.', 'd', 'l', 'l', 0}
153 winmmdll = [...]uint16{'w', 'i', 'n', 'm', 'm', '.', 'd', 'l', 'l', 0}
154 )
155
156
157
158 func tstart_stdcall(newm *m)
159
160
161 func wintls()
162
163 type mOS struct {
164
165 stdCallInfo windows.StdCallInfo
166
167 threadLock mutex
168 thread uintptr
169
170 waitsema uintptr
171 resumesema uintptr
172
173 highResTimer uintptr
174 waitIocpTimer uintptr
175 waitIocpHandle uintptr
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198 preemptExtLock uint32
199 }
200
201
202 func open(name *byte, mode, perm int32) int32 {
203 throw("unimplemented")
204 return -1
205 }
206 func closefd(fd int32) int32 {
207 throw("unimplemented")
208 return -1
209 }
210 func read(fd int32, p unsafe.Pointer, n int32) int32 {
211 throw("unimplemented")
212 return -1
213 }
214
215 type sigset struct{}
216
217 var asmstdcallAddr unsafe.Pointer
218
219 type winlibcall windows.StdCallInfo
220
221 func windowsFindfunc(lib uintptr, name []byte) stdFunction {
222 if name[len(name)-1] != 0 {
223 throw("usage")
224 }
225 f := stdcall(_GetProcAddress, lib, uintptr(unsafe.Pointer(&name[0])))
226 return stdFunction(unsafe.Pointer(f))
227 }
228
229 const _MAX_PATH = 260
230 var sysDirectory [_MAX_PATH + 1]byte
231 var sysDirectoryLen uintptr
232
233 func initSysDirectory() {
234 l := stdcall(_GetSystemDirectoryA, uintptr(unsafe.Pointer(&sysDirectory[0])), uintptr(len(sysDirectory)-1))
235 if l == 0 || l > uintptr(len(sysDirectory)-1) {
236 throw("Unable to determine system directory")
237 }
238 sysDirectory[l] = '\\'
239 sysDirectoryLen = l + 1
240 }
241
242
243 func windows_GetSystemDirectory() string {
244 return unsafe.String(&sysDirectory[0], sysDirectoryLen)
245 }
246
247 func windowsLoadSystemLib(name []uint16) uintptr {
248 const _LOAD_LIBRARY_SEARCH_SYSTEM32 = 0x00000800
249 return stdcall(_LoadLibraryExW, uintptr(unsafe.Pointer(&name[0])), 0, _LOAD_LIBRARY_SEARCH_SYSTEM32)
250 }
251
252
253 func windows_QueryPerformanceCounter() int64 {
254 var counter int64
255 stdcall(_QueryPerformanceCounter, uintptr(unsafe.Pointer(&counter)))
256 return counter
257 }
258
259
260 func windows_QueryPerformanceFrequency() int64 {
261 var frequency int64
262 stdcall(_QueryPerformanceFrequency, uintptr(unsafe.Pointer(&frequency)))
263 return frequency
264 }
265
266
267 func cpu_isProcessorFeaturePresent(processorFeature uint32) bool {
268 ret := stdcall(_IsProcessorFeaturePresent, uintptr(processorFeature))
269 return ret != 0
270 }
271
272 func loadOptionalSyscalls() {
273 bcryptPrimitives := windowsLoadSystemLib(bcryptprimitivesdll[:])
274 if bcryptPrimitives == 0 {
275 throw("bcryptprimitives.dll not found")
276 }
277 _ProcessPrng = windowsFindfunc(bcryptPrimitives, []byte("ProcessPrng\000"))
278
279 n32 := windowsLoadSystemLib(ntdlldll[:])
280 if n32 == 0 {
281 throw("ntdll.dll not found")
282 }
283 _NtCreateWaitCompletionPacket = windowsFindfunc(n32, []byte("NtCreateWaitCompletionPacket\000"))
284 if _NtCreateWaitCompletionPacket != nil {
285
286 _NtAssociateWaitCompletionPacket = windowsFindfunc(n32, []byte("NtAssociateWaitCompletionPacket\000"))
287 if _NtAssociateWaitCompletionPacket == nil {
288 throw("NtCreateWaitCompletionPacket exists but NtAssociateWaitCompletionPacket does not")
289 }
290 _NtCancelWaitCompletionPacket = windowsFindfunc(n32, []byte("NtCancelWaitCompletionPacket\000"))
291 if _NtCancelWaitCompletionPacket == nil {
292 throw("NtCreateWaitCompletionPacket exists but NtCancelWaitCompletionPacket does not")
293 }
294 }
295 _RtlGetCurrentPeb = windowsFindfunc(n32, []byte("RtlGetCurrentPeb\000"))
296 _RtlGetVersion = windowsFindfunc(n32, []byte("RtlGetVersion\000"))
297 }
298
299 func monitorSuspendResume() {
300 const (
301 _DEVICE_NOTIFY_CALLBACK = 2
302 )
303 type _DEVICE_NOTIFY_SUBSCRIBE_PARAMETERS struct {
304 callback uintptr
305 context uintptr
306 }
307
308 powrprof := windowsLoadSystemLib(powrprofdll[:])
309 if powrprof == 0 {
310 return
311 }
312 powerRegisterSuspendResumeNotification := windowsFindfunc(powrprof, []byte("PowerRegisterSuspendResumeNotification\000"))
313 if powerRegisterSuspendResumeNotification == nil {
314 return
315 }
316 var fn any = func(context uintptr, changeType uint32, setting uintptr) uintptr {
317 for mp := (*m)(atomic.Loadp(unsafe.Pointer(&allm))); mp != nil; mp = mp.alllink {
318 if mp.resumesema != 0 {
319 stdcall(_SetEvent, mp.resumesema)
320 }
321 }
322 return 0
323 }
324 params := _DEVICE_NOTIFY_SUBSCRIBE_PARAMETERS{
325 callback: compileCallback(*efaceOf(&fn), true),
326 }
327 handle := uintptr(0)
328 stdcall(powerRegisterSuspendResumeNotification, _DEVICE_NOTIFY_CALLBACK,
329 uintptr(unsafe.Pointer(¶ms)), uintptr(unsafe.Pointer(&handle)))
330 }
331
332 func getCPUCount() int32 {
333 var mask, sysmask uintptr
334 ret := stdcall(_GetProcessAffinityMask, windows.CurrentProcess, uintptr(unsafe.Pointer(&mask)), uintptr(unsafe.Pointer(&sysmask)))
335 if ret != 0 {
336 n := 0
337 maskbits := int(unsafe.Sizeof(mask) * 8)
338 for i := 0; i < maskbits; i++ {
339 if mask&(1<<uint(i)) != 0 {
340 n++
341 }
342 }
343 if n != 0 {
344 return int32(n)
345 }
346 }
347
348 var info windows.SystemInfo
349 stdcall(_GetSystemInfo, uintptr(unsafe.Pointer(&info)))
350 return int32(info.NumberOfProcessors)
351 }
352
353 func getPageSize() uintptr {
354 var info windows.SystemInfo
355 stdcall(_GetSystemInfo, uintptr(unsafe.Pointer(&info)))
356 return uintptr(info.PageSize)
357 }
358
359
360 func getlasterror() uint32
361
362 var timeBeginPeriodRetValue uint32
363
364
365
366
367
368 const osRelaxMinNS = 60 * 1e6
369
370
371
372
373
374
375
376
377
378
379
380 func osRelax(relax bool) uint32 {
381 if haveHighResTimer {
382
383
384
385 return 0
386 }
387
388 if relax {
389 return uint32(stdcall(_timeEndPeriod, 1))
390 } else {
391 return uint32(stdcall(_timeBeginPeriod, 1))
392 }
393 }
394
395
396
397 var haveHighResTimer = false
398
399
400
401
402
403
404 var haveHighResSleep = false
405
406
407
408
409
410 func createHighResTimer() uintptr {
411
412
413 return stdcall(_CreateWaitableTimerExW, 0, 0,
414 windows.CREATE_WAITABLE_TIMER_HIGH_RESOLUTION,
415 windows.SYNCHRONIZE|windows.TIMER_QUERY_STATE|windows.TIMER_MODIFY_STATE)
416 }
417
418 func initHighResTimer() {
419 h := createHighResTimer()
420 if h != 0 {
421 haveHighResTimer = true
422 haveHighResSleep = _NtCreateWaitCompletionPacket != nil
423 stdcall(_CloseHandle, h)
424 } else {
425
426
427
428 m32 := windowsLoadSystemLib(winmmdll[:])
429 if m32 == 0 {
430 print("runtime: LoadLibraryExW failed; errno=", getlasterror(), "\n")
431 throw("winmm.dll not found")
432 }
433 _timeBeginPeriod = windowsFindfunc(m32, []byte("timeBeginPeriod\000"))
434 _timeEndPeriod = windowsFindfunc(m32, []byte("timeEndPeriod\000"))
435 if _timeBeginPeriod == nil || _timeEndPeriod == nil {
436 print("runtime: GetProcAddress failed; errno=", getlasterror(), "\n")
437 throw("timeBegin/EndPeriod not found")
438 }
439 }
440 }
441
442
443 var canUseLongPaths bool
444
445
446 func initLongPathSupport() {
447 const (
448 IsLongPathAwareProcess = 0x80
449 PebBitFieldOffset = 3
450 )
451
452
453 info := windows.OSVERSIONINFOW{}
454 info.OSVersionInfoSize = uint32(unsafe.Sizeof(info))
455 stdcall(_RtlGetVersion, uintptr(unsafe.Pointer(&info)))
456 if info.MajorVersion < 10 || (info.MajorVersion == 10 && info.MinorVersion == 0 && info.BuildNumber < 15063) {
457 return
458 }
459
460
461
462
463 bitField := (*byte)(unsafe.Pointer(stdcall(_RtlGetCurrentPeb) + PebBitFieldOffset))
464 *bitField |= IsLongPathAwareProcess
465
466 canUseLongPaths = true
467 }
468
469 func osinit() {
470 asmstdcallAddr = unsafe.Pointer(windows.AsmStdCallAddr())
471
472 loadOptionalSyscalls()
473
474 preventErrorDialogs()
475
476 initExceptionHandler()
477
478 initHighResTimer()
479 timeBeginPeriodRetValue = osRelax(false)
480
481 initSysDirectory()
482 initLongPathSupport()
483
484 numCPUStartup = getCPUCount()
485
486 physPageSize = getPageSize()
487
488
489
490
491
492 stdcall(_SetProcessPriorityBoost, windows.CurrentProcess, 1)
493 }
494
495
496 func readRandom(r []byte) int {
497 n := 0
498 if stdcall(_ProcessPrng, uintptr(unsafe.Pointer(&r[0])), uintptr(len(r)))&0xff != 0 {
499 n = len(r)
500 }
501 return n
502 }
503
504 func goenvs() {
505
506
507
508 strings := unsafe.Pointer(stdcall(_GetEnvironmentStringsW))
509 p := (*[1 << 24]uint16)(strings)[:]
510
511 n := 0
512 for from, i := 0, 0; true; i++ {
513 if p[i] == 0 {
514
515 if i == from {
516 break
517 }
518 from = i + 1
519 n++
520 }
521 }
522 envs = make([]string, n)
523
524 for i := range envs {
525 envs[i] = gostringw(&p[0])
526 for p[0] != 0 {
527 p = p[1:]
528 }
529 p = p[1:]
530 }
531
532 stdcall(_FreeEnvironmentStringsW, uintptr(strings))
533
534
535
536 var fn any = ctrlHandler
537 ctrlHandlerPC := compileCallback(*efaceOf(&fn), true)
538 stdcall(_SetConsoleCtrlHandler, ctrlHandlerPC, 1)
539
540 monitorSuspendResume()
541 }
542
543
544 var exiting uint32
545
546
547 func exit(code int32) {
548
549
550
551
552 lock(&suspendLock)
553 atomic.Store(&exiting, 1)
554 stdcall(_ExitProcess, uintptr(code))
555 }
556
557
558
559
560
561
562 func write1(fd uintptr, buf unsafe.Pointer, n int32) int32 {
563 const (
564 _STD_OUTPUT_HANDLE = ^uintptr(10)
565 _STD_ERROR_HANDLE = ^uintptr(11)
566 )
567 var handle uintptr
568 switch fd {
569 case 1:
570 handle = stdcall(_GetStdHandle, _STD_OUTPUT_HANDLE)
571 case 2:
572 handle = stdcall(_GetStdHandle, _STD_ERROR_HANDLE)
573 default:
574
575 handle = fd
576 }
577 isASCII := true
578 b := (*[1 << 30]byte)(buf)[:n]
579 for _, x := range b {
580 if x >= 0x80 {
581 isASCII = false
582 break
583 }
584 }
585
586 if !isASCII {
587 var m uint32
588 isConsole := stdcall(_GetConsoleMode, handle, uintptr(unsafe.Pointer(&m))) != 0
589
590
591 if isConsole {
592 return int32(writeConsole(handle, buf, n))
593 }
594 }
595 var written uint32
596 stdcall(_WriteFile, handle, uintptr(buf), uintptr(n), uintptr(unsafe.Pointer(&written)), 0)
597 return int32(written)
598 }
599
600 var (
601 utf16ConsoleBack [1000]uint16
602 utf16ConsoleBackLock mutex
603 )
604
605
606
607 func writeConsole(handle uintptr, buf unsafe.Pointer, bufLen int32) int {
608 const surr2 = (surrogateMin + surrogateMax + 1) / 2
609
610
611 lock(&utf16ConsoleBackLock)
612
613 b := (*[1 << 30]byte)(buf)[:bufLen]
614 s := *(*string)(unsafe.Pointer(&b))
615
616 utf16tmp := utf16ConsoleBack[:]
617
618 total := len(s)
619 w := 0
620 for _, r := range s {
621 if w >= len(utf16tmp)-2 {
622 writeConsoleUTF16(handle, utf16tmp[:w])
623 w = 0
624 }
625 if r < 0x10000 {
626 utf16tmp[w] = uint16(r)
627 w++
628 } else {
629 r -= 0x10000
630 utf16tmp[w] = surrogateMin + uint16(r>>10)&0x3ff
631 utf16tmp[w+1] = surr2 + uint16(r)&0x3ff
632 w += 2
633 }
634 }
635 writeConsoleUTF16(handle, utf16tmp[:w])
636 unlock(&utf16ConsoleBackLock)
637 return total
638 }
639
640
641
642
643 func writeConsoleUTF16(handle uintptr, b []uint16) {
644 l := uint32(len(b))
645 if l == 0 {
646 return
647 }
648 var written uint32
649 stdcall(_WriteConsoleW,
650 handle,
651 uintptr(unsafe.Pointer(&b[0])),
652 uintptr(l),
653 uintptr(unsafe.Pointer(&written)),
654 0,
655 )
656 return
657 }
658
659
660 func semasleep(ns int64) int32 {
661 const (
662 _WAIT_ABANDONED = 0x00000080
663 _WAIT_OBJECT_0 = 0x00000000
664 _WAIT_TIMEOUT = 0x00000102
665 _WAIT_FAILED = 0xFFFFFFFF
666 )
667
668 var result uintptr
669 if ns < 0 {
670 result = stdcall(_WaitForSingleObject, getg().m.waitsema, uintptr(windows.INFINITE))
671 } else {
672 start := nanotime()
673 elapsed := int64(0)
674 for {
675 ms := (ns - elapsed) / 1000000
676 if ms == 0 {
677 ms = 1
678 }
679 result = stdcall(_WaitForMultipleObjects, 2,
680 uintptr(unsafe.Pointer(&[2]uintptr{getg().m.waitsema, getg().m.resumesema})),
681 0, uintptr(ms))
682 if result != _WAIT_OBJECT_0+1 {
683
684 break
685 }
686 elapsed = nanotime() - start
687 if elapsed >= ns {
688 return -1
689 }
690 }
691 }
692 switch result {
693 case _WAIT_OBJECT_0:
694 return 0
695
696 case _WAIT_TIMEOUT:
697 return -1
698
699 case _WAIT_ABANDONED:
700 systemstack(func() {
701 throw("runtime.semasleep wait_abandoned")
702 })
703
704 case _WAIT_FAILED:
705 systemstack(func() {
706 print("runtime: waitforsingleobject wait_failed; errno=", getlasterror(), "\n")
707 throw("runtime.semasleep wait_failed")
708 })
709
710 default:
711 systemstack(func() {
712 print("runtime: waitforsingleobject unexpected; result=", result, "\n")
713 throw("runtime.semasleep unexpected")
714 })
715 }
716
717 return -1
718 }
719
720
721 func semawakeup(mp *m) {
722 if stdcall(_SetEvent, mp.waitsema) == 0 {
723 systemstack(func() {
724 print("runtime: setevent failed; errno=", getlasterror(), "\n")
725 throw("runtime.semawakeup")
726 })
727 }
728 }
729
730
731 func semacreate(mp *m) {
732 if mp.waitsema != 0 {
733 return
734 }
735 mp.waitsema = stdcall(_CreateEventA, 0, 0, 0, 0)
736 if mp.waitsema == 0 {
737 systemstack(func() {
738 print("runtime: createevent failed; errno=", getlasterror(), "\n")
739 throw("runtime.semacreate")
740 })
741 }
742 mp.resumesema = stdcall(_CreateEventA, 0, 0, 0, 0)
743 if mp.resumesema == 0 {
744 systemstack(func() {
745 print("runtime: createevent failed; errno=", getlasterror(), "\n")
746 throw("runtime.semacreate")
747 })
748 stdcall(_CloseHandle, mp.waitsema)
749 mp.waitsema = 0
750 }
751 }
752
753
754
755
756 func newosproc(mp *m) {
757 thandle, err := createThread(0, unsafe.Pointer(abi.FuncPCABI0(tstart_stdcall)), unsafe.Pointer(mp))
758 if thandle == 0 {
759 if atomic.Load(&exiting) != 0 {
760
761
762
763
764 lock(&deadlock)
765 lock(&deadlock)
766 }
767 print("runtime: failed to create new OS thread (have ", mcount(), " already; errno=", err, ")\n")
768 throw("runtime.newosproc")
769 }
770
771
772 stdcall(_CloseHandle, thandle)
773 }
774
775
776
777
778
779
780
781 func newosproc0(stacksize uintptr, fn unsafe.Pointer) {
782 thandle, err := createThread(stacksize, fn, nil)
783 if thandle == 0 {
784 print("runtime: failed to create new OS thread (errno=", err, ")\n")
785 throw("runtime: failed to create new OS thread\n")
786 }
787 stdcall_no_g(_CloseHandle, thandle)
788 }
789
790
791
792
793
794 func createThread(stackSize uintptr, fn unsafe.Pointer, arg unsafe.Pointer) (handle uintptr, err uint32) {
795 for tries := range 20 {
796
797 handle = stdcall_no_g(_CreateThread, 0, stackSize, uintptr(fn), uintptr(arg), 0, 0)
798 if handle == 0 {
799 err = getlasterror()
800 }
801 if handle == 0 && err == windows.ERROR_ACCESS_DENIED {
802
803 usleep_no_g(uint32(tries) * 1000)
804 continue
805 }
806 break
807 }
808 return handle, err
809 }
810
811
812
813 func libpreinit() {}
814
815 func exitThread(wait *atomic.Uint32) {
816
817
818 throw("exitThread")
819 }
820
821
822
823 func mpreinit(mp *m) {
824 }
825
826
827 func sigsave(p *sigset) {
828 }
829
830
831 func msigrestore(sigmask sigset) {
832 }
833
834
835
836 func clearSignalHandlers() {
837 }
838
839
840 func sigblock(exiting bool) {
841 }
842
843
844
845 func minit() {
846 var thandle uintptr
847 if stdcall(_DuplicateHandle, windows.CurrentProcess, windows.CurrentThread, windows.CurrentProcess, uintptr(unsafe.Pointer(&thandle)), 0, 0, windows.DUPLICATE_SAME_ACCESS) == 0 {
848 print("runtime.minit: duplicatehandle failed; errno=", getlasterror(), "\n")
849 throw("runtime.minit: duplicatehandle failed")
850 }
851
852 mp := getg().m
853 lock(&mp.threadLock)
854 mp.thread = thandle
855 mp.procid = uint64(stdcall(_GetCurrentThreadId))
856
857
858 if mp.highResTimer == 0 && haveHighResTimer {
859 mp.highResTimer = createHighResTimer()
860 if mp.highResTimer == 0 {
861 print("runtime: CreateWaitableTimerEx failed; errno=", getlasterror(), "\n")
862 throw("CreateWaitableTimerEx when creating timer failed")
863 }
864 }
865 if mp.waitIocpHandle == 0 && haveHighResSleep {
866 mp.waitIocpTimer = createHighResTimer()
867 if mp.waitIocpTimer == 0 {
868 print("runtime: CreateWaitableTimerEx failed; errno=", getlasterror(), "\n")
869 throw("CreateWaitableTimerEx when creating timer failed")
870 }
871 const GENERIC_ALL = 0x10000000
872 errno := stdcall(_NtCreateWaitCompletionPacket, uintptr(unsafe.Pointer(&mp.waitIocpHandle)), GENERIC_ALL, 0)
873 if mp.waitIocpHandle == 0 {
874 print("runtime: NtCreateWaitCompletionPacket failed; errno=", errno, "\n")
875 throw("NtCreateWaitCompletionPacket failed")
876 }
877 }
878 unlock(&mp.threadLock)
879
880
881
882 var mbi windows.MemoryBasicInformation
883 res := stdcall(_VirtualQuery, uintptr(unsafe.Pointer(&mbi)), uintptr(unsafe.Pointer(&mbi)), unsafe.Sizeof(mbi))
884 if res == 0 {
885 print("runtime: VirtualQuery failed; errno=", getlasterror(), "\n")
886 throw("VirtualQuery for stack base failed")
887 }
888
889
890
891
892
893
894 base := mbi.AllocationBase + 16<<10
895
896 g0 := getg()
897 if base > g0.stack.hi || g0.stack.hi-base > 64<<20 {
898 print("runtime: g0 stack [", hex(base), ",", hex(g0.stack.hi), ")\n")
899 throw("bad g0 stack")
900 }
901 g0.stack.lo = base
902 g0.stackguard0 = g0.stack.lo + stackGuard
903 g0.stackguard1 = g0.stackguard0
904
905 stackcheck()
906 }
907
908
909
910
911 func unminit() {
912 mp := getg().m
913 lock(&mp.threadLock)
914 if mp.thread != 0 {
915 stdcall(_CloseHandle, mp.thread)
916 mp.thread = 0
917 }
918 unlock(&mp.threadLock)
919
920 mp.procid = 0
921 }
922
923
924
925
926
927
928
929
930 func mdestroy(mp *m) {
931 if mp.highResTimer != 0 {
932 stdcall(_CloseHandle, mp.highResTimer)
933 mp.highResTimer = 0
934 }
935 if mp.waitIocpTimer != 0 {
936 stdcall(_CloseHandle, mp.waitIocpTimer)
937 mp.waitIocpTimer = 0
938 }
939 if mp.waitIocpHandle != 0 {
940 stdcall(_CloseHandle, mp.waitIocpHandle)
941 mp.waitIocpHandle = 0
942 }
943 if mp.waitsema != 0 {
944 stdcall(_CloseHandle, mp.waitsema)
945 mp.waitsema = 0
946 }
947 if mp.resumesema != 0 {
948 stdcall(_CloseHandle, mp.resumesema)
949 mp.resumesema = 0
950 }
951 }
952
953
954
955
956
957
958 func stdcall_no_g(fn stdFunction, args ...uintptr) uintptr {
959 call := windows.StdCallInfo{
960 Fn: uintptr(unsafe.Pointer(fn)),
961 N: uintptr(len(args)),
962 }
963 if len(args) > 0 {
964 call.Args = uintptr(abi.NoEscape(unsafe.Pointer(&args[0])))
965 }
966 windows.StdCall(&call)
967 return call.R1
968 }
969
970
971
972
973
974
975
976
977 func stdcall(fn stdFunction, args ...uintptr) uintptr {
978 gp := getg()
979 mp := gp.m
980 mp.stdCallInfo.Fn = uintptr(unsafe.Pointer(fn))
981 mp.stdCallInfo.N = uintptr(len(args))
982 if len(args) > 0 {
983 mp.stdCallInfo.Args = uintptr(abi.NoEscape(unsafe.Pointer(&args[0])))
984 }
985 resetLibcall := false
986 if mp.profilehz != 0 && mp.libcallsp == 0 {
987
988 mp.libcallg.set(gp)
989 mp.libcallpc = sys.GetCallerPC()
990
991
992 mp.libcallsp = sys.GetCallerSP()
993 resetLibcall = true
994 }
995 asmcgocall(asmstdcallAddr, unsafe.Pointer(&mp.stdCallInfo))
996 if resetLibcall {
997 mp.libcallsp = 0
998 }
999 return mp.stdCallInfo.R1
1000 }
1001
1002
1003
1004
1005 func osyield_no_g() {
1006 stdcall_no_g(_SwitchToThread)
1007 }
1008
1009
1010 func osyield() {
1011 systemstack(func() {
1012 stdcall(_SwitchToThread)
1013 })
1014 }
1015
1016
1017 func usleep_no_g(us uint32) {
1018 timeout := uintptr(us) / 1000
1019 stdcall_no_g(_WaitForSingleObject, windows.INVALID_HANDLE_VALUE, timeout)
1020 }
1021
1022
1023 func usleep(us uint32) {
1024 systemstack(func() {
1025 var h, timeout uintptr
1026
1027
1028 if haveHighResTimer && getg().m.highResTimer != 0 {
1029 h = getg().m.highResTimer
1030 dt := -10 * int64(us)
1031 stdcall(_SetWaitableTimer, h, uintptr(unsafe.Pointer(&dt)), 0, 0, 0, 0)
1032 timeout = windows.INFINITE
1033 } else {
1034 h = windows.INVALID_HANDLE_VALUE
1035 timeout = uintptr(us) / 1000
1036 }
1037 stdcall(_WaitForSingleObject, h, timeout)
1038 })
1039 }
1040
1041 func ctrlHandler(_type uint32) uintptr {
1042 var s uint32
1043
1044 switch _type {
1045 case windows.CTRL_C_EVENT, windows.CTRL_BREAK_EVENT:
1046 s = windows.SIGINT
1047 case windows.CTRL_CLOSE_EVENT, windows.CTRL_LOGOFF_EVENT, windows.CTRL_SHUTDOWN_EVENT:
1048 s = windows.SIGTERM
1049 default:
1050 return 0
1051 }
1052
1053 if sigsend(s) {
1054 if s == windows.SIGTERM {
1055
1056
1057
1058
1059 block()
1060 }
1061 return 1
1062 }
1063 return 0
1064 }
1065
1066
1067 func callbackasm1()
1068
1069 var profiletimer uintptr
1070
1071 func profilem(mp *m, thread uintptr) {
1072
1073 var c *windows.Context
1074 var cbuf [unsafe.Sizeof(*c) + 15]byte
1075 c = (*windows.Context)(unsafe.Pointer((uintptr(unsafe.Pointer(&cbuf[15]))) &^ 15))
1076
1077 c.ContextFlags = windows.CONTEXT_CONTROL
1078 stdcall(_GetThreadContext, thread, uintptr(unsafe.Pointer(c)))
1079
1080 gp := gFromSP(mp, c.SP())
1081
1082 sigprof(c.PC(), c.SP(), c.LR(), gp, mp)
1083 }
1084
1085 func gFromSP(mp *m, sp uintptr) *g {
1086 if gp := mp.g0; gp != nil && gp.stack.lo < sp && sp < gp.stack.hi {
1087 return gp
1088 }
1089 if gp := mp.gsignal; gp != nil && gp.stack.lo < sp && sp < gp.stack.hi {
1090 return gp
1091 }
1092 if gp := mp.curg; gp != nil && gp.stack.lo < sp && sp < gp.stack.hi {
1093 return gp
1094 }
1095 return nil
1096 }
1097
1098 func profileLoop() {
1099 stdcall(_SetThreadPriority, windows.CurrentThread, windows.THREAD_PRIORITY_HIGHEST)
1100
1101 for {
1102 stdcall(_WaitForSingleObject, profiletimer, windows.INFINITE)
1103 first := (*m)(atomic.Loadp(unsafe.Pointer(&allm)))
1104 for mp := first; mp != nil; mp = mp.alllink {
1105 if mp == getg().m {
1106
1107 continue
1108 }
1109
1110 lock(&mp.threadLock)
1111
1112
1113
1114 if mp.thread == 0 || mp.profilehz == 0 || mp.blocked {
1115 unlock(&mp.threadLock)
1116 continue
1117 }
1118
1119 var thread uintptr
1120 if stdcall(_DuplicateHandle, windows.CurrentProcess, mp.thread, windows.CurrentProcess, uintptr(unsafe.Pointer(&thread)), 0, 0, windows.DUPLICATE_SAME_ACCESS) == 0 {
1121 print("runtime: duplicatehandle failed; errno=", getlasterror(), "\n")
1122 throw("duplicatehandle failed")
1123 }
1124 unlock(&mp.threadLock)
1125
1126
1127
1128
1129
1130 if int32(stdcall(_SuspendThread, thread)) == -1 {
1131
1132 stdcall(_CloseHandle, thread)
1133 continue
1134 }
1135 if mp.profilehz != 0 && !mp.blocked {
1136
1137
1138 profilem(mp, thread)
1139 }
1140 stdcall(_ResumeThread, thread)
1141 stdcall(_CloseHandle, thread)
1142 }
1143 }
1144 }
1145
1146 func setProcessCPUProfiler(hz int32) {
1147 if profiletimer == 0 {
1148 var timer uintptr
1149 if haveHighResTimer {
1150 timer = createHighResTimer()
1151 } else {
1152 timer = stdcall(_CreateWaitableTimerA, 0, 0, 0)
1153 }
1154 atomic.Storeuintptr(&profiletimer, timer)
1155 newm(profileLoop, nil, -1)
1156 }
1157 }
1158
1159 func setThreadCPUProfiler(hz int32) {
1160 ms := int32(0)
1161 due := ^int64(^uint64(1 << 63))
1162 if hz > 0 {
1163 ms = 1000 / hz
1164 if ms == 0 {
1165 ms = 1
1166 }
1167 due = int64(ms) * -10000
1168 }
1169 stdcall(_SetWaitableTimer, profiletimer, uintptr(unsafe.Pointer(&due)), uintptr(ms), 0, 0, 0)
1170 atomic.Store((*uint32)(unsafe.Pointer(&getg().m.profilehz)), uint32(hz))
1171 }
1172
1173 const preemptMSupported = true
1174
1175
1176
1177 var suspendLock mutex
1178
1179 func preemptM(mp *m) {
1180 if mp == getg().m {
1181 throw("self-preempt")
1182 }
1183
1184
1185 if !atomic.Cas(&mp.preemptExtLock, 0, 1) {
1186
1187
1188 mp.preemptGen.Add(1)
1189 return
1190 }
1191
1192
1193 lock(&mp.threadLock)
1194 if mp.thread == 0 {
1195
1196 unlock(&mp.threadLock)
1197 atomic.Store(&mp.preemptExtLock, 0)
1198 mp.preemptGen.Add(1)
1199 return
1200 }
1201 var thread uintptr
1202 if stdcall(_DuplicateHandle, windows.CurrentProcess, mp.thread, windows.CurrentProcess, uintptr(unsafe.Pointer(&thread)), 0, 0, windows.DUPLICATE_SAME_ACCESS) == 0 {
1203 print("runtime.preemptM: duplicatehandle failed; errno=", getlasterror(), "\n")
1204 throw("runtime.preemptM: duplicatehandle failed")
1205 }
1206 unlock(&mp.threadLock)
1207
1208
1209 var c *windows.Context
1210 var cbuf [unsafe.Sizeof(*c) + 15]byte
1211 c = (*windows.Context)(unsafe.Pointer((uintptr(unsafe.Pointer(&cbuf[15]))) &^ 15))
1212 c.ContextFlags = windows.CONTEXT_CONTROL
1213
1214
1215
1216
1217
1218
1219 lock(&suspendLock)
1220
1221
1222 if int32(stdcall(_SuspendThread, thread)) == -1 {
1223 unlock(&suspendLock)
1224 stdcall(_CloseHandle, thread)
1225 atomic.Store(&mp.preemptExtLock, 0)
1226
1227
1228 mp.preemptGen.Add(1)
1229 return
1230 }
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241 stdcall(_GetThreadContext, thread, uintptr(unsafe.Pointer(c)))
1242
1243 unlock(&suspendLock)
1244
1245
1246 gp := gFromSP(mp, c.SP())
1247 if gp != nil && wantAsyncPreempt(gp) {
1248 if ok, resumePC := isAsyncSafePoint(gp, c.PC(), c.SP(), c.LR()); ok {
1249
1250 targetPC := abi.FuncPCABI0(asyncPreempt)
1251 c.PushCall(targetPC, resumePC)
1252 stdcall(_SetThreadContext, thread, uintptr(unsafe.Pointer(c)))
1253 }
1254 }
1255
1256 atomic.Store(&mp.preemptExtLock, 0)
1257
1258
1259 mp.preemptGen.Add(1)
1260
1261 stdcall(_ResumeThread, thread)
1262 stdcall(_CloseHandle, thread)
1263 }
1264
1265
1266
1267
1268
1269
1270
1271
1272 func osPreemptExtEnter(mp *m) {
1273 for !atomic.Cas(&mp.preemptExtLock, 0, 1) {
1274
1275
1276
1277
1278
1279
1280
1281
1282 osyield()
1283 }
1284
1285 }
1286
1287
1288
1289
1290
1291
1292
1293 func osPreemptExtExit(mp *m) {
1294 atomic.Store(&mp.preemptExtLock, 0)
1295 }
1296
View as plain text