Source file
src/runtime/netpoll_windows.go
1
2
3
4
5 package runtime
6
7 import (
8 "runtime/internal/atomic"
9 "unsafe"
10 )
11
12 const _DWORD_MAX = 0xffffffff
13
14 const _INVALID_HANDLE_VALUE = ^uintptr(0)
15
16
17
18 type net_op struct {
19
20 o overlapped
21
22 pd *pollDesc
23 mode int32
24 errno int32
25 qty uint32
26 }
27
28 type overlappedEntry struct {
29 key uintptr
30 op *net_op
31 internal uintptr
32 qty uint32
33 }
34
35 var (
36 iocphandle uintptr = _INVALID_HANDLE_VALUE
37
38 netpollWakeSig atomic.Uint32
39 )
40
41 func netpollinit() {
42 iocphandle = stdcall4(_CreateIoCompletionPort, _INVALID_HANDLE_VALUE, 0, 0, _DWORD_MAX)
43 if iocphandle == 0 {
44 println("runtime: CreateIoCompletionPort failed (errno=", getlasterror(), ")")
45 throw("runtime: netpollinit failed")
46 }
47 }
48
49 func netpollIsPollDescriptor(fd uintptr) bool {
50 return fd == iocphandle
51 }
52
53 func netpollopen(fd uintptr, pd *pollDesc) int32 {
54 if stdcall4(_CreateIoCompletionPort, fd, iocphandle, 0, 0) == 0 {
55 return int32(getlasterror())
56 }
57 return 0
58 }
59
60 func netpollclose(fd uintptr) int32 {
61
62 return 0
63 }
64
65 func netpollarm(pd *pollDesc, mode int) {
66 throw("runtime: unused")
67 }
68
69 func netpollBreak() {
70
71 if !netpollWakeSig.CompareAndSwap(0, 1) {
72 return
73 }
74
75 if stdcall4(_PostQueuedCompletionStatus, iocphandle, 0, 0, 0) == 0 {
76 println("runtime: netpoll: PostQueuedCompletionStatus failed (errno=", getlasterror(), ")")
77 throw("runtime: netpoll: PostQueuedCompletionStatus failed")
78 }
79 }
80
81
82
83
84
85
86 func netpoll(delay int64) gList {
87 var entries [64]overlappedEntry
88 var wait, qty, flags, n, i uint32
89 var errno int32
90 var op *net_op
91 var toRun gList
92
93 mp := getg().m
94
95 if iocphandle == _INVALID_HANDLE_VALUE {
96 return gList{}
97 }
98 if delay < 0 {
99 wait = _INFINITE
100 } else if delay == 0 {
101 wait = 0
102 } else if delay < 1e6 {
103 wait = 1
104 } else if delay < 1e15 {
105 wait = uint32(delay / 1e6)
106 } else {
107
108
109 wait = 1e9
110 }
111
112 n = uint32(len(entries) / int(gomaxprocs))
113 if n < 8 {
114 n = 8
115 }
116 if delay != 0 {
117 mp.blocked = true
118 }
119 if stdcall6(_GetQueuedCompletionStatusEx, iocphandle, uintptr(unsafe.Pointer(&entries[0])), uintptr(n), uintptr(unsafe.Pointer(&n)), uintptr(wait), 0) == 0 {
120 mp.blocked = false
121 errno = int32(getlasterror())
122 if errno == _WAIT_TIMEOUT {
123 return gList{}
124 }
125 println("runtime: GetQueuedCompletionStatusEx failed (errno=", errno, ")")
126 throw("runtime: netpoll failed")
127 }
128 mp.blocked = false
129 for i = 0; i < n; i++ {
130 op = entries[i].op
131 if op != nil {
132 errno = 0
133 qty = 0
134 if stdcall5(_WSAGetOverlappedResult, op.pd.fd, uintptr(unsafe.Pointer(op)), uintptr(unsafe.Pointer(&qty)), 0, uintptr(unsafe.Pointer(&flags))) == 0 {
135 errno = int32(getlasterror())
136 }
137 handlecompletion(&toRun, op, errno, qty)
138 } else {
139 netpollWakeSig.Store(0)
140 if delay == 0 {
141
142
143 netpollBreak()
144 }
145 }
146 }
147 return toRun
148 }
149
150 func handlecompletion(toRun *gList, op *net_op, errno int32, qty uint32) {
151 mode := op.mode
152 if mode != 'r' && mode != 'w' {
153 println("runtime: GetQueuedCompletionStatusEx returned invalid mode=", mode)
154 throw("runtime: netpoll failed")
155 }
156 op.errno = errno
157 op.qty = qty
158 netpollready(toRun, op.pd, mode)
159 }
160
View as plain text