Source file
src/runtime/netpoll_wasip1.go
1
2
3
4
5
6
7 package runtime
8
9 import "unsafe"
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36 const _EINTR = 27
37
38 var (
39 evts []event
40 subs []subscription
41 pds []*pollDesc
42 mtx mutex
43 )
44
45 func netpollinit() {
46
47
48
49
50
51 subs = make([]subscription, 1, 128)
52 evts = make([]event, 0, 128)
53 pds = make([]*pollDesc, 0, 128)
54
55 timeout := &subs[0]
56 eventtype := timeout.u.eventtype()
57 *eventtype = eventtypeClock
58 clock := timeout.u.subscriptionClock()
59 clock.id = clockMonotonic
60 clock.precision = 1e3
61 }
62
63 func netpollIsPollDescriptor(fd uintptr) bool {
64 return false
65 }
66
67 func netpollopen(fd uintptr, pd *pollDesc) int32 {
68 lock(&mtx)
69
70
71
72
73 pds = append(pds, pd)
74
75
76
77
78
79 pd.user = uint32(disarmed)<<16 | uint32(disarmed)
80
81 unlock(&mtx)
82 return 0
83 }
84
85 const disarmed = 0xFFFF
86
87 func netpollarm(pd *pollDesc, mode int) {
88 lock(&mtx)
89
90 var s subscription
91
92 s.userdata = userdata(uintptr(unsafe.Pointer(pd)))
93
94 fdReadwrite := s.u.subscriptionFdReadwrite()
95 fdReadwrite.fd = int32(pd.fd)
96
97 ridx := int(pd.user >> 16)
98 widx := int(pd.user & 0xFFFF)
99
100 if (mode == 'r' && ridx != disarmed) || (mode == 'w' && widx != disarmed) {
101 unlock(&mtx)
102 return
103 }
104
105 eventtype := s.u.eventtype()
106 switch mode {
107 case 'r':
108 *eventtype = eventtypeFdRead
109 ridx = len(subs)
110 case 'w':
111 *eventtype = eventtypeFdWrite
112 widx = len(subs)
113 }
114
115 if len(subs) == disarmed {
116 throw("overflow")
117 }
118
119 pd.user = uint32(ridx)<<16 | uint32(widx)
120
121 subs = append(subs, s)
122 evts = append(evts, event{})
123
124 unlock(&mtx)
125 }
126
127 func netpolldisarm(pd *pollDesc, mode int32) {
128 switch mode {
129 case 'r':
130 removesub(int(pd.user >> 16))
131 case 'w':
132 removesub(int(pd.user & 0xFFFF))
133 case 'r' + 'w':
134 removesub(int(pd.user >> 16))
135 removesub(int(pd.user & 0xFFFF))
136 }
137 }
138
139 func removesub(i int) {
140 if i == disarmed {
141 return
142 }
143 j := len(subs) - 1
144
145 pdi := (*pollDesc)(unsafe.Pointer(uintptr(subs[i].userdata)))
146 pdj := (*pollDesc)(unsafe.Pointer(uintptr(subs[j].userdata)))
147
148 swapsub(pdi, i, disarmed)
149 swapsub(pdj, j, i)
150
151 subs = subs[:j]
152 }
153
154 func swapsub(pd *pollDesc, from, to int) {
155 if from == to {
156 return
157 }
158 ridx := int(pd.user >> 16)
159 widx := int(pd.user & 0xFFFF)
160 if ridx == from {
161 ridx = to
162 } else if widx == from {
163 widx = to
164 }
165 pd.user = uint32(ridx)<<16 | uint32(widx)
166 if to != disarmed {
167 subs[to], subs[from] = subs[from], subs[to]
168 }
169 }
170
171 func netpollclose(fd uintptr) int32 {
172 lock(&mtx)
173 for i := 0; i < len(pds); i++ {
174 if pds[i].fd == fd {
175 netpolldisarm(pds[i], 'r'+'w')
176 pds[i] = pds[len(pds)-1]
177 pds = pds[:len(pds)-1]
178 break
179 }
180 }
181 unlock(&mtx)
182 return 0
183 }
184
185 func netpollBreak() {}
186
187 func netpoll(delay int64) (gList, int32) {
188 lock(&mtx)
189
190
191
192
193 pollsubs := subs
194 if delay >= 0 {
195 timeout := &subs[0]
196 clock := timeout.u.subscriptionClock()
197 clock.timeout = uint64(delay)
198 } else {
199 pollsubs = subs[1:]
200 }
201
202 if len(pollsubs) == 0 {
203 unlock(&mtx)
204 return gList{}, 0
205 }
206
207 evts = evts[:len(pollsubs)]
208 clear(evts)
209
210 retry:
211 var nevents size
212 errno := poll_oneoff(&pollsubs[0], &evts[0], uint32(len(pollsubs)), &nevents)
213 if errno != 0 {
214 if errno != _EINTR {
215 println("errno=", errno, " len(pollsubs)=", len(pollsubs))
216 throw("poll_oneoff failed")
217 }
218
219
220 if delay > 0 {
221 unlock(&mtx)
222 return gList{}, 0
223 }
224 goto retry
225 }
226
227 var toRun gList
228 delta := int32(0)
229 for i := 0; i < int(nevents); i++ {
230 e := &evts[i]
231 if e.typ == eventtypeClock {
232 continue
233 }
234
235 hangup := e.fdReadwrite.flags&fdReadwriteHangup != 0
236 var mode int32
237 if e.typ == eventtypeFdRead || e.error != 0 || hangup {
238 mode += 'r'
239 }
240 if e.typ == eventtypeFdWrite || e.error != 0 || hangup {
241 mode += 'w'
242 }
243 if mode != 0 {
244 pd := (*pollDesc)(unsafe.Pointer(uintptr(e.userdata)))
245 netpolldisarm(pd, mode)
246 pd.setEventErr(e.error != 0, 0)
247 delta += netpollready(&toRun, pd, mode)
248 }
249 }
250
251 unlock(&mtx)
252 return toRun, delta
253 }
254
View as plain text