Source file
src/runtime/netpoll_windows.go
Documentation: runtime
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 *pollDesc
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
55 if stdcall4(_CreateIoCompletionPort, fd, iocphandle, uintptr(unsafe.Pointer(pd)), 0) == 0 {
56 return int32(getlasterror())
57 }
58 return 0
59 }
60
61 func netpollclose(fd uintptr) int32 {
62
63 return 0
64 }
65
66 func netpollarm(pd *pollDesc, mode int) {
67 throw("runtime: unused")
68 }
69
70 func netpollBreak() {
71
72 if !netpollWakeSig.CompareAndSwap(0, 1) {
73 return
74 }
75
76 if stdcall4(_PostQueuedCompletionStatus, iocphandle, 0, 0, 0) == 0 {
77 println("runtime: netpoll: PostQueuedCompletionStatus failed (errno=", getlasterror(), ")")
78 throw("runtime: netpoll: PostQueuedCompletionStatus failed")
79 }
80 }
81
82
83
84
85
86
87 func netpoll(delay int64) (gList, int32) {
88 var entries [64]overlappedEntry
89 var wait, qty, flags, n, i uint32
90 var errno int32
91 var op *net_op
92 var toRun gList
93
94 mp := getg().m
95
96 if iocphandle == _INVALID_HANDLE_VALUE {
97 return gList{}, 0
98 }
99 if delay < 0 {
100 wait = _INFINITE
101 } else if delay == 0 {
102 wait = 0
103 } else if delay < 1e6 {
104 wait = 1
105 } else if delay < 1e15 {
106 wait = uint32(delay / 1e6)
107 } else {
108
109
110 wait = 1e9
111 }
112
113 n = uint32(len(entries) / int(gomaxprocs))
114 if n < 8 {
115 n = 8
116 }
117 if delay != 0 {
118 mp.blocked = true
119 }
120 if stdcall6(_GetQueuedCompletionStatusEx, iocphandle, uintptr(unsafe.Pointer(&entries[0])), uintptr(n), uintptr(unsafe.Pointer(&n)), uintptr(wait), 0) == 0 {
121 mp.blocked = false
122 errno = int32(getlasterror())
123 if errno == _WAIT_TIMEOUT {
124 return gList{}, 0
125 }
126 println("runtime: GetQueuedCompletionStatusEx failed (errno=", errno, ")")
127 throw("runtime: netpoll failed")
128 }
129 mp.blocked = false
130 delta := int32(0)
131 for i = 0; i < n; i++ {
132 op = entries[i].op
133 if op != nil && op.pd == entries[i].key {
134 errno = 0
135 qty = 0
136 if stdcall5(_WSAGetOverlappedResult, op.pd.fd, uintptr(unsafe.Pointer(op)), uintptr(unsafe.Pointer(&qty)), 0, uintptr(unsafe.Pointer(&flags))) == 0 {
137 errno = int32(getlasterror())
138 }
139 delta += handlecompletion(&toRun, op, errno, qty)
140 } else {
141 netpollWakeSig.Store(0)
142 if delay == 0 {
143
144
145 netpollBreak()
146 }
147 }
148 }
149 return toRun, delta
150 }
151
152 func handlecompletion(toRun *gList, op *net_op, errno int32, qty uint32) int32 {
153 mode := op.mode
154 if mode != 'r' && mode != 'w' {
155 println("runtime: GetQueuedCompletionStatusEx returned invalid mode=", mode)
156 throw("runtime: netpoll failed")
157 }
158 op.errno = errno
159 op.qty = qty
160 return netpollready(toRun, op.pd, mode)
161 }
162
View as plain text