Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(1408)

Delta Between Two Patch Sets: src/pkg/runtime/netpoll.goc

Issue 8670044: code review 8670044: net: implement netpoll for windows (Closed)
Left Patch Set: diff -r 0c9561ddf631 https://go.googlecode.com/hg/ Created 10 years, 11 months ago
Right Patch Set: diff -r 5ee81a14cdfe https://go.googlecode.com/hg/ Created 10 years, 8 months ago
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
Left: Side by side diff | Download
Right: Side by side diff | Download
« no previous file with change/comment | « src/pkg/runtime/defs_windows_amd64.h ('k') | src/pkg/runtime/netpoll_stub.c » ('j') | no next file with change/comment »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
LEFTRIGHT
1 // Copyright 2013 The Go Authors. All rights reserved. 1 // Copyright 2013 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style 2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file. 3 // license that can be found in the LICENSE file.
4 4
5 // +build darwin linux windows 5 // +build darwin linux windows
6 6
7 package net 7 package net
8 8
9 #include "runtime.h" 9 #include "runtime.h"
10 #include "defs_GOOS_GOARCH.h" 10 #include "defs_GOOS_GOARCH.h"
(...skipping 29 matching lines...) Expand all
40 { 40 {
41 Lock; 41 Lock;
42 PollDesc* first; 42 PollDesc* first;
43 // PollDesc objects must be type-stable, 43 // PollDesc objects must be type-stable,
44 // because we can get ready notification from epoll/kqueue 44 // because we can get ready notification from epoll/kqueue
45 // after the descriptor is closed/reused. 45 // after the descriptor is closed/reused.
46 // Stale notifications are detected using seq variable, 46 // Stale notifications are detected using seq variable,
47 // seq is incremented when deadlines are changed or descriptor is reused . 47 // seq is incremented when deadlines are changed or descriptor is reused .
48 } pollcache; 48 } pollcache;
49 49
50 static void» netpollblock(PollDesc*, int32); 50 static bool» netpollblock(PollDesc*, int32);
51 static G*» netpollunblock(PollDesc*, int32); 51 static G*» netpollunblock(PollDesc*, int32, bool);
52 static void deadline(int64, Eface); 52 static void deadline(int64, Eface);
53 static void readDeadline(int64, Eface); 53 static void readDeadline(int64, Eface);
54 static void writeDeadline(int64, Eface); 54 static void writeDeadline(int64, Eface);
55 static PollDesc* allocPollDesc(void); 55 static PollDesc* allocPollDesc(void);
56 static intgo checkerr(PollDesc *pd, int32 mode); 56 static intgo checkerr(PollDesc *pd, int32 mode);
57 57
58 static FuncVal deadlineFn = {(void(*)(void))deadline}; 58 static FuncVal deadlineFn = {(void(*)(void))deadline};
59 static FuncVal readDeadlineFn = {(void(*)(void))readDeadline}; 59 static FuncVal readDeadlineFn = {(void(*)(void))readDeadline};
60 static FuncVal writeDeadlineFn = {(void(*)(void))writeDeadline}; 60 static FuncVal writeDeadlineFn = {(void(*)(void))writeDeadline};
61 61
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
105 pd->rg = nil; 105 pd->rg = nil;
106 else if(mode == 'w') 106 else if(mode == 'w')
107 pd->wg = nil; 107 pd->wg = nil;
108 ret: 108 ret:
109 runtime·unlock(pd); 109 runtime·unlock(pd);
110 } 110 }
111 111
112 func runtime_pollWait(pd *PollDesc, mode int) (err int) { 112 func runtime_pollWait(pd *PollDesc, mode int) (err int) {
113 runtime·lock(pd); 113 runtime·lock(pd);
114 err = checkerr(pd, mode); 114 err = checkerr(pd, mode);
115 » if(err) 115 » if(err == 0) {
116 » » goto ret; 116 » » if(!netpollblock(pd, mode)) {
117 » netpollblock(pd, mode); 117 » » » err = checkerr(pd, mode);
118 » err = checkerr(pd, mode); 118 » » » if(err == 0)
119 ret: 119 » » » » runtime·throw("runtime_pollWait: unblocked by io ready");
120 » » }
121 » }
120 runtime·unlock(pd); 122 runtime·unlock(pd);
121 } 123 }
122 124
123 func runtime_pollWaitCanceled(pd *PollDesc, mode int) { 125 func runtime_pollWaitCanceled(pd *PollDesc, mode int) {
124 runtime·lock(pd); 126 runtime·lock(pd);
125 » netpollblock(pd, mode); 127 » // wait for ioready, ignore closing or timeouts.
128 » while(!netpollblock(pd, mode))
129 » » ;
126 runtime·unlock(pd); 130 runtime·unlock(pd);
127 } 131 }
128 132
129 func runtime_pollSetDeadline(pd *PollDesc, d int64, mode int) { 133 func runtime_pollSetDeadline(pd *PollDesc, d int64, mode int) {
130 runtime·lock(pd); 134 runtime·lock(pd);
131 if(pd->closing) 135 if(pd->closing)
132 goto ret; 136 goto ret;
133 pd->seq++; // invalidate current timers 137 pd->seq++; // invalidate current timers
134 // Reset current timers. 138 // Reset current timers.
135 if(pd->rt.fv) { 139 if(pd->rt.fv) {
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
178 } 182 }
179 183
180 func runtime_pollUnblock(pd *PollDesc) { 184 func runtime_pollUnblock(pd *PollDesc) {
181 G *rg, *wg; 185 G *rg, *wg;
182 186
183 runtime·lock(pd); 187 runtime·lock(pd);
184 if(pd->closing) 188 if(pd->closing)
185 runtime·throw("runtime_pollUnblock: already closing"); 189 runtime·throw("runtime_pollUnblock: already closing");
186 pd->closing = true; 190 pd->closing = true;
187 pd->seq++; 191 pd->seq++;
188 » rg = netpollunblock(pd, 'r'); 192 » rg = netpollunblock(pd, 'r', false);
189 » wg = netpollunblock(pd, 'w'); 193 » wg = netpollunblock(pd, 'w', false);
190 if(pd->rt.fv) { 194 if(pd->rt.fv) {
191 runtime·deltimer(&pd->rt); 195 runtime·deltimer(&pd->rt);
192 pd->rt.fv = nil; 196 pd->rt.fv = nil;
193 } 197 }
194 if(pd->wt.fv) { 198 if(pd->wt.fv) {
195 runtime·deltimer(&pd->wt); 199 runtime·deltimer(&pd->wt);
196 pd->wt.fv = nil; 200 pd->wt.fv = nil;
197 } 201 }
198 runtime·unlock(pd); 202 runtime·unlock(pd);
199 if(rg) 203 if(rg)
200 runtime·ready(rg); 204 runtime·ready(rg);
201 if(wg) 205 if(wg)
202 runtime·ready(wg); 206 runtime·ready(wg);
203 } 207 }
204 208
205 // make pd ready, newly runnable goroutines (if any) are enqueued info gpp list 209 // make pd ready, newly runnable goroutines (if any) are enqueued info gpp list
206 void 210 void
207 runtime·netpollready(G **gpp, PollDesc *pd, int32 mode) 211 runtime·netpollready(G **gpp, PollDesc *pd, int32 mode)
208 { 212 {
209 G *rg, *wg; 213 G *rg, *wg;
210 214
211 rg = wg = nil; 215 rg = wg = nil;
212 runtime·lock(pd); 216 runtime·lock(pd);
213 if(mode == 'r' || mode == 'r'+'w') 217 if(mode == 'r' || mode == 'r'+'w')
214 » » rg = netpollunblock(pd, 'r'); 218 » » rg = netpollunblock(pd, 'r', true);
215 if(mode == 'w' || mode == 'r'+'w') 219 if(mode == 'w' || mode == 'r'+'w')
216 » » wg = netpollunblock(pd, 'w'); 220 » » wg = netpollunblock(pd, 'w', true);
217 runtime·unlock(pd); 221 runtime·unlock(pd);
218 if(rg) { 222 if(rg) {
219 rg->schedlink = *gpp; 223 rg->schedlink = *gpp;
220 *gpp = rg; 224 *gpp = rg;
221 } 225 }
222 if(wg) { 226 if(wg) {
223 wg->schedlink = *gpp; 227 wg->schedlink = *gpp;
224 *gpp = wg; 228 *gpp = wg;
225 } 229 }
226 } 230 }
227 231
228 static intgo 232 static intgo
229 checkerr(PollDesc *pd, int32 mode) 233 checkerr(PollDesc *pd, int32 mode)
230 { 234 {
231 if(pd->closing) 235 if(pd->closing)
232 return 1; // errClosing 236 return 1; // errClosing
233 if((mode == 'r' && pd->rd < 0) || (mode == 'w' && pd->wd < 0)) 237 if((mode == 'r' && pd->rd < 0) || (mode == 'w' && pd->wd < 0))
234 return 2; // errTimeout 238 return 2; // errTimeout
235 return 0; 239 return 0;
236 } 240 }
237 241
238 static void 242 // returns true if IO is ready, or false if timedout or closed
243 static bool
239 netpollblock(PollDesc *pd, int32 mode) 244 netpollblock(PollDesc *pd, int32 mode)
240 { 245 {
241 G **gpp; 246 G **gpp;
242 247
243 gpp = &pd->rg; 248 gpp = &pd->rg;
244 if(mode == 'w') 249 if(mode == 'w')
245 gpp = &pd->wg; 250 gpp = &pd->wg;
246 if(*gpp == READY) { 251 if(*gpp == READY) {
247 *gpp = nil; 252 *gpp = nil;
248 » » return; 253 » » return true;
249 } 254 }
250 if(*gpp != nil) 255 if(*gpp != nil)
251 runtime·throw("epoll: double wait"); 256 runtime·throw("epoll: double wait");
252 *gpp = g; 257 *gpp = g;
253 runtime·park(runtime·unlock, &pd->Lock, "IO wait"); 258 runtime·park(runtime·unlock, &pd->Lock, "IO wait");
254 runtime·lock(pd); 259 runtime·lock(pd);
260 if(g->param)
261 return true;
262 return false;
255 } 263 }
256 264
257 static G* 265 static G*
258 netpollunblock(PollDesc *pd, int32 mode) 266 netpollunblock(PollDesc *pd, int32 mode, bool ioready)
259 { 267 {
260 G **gpp, *old; 268 G **gpp, *old;
261 269
262 gpp = &pd->rg; 270 gpp = &pd->rg;
263 if(mode == 'w') 271 if(mode == 'w')
264 gpp = &pd->wg; 272 gpp = &pd->wg;
265 if(*gpp == READY) 273 if(*gpp == READY)
266 return nil; 274 return nil;
267 if(*gpp == nil) { 275 if(*gpp == nil) {
268 » » *gpp = READY; 276 » » // Only set READY for ioready. runtime_pollWait
277 » » // will check for timeout/cancel before waiting.
278 » » if(ioready)
279 » » » *gpp = READY;
269 return nil; 280 return nil;
270 } 281 }
271 old = *gpp; 282 old = *gpp;
283 // pass unblock reason onto blocked g
284 old->param = (void*)ioready;
272 *gpp = nil; 285 *gpp = nil;
273 return old; 286 return old;
274 } 287 }
275 288
276 static void 289 static void
277 deadlineimpl(int64 now, Eface arg, bool read, bool write) 290 deadlineimpl(int64 now, Eface arg, bool read, bool write)
278 { 291 {
279 PollDesc *pd; 292 PollDesc *pd;
280 uint32 seq; 293 uint32 seq;
281 G *rg, *wg; 294 G *rg, *wg;
282 295
283 USED(now); 296 USED(now);
284 pd = (PollDesc*)arg.data; 297 pd = (PollDesc*)arg.data;
285 // This is the seq when the timer was set. 298 // This is the seq when the timer was set.
286 // If it's stale, ignore the timer event. 299 // If it's stale, ignore the timer event.
287 seq = (uintptr)arg.type; 300 seq = (uintptr)arg.type;
288 rg = wg = nil; 301 rg = wg = nil;
289 runtime·lock(pd); 302 runtime·lock(pd);
290 if(seq != pd->seq) { 303 if(seq != pd->seq) {
291 // The descriptor was reused or timers were reset. 304 // The descriptor was reused or timers were reset.
292 runtime·unlock(pd); 305 runtime·unlock(pd);
293 return; 306 return;
294 } 307 }
295 if(read) { 308 if(read) {
296 if(pd->rd <= 0 || pd->rt.fv == nil) 309 if(pd->rd <= 0 || pd->rt.fv == nil)
297 runtime·throw("deadlineimpl: inconsistent read deadline" ); 310 runtime·throw("deadlineimpl: inconsistent read deadline" );
298 pd->rd = -1; 311 pd->rd = -1;
299 pd->rt.fv = nil; 312 pd->rt.fv = nil;
300 » » rg = netpollunblock(pd, 'r'); 313 » » rg = netpollunblock(pd, 'r', false);
301 } 314 }
302 if(write) { 315 if(write) {
303 if(pd->wd <= 0 || (pd->wt.fv == nil && !read)) 316 if(pd->wd <= 0 || (pd->wt.fv == nil && !read))
304 runtime·throw("deadlineimpl: inconsistent write deadline "); 317 runtime·throw("deadlineimpl: inconsistent write deadline ");
305 pd->wd = -1; 318 pd->wd = -1;
306 pd->wt.fv = nil; 319 pd->wt.fv = nil;
307 » » wg = netpollunblock(pd, 'w'); 320 » » wg = netpollunblock(pd, 'w', false);
308 } 321 }
309 runtime·unlock(pd); 322 runtime·unlock(pd);
310 if(rg) 323 if(rg)
311 runtime·ready(rg); 324 runtime·ready(rg);
312 if(wg) 325 if(wg)
313 runtime·ready(wg); 326 runtime·ready(wg);
314 } 327 }
315 328
316 static void 329 static void
317 deadline(int64 now, Eface arg) 330 deadline(int64 now, Eface arg)
(...skipping 19 matching lines...) Expand all
337 PollDesc *pd; 350 PollDesc *pd;
338 uint32 i, n; 351 uint32 i, n;
339 352
340 runtime·lock(&pollcache); 353 runtime·lock(&pollcache);
341 if(pollcache.first == nil) { 354 if(pollcache.first == nil) {
342 n = PageSize/sizeof(*pd); 355 n = PageSize/sizeof(*pd);
343 if(n == 0) 356 if(n == 0)
344 n = 1; 357 n = 1;
345 // Must be in non-GC memory because can be referenced 358 // Must be in non-GC memory because can be referenced
346 // only from epoll/kqueue internals. 359 // only from epoll/kqueue internals.
347 » » pd = runtime·SysAlloc(n*sizeof(*pd)); 360 » » pd = runtime·persistentalloc(n*sizeof(*pd), 0);
348 for(i = 0; i < n; i++) { 361 for(i = 0; i < n; i++) {
349 pd[i].link = pollcache.first; 362 pd[i].link = pollcache.first;
350 pollcache.first = &pd[i]; 363 pollcache.first = &pd[i];
351 } 364 }
352 } 365 }
353 pd = pollcache.first; 366 pd = pollcache.first;
354 pollcache.first = pd->link; 367 pollcache.first = pd->link;
355 runtime·unlock(&pollcache); 368 runtime·unlock(&pollcache);
356 return pd; 369 return pd;
357 } 370 }
LEFTRIGHT

Powered by Google App Engine
RSS Feeds Recent Issues | This issue
This is Rietveld f62528b