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