LEFT | RIGHT |
(no file at all) | |
1 // Copyright 2014 The Go Authors. All rights reserved. | 1 // Copyright 2014 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 channels. | 7 // This file contains the implementation of Go channels. |
8 | 8 |
9 import "unsafe" | 9 import "unsafe" |
10 | 10 |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
75 * sleep but return if it could | 75 * sleep but return if it could |
76 * not complete. | 76 * not complete. |
77 * | 77 * |
78 * sleep can wake up with g.param == nil | 78 * sleep can wake up with g.param == nil |
79 * when a channel involved in the sleep has | 79 * when a channel involved in the sleep has |
80 * been closed. it is easiest to loop and re-run | 80 * been closed. it is easiest to loop and re-run |
81 * the operation; we'll see that it's now closed. | 81 * the operation; we'll see that it's now closed. |
82 */ | 82 */ |
83 func chansend(t *chantype, c *hchan, ep unsafe.Pointer, block bool, callerpc uin
tptr) bool { | 83 func chansend(t *chantype, c *hchan, ep unsafe.Pointer, block bool, callerpc uin
tptr) bool { |
84 if raceenabled { | 84 if raceenabled { |
85 » » fn := chansend | 85 » » raceReadObjectPC(t.elem, ep, callerpc, funcPC(chansend)) |
86 » » pc := **(**uintptr)(unsafe.Pointer(&fn)) | |
87 » » raceReadObjectPC(t.elem, ep, callerpc, pc) | |
88 } | 86 } |
89 | 87 |
90 if c == nil { | 88 if c == nil { |
91 if !block { | 89 if !block { |
92 return false | 90 return false |
93 } | 91 } |
94 gopark(nil, nil, "chan send (nil chan)") | 92 gopark(nil, nil, "chan send (nil chan)") |
95 gothrow("unreachable") | 93 gothrow("unreachable") |
96 } | 94 } |
97 | 95 |
98 if debugChan { | 96 if debugChan { |
99 print("chansend: chan=", c, "\n") | 97 print("chansend: chan=", c, "\n") |
100 } | 98 } |
101 | 99 |
102 if raceenabled { | 100 if raceenabled { |
103 » » fn := chansend | 101 » » racereadpc(unsafe.Pointer(c), callerpc, funcPC(chansend)) |
104 » » pc := **(**uintptr)(unsafe.Pointer(&fn)) | |
105 » » racereadpc(unsafe.Pointer(c), pc, callerpc) | |
106 } | 102 } |
107 | 103 |
108 // Fast path: check for failed non-blocking operation without acquiring
the lock. | 104 // Fast path: check for failed non-blocking operation without acquiring
the lock. |
109 // | 105 // |
110 // After observing that the channel is not closed, we observe that the c
hannel is | 106 // After observing that the channel is not closed, we observe that the c
hannel is |
111 // not ready for sending. Each of these observations is a single word-si
zed read | 107 // not ready for sending. Each of these observations is a single word-si
zed read |
112 // (first c.closed and second c.recvq.first or c.qcount depending on kin
d of channel). | 108 // (first c.closed and second c.recvq.first or c.qcount depending on kin
d of channel). |
113 // Because a closed channel cannot transition from 'ready for sending' t
o | 109 // Because a closed channel cannot transition from 'ready for sending' t
o |
114 // 'not ready for sending', even if the channel is closed between the tw
o observations, | 110 // 'not ready for sending', even if the channel is closed between the tw
o observations, |
115 // they imply a moment between the two when the channel was both not yet
closed | 111 // they imply a moment between the two when the channel was both not yet
closed |
(...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
262 } | 258 } |
263 | 259 |
264 lock(&c.lock) | 260 lock(&c.lock) |
265 if c.closed != 0 { | 261 if c.closed != 0 { |
266 unlock(&c.lock) | 262 unlock(&c.lock) |
267 panic("close of closed channel") | 263 panic("close of closed channel") |
268 } | 264 } |
269 | 265 |
270 if raceenabled { | 266 if raceenabled { |
271 callerpc := getcallerpc(unsafe.Pointer(&c)) | 267 callerpc := getcallerpc(unsafe.Pointer(&c)) |
272 » » fn := closechan | 268 » » racewritepc(unsafe.Pointer(c), callerpc, funcPC(closechan)) |
273 » » pc := **(**uintptr)(unsafe.Pointer(&fn)) | |
274 » » racewritepc(unsafe.Pointer(c), callerpc, pc) | |
275 racerelease(unsafe.Pointer(c)) | 269 racerelease(unsafe.Pointer(c)) |
276 } | 270 } |
277 | 271 |
278 c.closed = 1 | 272 c.closed = 1 |
279 | 273 |
280 // release all readers | 274 // release all readers |
281 for { | 275 for { |
282 sg := c.recvq.dequeue() | 276 sg := c.recvq.dequeue() |
283 if sg == nil { | 277 if sg == nil { |
284 break | 278 break |
(...skipping 356 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
641 return sgp | 635 return sgp |
642 } | 636 } |
643 } | 637 } |
644 | 638 |
645 func racesync(c *hchan, sg *sudog) { | 639 func racesync(c *hchan, sg *sudog) { |
646 racerelease(chanbuf(c, 0)) | 640 racerelease(chanbuf(c, 0)) |
647 raceacquireg(sg.g, chanbuf(c, 0)) | 641 raceacquireg(sg.g, chanbuf(c, 0)) |
648 racereleaseg(sg.g, chanbuf(c, 0)) | 642 racereleaseg(sg.g, chanbuf(c, 0)) |
649 raceacquire(chanbuf(c, 0)) | 643 raceacquire(chanbuf(c, 0)) |
650 } | 644 } |
LEFT | RIGHT |