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

Side by Side Diff: src/pkg/runtime/netpoll.goc

Issue 10485043: code review 10485043: runtime: change netpoll in preparation for windows impl... (Closed)
Patch Set: diff -r fc8f4a3920e1 https://go.googlecode.com/hg/ Created 10 years, 9 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:
View unified diff | Download patch
« no previous file with comments | « src/pkg/net/fd_poll_runtime.go ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 5 // +build darwin linux
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
125 func runtime_pollWaitCanceled(pd *PollDesc, mode int) {
126 runtime·lock(pd);
127 // wait for ioready, ignore closing or timeouts.
128 while(!netpollblock(pd, mode))
129 ;
130 runtime·unlock(pd);
131 }
132
123 func runtime_pollSetDeadline(pd *PollDesc, d int64, mode int) { 133 func runtime_pollSetDeadline(pd *PollDesc, d int64, mode int) {
124 runtime·lock(pd); 134 runtime·lock(pd);
125 if(pd->closing) 135 if(pd->closing)
126 goto ret; 136 goto ret;
127 pd->seq++; // invalidate current timers 137 pd->seq++; // invalidate current timers
128 // Reset current timers. 138 // Reset current timers.
129 if(pd->rt.fv) { 139 if(pd->rt.fv) {
130 runtime·deltimer(&pd->rt); 140 runtime·deltimer(&pd->rt);
131 pd->rt.fv = nil; 141 pd->rt.fv = nil;
132 } 142 }
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
172 } 182 }
173 183
174 func runtime_pollUnblock(pd *PollDesc) { 184 func runtime_pollUnblock(pd *PollDesc) {
175 G *rg, *wg; 185 G *rg, *wg;
176 186
177 runtime·lock(pd); 187 runtime·lock(pd);
178 if(pd->closing) 188 if(pd->closing)
179 runtime·throw("runtime_pollUnblock: already closing"); 189 runtime·throw("runtime_pollUnblock: already closing");
180 pd->closing = true; 190 pd->closing = true;
181 pd->seq++; 191 pd->seq++;
182 » rg = netpollunblock(pd, 'r'); 192 » rg = netpollunblock(pd, 'r', false);
183 » wg = netpollunblock(pd, 'w'); 193 » wg = netpollunblock(pd, 'w', false);
184 if(pd->rt.fv) { 194 if(pd->rt.fv) {
185 runtime·deltimer(&pd->rt); 195 runtime·deltimer(&pd->rt);
186 pd->rt.fv = nil; 196 pd->rt.fv = nil;
187 } 197 }
188 if(pd->wt.fv) { 198 if(pd->wt.fv) {
189 runtime·deltimer(&pd->wt); 199 runtime·deltimer(&pd->wt);
190 pd->wt.fv = nil; 200 pd->wt.fv = nil;
191 } 201 }
192 runtime·unlock(pd); 202 runtime·unlock(pd);
193 if(rg) 203 if(rg)
194 runtime·ready(rg); 204 runtime·ready(rg);
195 if(wg) 205 if(wg)
196 runtime·ready(wg); 206 runtime·ready(wg);
197 } 207 }
198 208
199 // 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
200 void 210 void
201 runtime·netpollready(G **gpp, PollDesc *pd, int32 mode) 211 runtime·netpollready(G **gpp, PollDesc *pd, int32 mode)
202 { 212 {
203 G *rg, *wg; 213 G *rg, *wg;
204 214
205 rg = wg = nil; 215 rg = wg = nil;
206 runtime·lock(pd); 216 runtime·lock(pd);
207 if(mode == 'r' || mode == 'r'+'w') 217 if(mode == 'r' || mode == 'r'+'w')
208 » » rg = netpollunblock(pd, 'r'); 218 » » rg = netpollunblock(pd, 'r', true);
209 if(mode == 'w' || mode == 'r'+'w') 219 if(mode == 'w' || mode == 'r'+'w')
210 » » wg = netpollunblock(pd, 'w'); 220 » » wg = netpollunblock(pd, 'w', true);
211 runtime·unlock(pd); 221 runtime·unlock(pd);
212 if(rg) { 222 if(rg) {
213 rg->schedlink = *gpp; 223 rg->schedlink = *gpp;
214 *gpp = rg; 224 *gpp = rg;
215 } 225 }
216 if(wg) { 226 if(wg) {
217 wg->schedlink = *gpp; 227 wg->schedlink = *gpp;
218 *gpp = wg; 228 *gpp = wg;
219 } 229 }
220 } 230 }
221 231
222 static intgo 232 static intgo
223 checkerr(PollDesc *pd, int32 mode) 233 checkerr(PollDesc *pd, int32 mode)
224 { 234 {
225 if(pd->closing) 235 if(pd->closing)
226 return 1; // errClosing 236 return 1; // errClosing
227 if((mode == 'r' && pd->rd < 0) || (mode == 'w' && pd->wd < 0)) 237 if((mode == 'r' && pd->rd < 0) || (mode == 'w' && pd->wd < 0))
228 return 2; // errTimeout 238 return 2; // errTimeout
229 return 0; 239 return 0;
230 } 240 }
231 241
232 static void 242 // returns true if IO is ready, or false if timedout or closed
243 static bool
233 netpollblock(PollDesc *pd, int32 mode) 244 netpollblock(PollDesc *pd, int32 mode)
234 { 245 {
235 G **gpp; 246 G **gpp;
236 247
237 gpp = &pd->rg; 248 gpp = &pd->rg;
238 if(mode == 'w') 249 if(mode == 'w')
239 gpp = &pd->wg; 250 gpp = &pd->wg;
240 if(*gpp == READY) { 251 if(*gpp == READY) {
241 *gpp = nil; 252 *gpp = nil;
242 » » return; 253 » » return true;
243 } 254 }
244 if(*gpp != nil) 255 if(*gpp != nil)
245 runtime·throw("epoll: double wait"); 256 runtime·throw("epoll: double wait");
246 *gpp = g; 257 *gpp = g;
247 runtime·park(runtime·unlock, &pd->Lock, "IO wait"); 258 runtime·park(runtime·unlock, &pd->Lock, "IO wait");
248 runtime·lock(pd); 259 runtime·lock(pd);
260 if(g->param)
261 return true;
262 return false;
249 } 263 }
250 264
251 static G* 265 static G*
252 netpollunblock(PollDesc *pd, int32 mode) 266 netpollunblock(PollDesc *pd, int32 mode, bool ioready)
253 { 267 {
254 G **gpp, *old; 268 G **gpp, *old;
255 269
256 gpp = &pd->rg; 270 gpp = &pd->rg;
257 if(mode == 'w') 271 if(mode == 'w')
258 gpp = &pd->wg; 272 gpp = &pd->wg;
259 if(*gpp == READY) 273 if(*gpp == READY)
260 return nil; 274 return nil;
261 if(*gpp == nil) { 275 if(*gpp == nil) {
262 » » *gpp = READY; 276 » » // Only set READY for ioready. runtime_pollWait
277 » » // will check for timeout/cancel before waiting.
278 » » if(ioready)
279 » » » *gpp = READY;
263 return nil; 280 return nil;
264 } 281 }
265 old = *gpp; 282 old = *gpp;
283 // pass unblock reason onto blocked g
284 old->param = (void*)ioready;
266 *gpp = nil; 285 *gpp = nil;
267 return old; 286 return old;
268 } 287 }
269 288
270 static void 289 static void
271 deadlineimpl(int64 now, Eface arg, bool read, bool write) 290 deadlineimpl(int64 now, Eface arg, bool read, bool write)
272 { 291 {
273 PollDesc *pd; 292 PollDesc *pd;
274 uint32 seq; 293 uint32 seq;
275 G *rg, *wg; 294 G *rg, *wg;
276 295
277 USED(now); 296 USED(now);
278 pd = (PollDesc*)arg.data; 297 pd = (PollDesc*)arg.data;
279 // This is the seq when the timer was set. 298 // This is the seq when the timer was set.
280 // If it's stale, ignore the timer event. 299 // If it's stale, ignore the timer event.
281 seq = (uintptr)arg.type; 300 seq = (uintptr)arg.type;
282 rg = wg = nil; 301 rg = wg = nil;
283 runtime·lock(pd); 302 runtime·lock(pd);
284 if(seq != pd->seq) { 303 if(seq != pd->seq) {
285 // The descriptor was reused or timers were reset. 304 // The descriptor was reused or timers were reset.
286 runtime·unlock(pd); 305 runtime·unlock(pd);
287 return; 306 return;
288 } 307 }
289 if(read) { 308 if(read) {
290 if(pd->rd <= 0 || pd->rt.fv == nil) 309 if(pd->rd <= 0 || pd->rt.fv == nil)
291 runtime·throw("deadlineimpl: inconsistent read deadline" ); 310 runtime·throw("deadlineimpl: inconsistent read deadline" );
292 pd->rd = -1; 311 pd->rd = -1;
293 pd->rt.fv = nil; 312 pd->rt.fv = nil;
294 » » rg = netpollunblock(pd, 'r'); 313 » » rg = netpollunblock(pd, 'r', false);
295 } 314 }
296 if(write) { 315 if(write) {
297 if(pd->wd <= 0 || (pd->wt.fv == nil && !read)) 316 if(pd->wd <= 0 || (pd->wt.fv == nil && !read))
298 runtime·throw("deadlineimpl: inconsistent write deadline "); 317 runtime·throw("deadlineimpl: inconsistent write deadline ");
299 pd->wd = -1; 318 pd->wd = -1;
300 pd->wt.fv = nil; 319 pd->wt.fv = nil;
301 » » wg = netpollunblock(pd, 'w'); 320 » » wg = netpollunblock(pd, 'w', false);
302 } 321 }
303 runtime·unlock(pd); 322 runtime·unlock(pd);
304 if(rg) 323 if(rg)
305 runtime·ready(rg); 324 runtime·ready(rg);
306 if(wg) 325 if(wg)
307 runtime·ready(wg); 326 runtime·ready(wg);
308 } 327 }
309 328
310 static void 329 static void
311 deadline(int64 now, Eface arg) 330 deadline(int64 now, Eface arg)
(...skipping 30 matching lines...) Expand all
342 for(i = 0; i < n; i++) { 361 for(i = 0; i < n; i++) {
343 pd[i].link = pollcache.first; 362 pd[i].link = pollcache.first;
344 pollcache.first = &pd[i]; 363 pollcache.first = &pd[i];
345 } 364 }
346 } 365 }
347 pd = pollcache.first; 366 pd = pollcache.first;
348 pollcache.first = pd->link; 367 pollcache.first = pd->link;
349 runtime·unlock(&pollcache); 368 runtime·unlock(&pollcache);
350 return pd; 369 return pd;
351 } 370 }
OLDNEW
« no previous file with comments | « src/pkg/net/fd_poll_runtime.go ('k') | no next file » | no next file with comments »

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