LEFT | RIGHT |
(no file at all) | |
1 // Copyright 2009 The Go Authors. All rights reserved. | 1 // Copyright 2009 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 package runtime | 5 package runtime |
6 | 6 |
7 // This file contains the implementation of Go select statements. | 7 // This file contains the implementation of Go select statements. |
8 | 8 |
9 import "unsafe" | 9 import "unsafe" |
10 | 10 |
11 const ( | 11 const ( |
12 debugSelect = false | 12 debugSelect = false |
13 ) | 13 ) |
14 | 14 |
15 var ( | 15 var ( |
16 » chansendpc uintptr | 16 » chansendpc = funcPC(chansend) |
17 » chanrecvpc uintptr | 17 » chanrecvpc = funcPC(chanrecv) |
18 ) | 18 ) |
19 | |
20 func init() { | |
21 f := chansend | |
22 chansendpc = **(**uintptr)(unsafe.Pointer(&f)) | |
23 g := chanrecv | |
24 chanrecvpc = **(**uintptr)(unsafe.Pointer(&g)) | |
25 } | |
26 | 19 |
27 func selectsize(size uintptr) uintptr { | 20 func selectsize(size uintptr) uintptr { |
28 selsize := unsafe.Sizeof(_select{}) + | 21 selsize := unsafe.Sizeof(_select{}) + |
29 (size-1)*unsafe.Sizeof(_select{}.scase[0]) + | 22 (size-1)*unsafe.Sizeof(_select{}.scase[0]) + |
30 size*unsafe.Sizeof(*_select{}.lockorder) + | 23 size*unsafe.Sizeof(*_select{}.lockorder) + |
31 size*unsafe.Sizeof(*_select{}.pollorder) | 24 size*unsafe.Sizeof(*_select{}.pollorder) |
32 return round(selsize, _Int64Align) | 25 return round(selsize, _Int64Align) |
33 } | 26 } |
34 | 27 |
35 func newselect(sel *_select, selsize int64, size int32) { | 28 func newselect(sel *_select, selsize int64, size int32) { |
(...skipping 243 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
279 sellock(sel) | 272 sellock(sel) |
280 | 273 |
281 var ( | 274 var ( |
282 gp *g | 275 gp *g |
283 done uint32 | 276 done uint32 |
284 sg *sudog | 277 sg *sudog |
285 c *hchan | 278 c *hchan |
286 k *scase | 279 k *scase |
287 sglist *sudog | 280 sglist *sudog |
288 sgnext *sudog | 281 sgnext *sudog |
289 fn func(*g, *_select) bool | |
290 ) | 282 ) |
291 | 283 |
292 loop: | 284 loop: |
293 // pass 1 - look for something already waiting | 285 // pass 1 - look for something already waiting |
294 var dfl *scase | 286 var dfl *scase |
295 var cas *scase | 287 var cas *scase |
296 for i := 0; i < int(sel.ncase); i++ { | 288 for i := 0; i < int(sel.ncase); i++ { |
297 cas = &scases[pollorder[i]] | 289 cas = &scases[pollorder[i]] |
298 c = cas._chan | 290 c = cas._chan |
299 | 291 |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
364 case _CaseRecv: | 356 case _CaseRecv: |
365 c.recvq.enqueue(sg) | 357 c.recvq.enqueue(sg) |
366 | 358 |
367 case _CaseSend: | 359 case _CaseSend: |
368 c.sendq.enqueue(sg) | 360 c.sendq.enqueue(sg) |
369 } | 361 } |
370 } | 362 } |
371 | 363 |
372 // wait for someone to wake us up | 364 // wait for someone to wake us up |
373 gp.param = nil | 365 gp.param = nil |
374 » fn = selparkcommit | 366 » gopark(unsafe.Pointer(funcPC(selparkcommit)), unsafe.Pointer(sel), "sele
ct") |
375 » gopark(**(**unsafe.Pointer)(unsafe.Pointer(&fn)), unsafe.Pointer(sel), "
select") | |
376 | 367 |
377 // someone woke us up | 368 // someone woke us up |
378 sellock(sel) | 369 sellock(sel) |
379 sg = (*sudog)(gp.param) | 370 sg = (*sudog)(gp.param) |
380 | 371 |
381 // pass 3 - dequeue from unsuccessful chans | 372 // pass 3 - dequeue from unsuccessful chans |
382 // otherwise they stack up on quiet channels | 373 // otherwise they stack up on quiet channels |
383 // record the successful case, if any. | 374 // record the successful case, if any. |
384 // We singly-linked up the SudoGs in case order, so when | 375 // We singly-linked up the SudoGs in case order, so when |
385 // iterating through the linked list they are in reverse order. | 376 // iterating through the linked list they are in reverse order. |
(...skipping 250 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
636 *l = sgp.next | 627 *l = sgp.next |
637 if q.last == sgp { | 628 if q.last == sgp { |
638 q.last = prevsgp | 629 q.last = prevsgp |
639 } | 630 } |
640 return | 631 return |
641 } | 632 } |
642 l = &sgp.next | 633 l = &sgp.next |
643 prevsgp = sgp | 634 prevsgp = sgp |
644 } | 635 } |
645 } | 636 } |
LEFT | RIGHT |