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