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