OLD | NEW |
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 #include "runtime.h" | 5 #include "runtime.h" |
6 #include "arch_GOARCH.h" | 6 #include "arch_GOARCH.h" |
7 #include "type.h" | 7 #include "type.h" |
8 #include "race.h" | 8 #include "race.h" |
9 #include "malloc.h" | 9 #include "malloc.h" |
10 #include "../../cmd/ld/textflag.h" | 10 #include "../../cmd/ld/textflag.h" |
(...skipping 23 matching lines...) Expand all Loading... |
34 | 34 |
35 // The garbage collector is assuming that Hchan can only contain pointers into t
he stack | 35 // The garbage collector is assuming that Hchan can only contain pointers into t
he stack |
36 // and cannot contain pointers into the heap. | 36 // and cannot contain pointers into the heap. |
37 struct Hchan | 37 struct Hchan |
38 { | 38 { |
39 uintgo qcount; // total data in the q | 39 uintgo qcount; // total data in the q |
40 uintgo dataqsiz; // size of the circular q | 40 uintgo dataqsiz; // size of the circular q |
41 uint16 elemsize; | 41 uint16 elemsize; |
42 uint16 pad; // ensures proper alignment of the buffe
r that follows Hchan in memory | 42 uint16 pad; // ensures proper alignment of the buffe
r that follows Hchan in memory |
43 bool closed; | 43 bool closed; |
44 » Alg*» elemalg;» » // interface for element type | 44 » Type*» elemtype;» » // element type |
45 uintgo sendx; // send index | 45 uintgo sendx; // send index |
46 uintgo recvx; // receive index | 46 uintgo recvx; // receive index |
47 WaitQ recvq; // list of recv waiters | 47 WaitQ recvq; // list of recv waiters |
48 WaitQ sendq; // list of send waiters | 48 WaitQ sendq; // list of send waiters |
49 Lock; | 49 Lock; |
50 }; | 50 }; |
51 | 51 |
52 uint32 runtime·Hchansize = sizeof(Hchan); | 52 uint32 runtime·Hchansize = sizeof(Hchan); |
53 | 53 |
54 // Buffer follows Hchan immediately in memory. | 54 // Buffer follows Hchan immediately in memory. |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
103 runtime·throw("makechan: invalid channel element type"); | 103 runtime·throw("makechan: invalid channel element type"); |
104 if((sizeof(*c)%MAXALIGN) != 0 || elem->align > MAXALIGN) | 104 if((sizeof(*c)%MAXALIGN) != 0 || elem->align > MAXALIGN) |
105 runtime·throw("makechan: bad alignment"); | 105 runtime·throw("makechan: bad alignment"); |
106 | 106 |
107 if(hint < 0 || (intgo)hint != hint || (elem->size > 0 && hint > MaxMem /
elem->size)) | 107 if(hint < 0 || (intgo)hint != hint || (elem->size > 0 && hint > MaxMem /
elem->size)) |
108 runtime·panicstring("makechan: size out of range"); | 108 runtime·panicstring("makechan: size out of range"); |
109 | 109 |
110 // allocate memory in one call | 110 // allocate memory in one call |
111 c = (Hchan*)runtime·mallocgc(sizeof(*c) + hint*elem->size, (uintptr)t |
TypeInfo_Chan, 0); | 111 c = (Hchan*)runtime·mallocgc(sizeof(*c) + hint*elem->size, (uintptr)t |
TypeInfo_Chan, 0); |
112 c->elemsize = elem->size; | 112 c->elemsize = elem->size; |
113 » c->elemalg = elem->alg; | 113 » c->elemtype = elem; |
114 c->dataqsiz = hint; | 114 c->dataqsiz = hint; |
115 | 115 |
116 if(debug) | 116 if(debug) |
117 runtime·printf("makechan: chan=%p; elemsize=%D; elemalg=%p; data
qsiz=%D\n", | 117 runtime·printf("makechan: chan=%p; elemsize=%D; elemalg=%p; data
qsiz=%D\n", |
118 c, (int64)elem->size, elem->alg, (int64)c->dataqsiz); | 118 c, (int64)elem->size, elem->alg, (int64)c->dataqsiz); |
119 | 119 |
120 return c; | 120 return c; |
121 } | 121 } |
122 | 122 |
123 // For reflect | 123 // For reflect |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
167 if(pres != nil) { | 167 if(pres != nil) { |
168 *pres = false; | 168 *pres = false; |
169 return; | 169 return; |
170 } | 170 } |
171 runtime·park(nil, nil, "chan send (nil chan)"); | 171 runtime·park(nil, nil, "chan send (nil chan)"); |
172 return; // not reached | 172 return; // not reached |
173 } | 173 } |
174 | 174 |
175 if(debug) { | 175 if(debug) { |
176 runtime·printf("chansend: chan=%p; elem=", c); | 176 runtime·printf("chansend: chan=%p; elem=", c); |
177 » » c->elemalg->print(c->elemsize, ep); | 177 » » c->elemtype->alg->print(c->elemsize, ep); |
178 runtime·prints("\n"); | 178 runtime·prints("\n"); |
179 } | 179 } |
180 | 180 |
181 t0 = 0; | 181 t0 = 0; |
182 mysg.releasetime = 0; | 182 mysg.releasetime = 0; |
183 if(runtime·blockprofilerate > 0) { | 183 if(runtime·blockprofilerate > 0) { |
184 t0 = runtime·cputicks(); | 184 t0 = runtime·cputicks(); |
185 mysg.releasetime = -1; | 185 mysg.releasetime = -1; |
186 } | 186 } |
187 | 187 |
188 runtime·lock(c); | 188 runtime·lock(c); |
189 if(raceenabled) | 189 if(raceenabled) |
190 runtime·racereadpc(c, pc, runtime·chansend); | 190 runtime·racereadpc(c, pc, runtime·chansend); |
191 if(c->closed) | 191 if(c->closed) |
192 goto closed; | 192 goto closed; |
193 | 193 |
194 if(c->dataqsiz > 0) | 194 if(c->dataqsiz > 0) |
195 goto asynch; | 195 goto asynch; |
196 | 196 |
197 sg = dequeue(&c->recvq); | 197 sg = dequeue(&c->recvq); |
198 if(sg != nil) { | 198 if(sg != nil) { |
199 if(raceenabled) | 199 if(raceenabled) |
200 racesync(c, sg); | 200 racesync(c, sg); |
201 runtime·unlock(c); | 201 runtime·unlock(c); |
202 | 202 |
203 gp = sg->g; | 203 gp = sg->g; |
204 gp->param = sg; | 204 gp->param = sg; |
205 if(sg->elem != nil) | 205 if(sg->elem != nil) |
206 » » » c->elemalg->copy(c->elemsize, sg->elem, ep); | 206 » » » c->elemtype->alg->copy(c->elemsize, sg->elem, ep); |
207 if(sg->releasetime) | 207 if(sg->releasetime) |
208 sg->releasetime = runtime·cputicks(); | 208 sg->releasetime = runtime·cputicks(); |
209 runtime·ready(gp); | 209 runtime·ready(gp); |
210 | 210 |
211 if(pres != nil) | 211 if(pres != nil) |
212 *pres = true; | 212 *pres = true; |
213 return; | 213 return; |
214 } | 214 } |
215 | 215 |
216 if(pres != nil) { | 216 if(pres != nil) { |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
254 enqueue(&c->sendq, &mysg); | 254 enqueue(&c->sendq, &mysg); |
255 runtime·park(runtime·unlock, c, "chan send"); | 255 runtime·park(runtime·unlock, c, "chan send"); |
256 | 256 |
257 runtime·lock(c); | 257 runtime·lock(c); |
258 goto asynch; | 258 goto asynch; |
259 } | 259 } |
260 | 260 |
261 if(raceenabled) | 261 if(raceenabled) |
262 runtime·racerelease(chanbuf(c, c->sendx)); | 262 runtime·racerelease(chanbuf(c, c->sendx)); |
263 | 263 |
264 » c->elemalg->copy(c->elemsize, chanbuf(c, c->sendx), ep); | 264 » c->elemtype->alg->copy(c->elemsize, chanbuf(c, c->sendx), ep); |
265 if(++c->sendx == c->dataqsiz) | 265 if(++c->sendx == c->dataqsiz) |
266 c->sendx = 0; | 266 c->sendx = 0; |
267 c->qcount++; | 267 c->qcount++; |
268 | 268 |
269 sg = dequeue(&c->recvq); | 269 sg = dequeue(&c->recvq); |
270 if(sg != nil) { | 270 if(sg != nil) { |
271 gp = sg->g; | 271 gp = sg->g; |
272 runtime·unlock(c); | 272 runtime·unlock(c); |
273 if(sg->releasetime) | 273 if(sg->releasetime) |
274 sg->releasetime = runtime·cputicks(); | 274 sg->releasetime = runtime·cputicks(); |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
324 if(c->closed) | 324 if(c->closed) |
325 goto closed; | 325 goto closed; |
326 | 326 |
327 sg = dequeue(&c->sendq); | 327 sg = dequeue(&c->sendq); |
328 if(sg != nil) { | 328 if(sg != nil) { |
329 if(raceenabled) | 329 if(raceenabled) |
330 racesync(c, sg); | 330 racesync(c, sg); |
331 runtime·unlock(c); | 331 runtime·unlock(c); |
332 | 332 |
333 if(ep != nil) | 333 if(ep != nil) |
334 » » » c->elemalg->copy(c->elemsize, ep, sg->elem); | 334 » » » c->elemtype->alg->copy(c->elemsize, ep, sg->elem); |
335 gp = sg->g; | 335 gp = sg->g; |
336 gp->param = sg; | 336 gp->param = sg; |
337 if(sg->releasetime) | 337 if(sg->releasetime) |
338 sg->releasetime = runtime·cputicks(); | 338 sg->releasetime = runtime·cputicks(); |
339 runtime·ready(gp); | 339 runtime·ready(gp); |
340 | 340 |
341 if(selected != nil) | 341 if(selected != nil) |
342 *selected = true; | 342 *selected = true; |
343 if(received != nil) | 343 if(received != nil) |
344 *received = true; | 344 *received = true; |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
390 runtime·park(runtime·unlock, c, "chan receive"); | 390 runtime·park(runtime·unlock, c, "chan receive"); |
391 | 391 |
392 runtime·lock(c); | 392 runtime·lock(c); |
393 goto asynch; | 393 goto asynch; |
394 } | 394 } |
395 | 395 |
396 if(raceenabled) | 396 if(raceenabled) |
397 runtime·raceacquire(chanbuf(c, c->recvx)); | 397 runtime·raceacquire(chanbuf(c, c->recvx)); |
398 | 398 |
399 if(ep != nil) | 399 if(ep != nil) |
400 » » c->elemalg->copy(c->elemsize, ep, chanbuf(c, c->recvx)); | 400 » » c->elemtype->alg->copy(c->elemsize, ep, chanbuf(c, c->recvx)); |
401 » c->elemalg->copy(c->elemsize, chanbuf(c, c->recvx), nil); | 401 » c->elemtype->alg->copy(c->elemsize, chanbuf(c, c->recvx), nil); |
402 if(++c->recvx == c->dataqsiz) | 402 if(++c->recvx == c->dataqsiz) |
403 c->recvx = 0; | 403 c->recvx = 0; |
404 c->qcount--; | 404 c->qcount--; |
405 | 405 |
406 sg = dequeue(&c->sendq); | 406 sg = dequeue(&c->sendq); |
407 if(sg != nil) { | 407 if(sg != nil) { |
408 gp = sg->g; | 408 gp = sg->g; |
409 runtime·unlock(c); | 409 runtime·unlock(c); |
410 if(sg->releasetime) | 410 if(sg->releasetime) |
411 sg->releasetime = runtime·cputicks(); | 411 sg->releasetime = runtime·cputicks(); |
412 runtime·ready(gp); | 412 runtime·ready(gp); |
413 } else | 413 } else |
414 runtime·unlock(c); | 414 runtime·unlock(c); |
415 | 415 |
416 if(selected != nil) | 416 if(selected != nil) |
417 *selected = true; | 417 *selected = true; |
418 if(received != nil) | 418 if(received != nil) |
419 *received = true; | 419 *received = true; |
420 if(mysg.releasetime > 0) | 420 if(mysg.releasetime > 0) |
421 runtime·blockevent(mysg.releasetime - t0, 2); | 421 runtime·blockevent(mysg.releasetime - t0, 2); |
422 return; | 422 return; |
423 | 423 |
424 closed: | 424 closed: |
425 if(ep != nil) | 425 if(ep != nil) |
426 » » c->elemalg->copy(c->elemsize, ep, nil); | 426 » » c->elemtype->alg->copy(c->elemsize, ep, nil); |
427 if(selected != nil) | 427 if(selected != nil) |
428 *selected = true; | 428 *selected = true; |
429 if(received != nil) | 429 if(received != nil) |
430 *received = false; | 430 *received = false; |
431 if(raceenabled) | 431 if(raceenabled) |
432 runtime·raceacquire(c); | 432 runtime·raceacquire(c); |
433 runtime·unlock(c); | 433 runtime·unlock(c); |
434 if(mysg.releasetime > 0) | 434 if(mysg.releasetime > 0) |
435 runtime·blockevent(mysg.releasetime - t0, 2); | 435 runtime·blockevent(mysg.releasetime - t0, 2); |
436 } | 436 } |
(...skipping 563 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1000 | 1000 |
1001 if(debug) | 1001 if(debug) |
1002 runtime·printf("wait-return: sel=%p c=%p cas=%p kind=%d\n", | 1002 runtime·printf("wait-return: sel=%p c=%p cas=%p kind=%d\n", |
1003 sel, c, cas, cas->kind); | 1003 sel, c, cas, cas->kind); |
1004 | 1004 |
1005 if(cas->kind == CaseRecv) { | 1005 if(cas->kind == CaseRecv) { |
1006 if(cas->receivedp != nil) | 1006 if(cas->receivedp != nil) |
1007 *cas->receivedp = true; | 1007 *cas->receivedp = true; |
1008 } | 1008 } |
1009 | 1009 |
| 1010 if(raceenabled) { |
| 1011 if(cas->kind == CaseRecv && cas->sg.elem != nil) |
| 1012 runtime·racewriteobjectpc(cas->sg.elem, c->elemtype, cas
->pc, runtime·chanrecv); |
| 1013 else if(cas->kind == CaseSend) |
| 1014 runtime·racereadobjectpc(cas->sg.elem, c->elemtype, cas-
>pc, runtime·chansend); |
| 1015 } |
| 1016 |
1010 selunlock(sel); | 1017 selunlock(sel); |
1011 goto retc; | 1018 goto retc; |
1012 | 1019 |
1013 asyncrecv: | 1020 asyncrecv: |
1014 // can receive from buffer | 1021 // can receive from buffer |
1015 » if(raceenabled) | 1022 » if(raceenabled) { |
| 1023 » » if(cas->sg.elem != nil) |
| 1024 » » » runtime·racewriteobjectpc(cas->sg.elem, c->elemtype, cas
->pc, runtime·chanrecv); |
1016 runtime·raceacquire(chanbuf(c, c->recvx)); | 1025 runtime·raceacquire(chanbuf(c, c->recvx)); |
| 1026 } |
1017 if(cas->receivedp != nil) | 1027 if(cas->receivedp != nil) |
1018 *cas->receivedp = true; | 1028 *cas->receivedp = true; |
1019 if(cas->sg.elem != nil) | 1029 if(cas->sg.elem != nil) |
1020 » » c->elemalg->copy(c->elemsize, cas->sg.elem, chanbuf(c, c->recvx)
); | 1030 » » c->elemtype->alg->copy(c->elemsize, cas->sg.elem, chanbuf(c, c->
recvx)); |
1021 » c->elemalg->copy(c->elemsize, chanbuf(c, c->recvx), nil); | 1031 » c->elemtype->alg->copy(c->elemsize, chanbuf(c, c->recvx), nil); |
1022 if(++c->recvx == c->dataqsiz) | 1032 if(++c->recvx == c->dataqsiz) |
1023 c->recvx = 0; | 1033 c->recvx = 0; |
1024 c->qcount--; | 1034 c->qcount--; |
1025 sg = dequeue(&c->sendq); | 1035 sg = dequeue(&c->sendq); |
1026 if(sg != nil) { | 1036 if(sg != nil) { |
1027 gp = sg->g; | 1037 gp = sg->g; |
1028 selunlock(sel); | 1038 selunlock(sel); |
1029 if(sg->releasetime) | 1039 if(sg->releasetime) |
1030 sg->releasetime = runtime·cputicks(); | 1040 sg->releasetime = runtime·cputicks(); |
1031 runtime·ready(gp); | 1041 runtime·ready(gp); |
1032 } else { | 1042 } else { |
1033 selunlock(sel); | 1043 selunlock(sel); |
1034 } | 1044 } |
1035 goto retc; | 1045 goto retc; |
1036 | 1046 |
1037 asyncsend: | 1047 asyncsend: |
1038 // can send to buffer | 1048 // can send to buffer |
1039 » if(raceenabled) | 1049 » if(raceenabled) { |
1040 runtime·racerelease(chanbuf(c, c->sendx)); | 1050 runtime·racerelease(chanbuf(c, c->sendx)); |
1041 » c->elemalg->copy(c->elemsize, chanbuf(c, c->sendx), cas->sg.elem); | 1051 » » runtime·racereadobjectpc(cas->sg.elem, c->elemtype, cas->pc, run
time·chansend); |
| 1052 » } |
| 1053 » c->elemtype->alg->copy(c->elemsize, chanbuf(c, c->sendx), cas->sg.elem); |
1042 if(++c->sendx == c->dataqsiz) | 1054 if(++c->sendx == c->dataqsiz) |
1043 c->sendx = 0; | 1055 c->sendx = 0; |
1044 c->qcount++; | 1056 c->qcount++; |
1045 sg = dequeue(&c->recvq); | 1057 sg = dequeue(&c->recvq); |
1046 if(sg != nil) { | 1058 if(sg != nil) { |
1047 gp = sg->g; | 1059 gp = sg->g; |
1048 selunlock(sel); | 1060 selunlock(sel); |
1049 if(sg->releasetime) | 1061 if(sg->releasetime) |
1050 sg->releasetime = runtime·cputicks(); | 1062 sg->releasetime = runtime·cputicks(); |
1051 runtime·ready(gp); | 1063 runtime·ready(gp); |
1052 } else { | 1064 } else { |
1053 selunlock(sel); | 1065 selunlock(sel); |
1054 } | 1066 } |
1055 goto retc; | 1067 goto retc; |
1056 | 1068 |
1057 syncrecv: | 1069 syncrecv: |
1058 // can receive from sleeping sender (sg) | 1070 // can receive from sleeping sender (sg) |
1059 » if(raceenabled) | 1071 » if(raceenabled) { |
| 1072 » » if(cas->sg.elem != nil) |
| 1073 » » » runtime·racewriteobjectpc(cas->sg.elem, c->elemtype, cas
->pc, runtime·chanrecv); |
1060 racesync(c, sg); | 1074 racesync(c, sg); |
| 1075 } |
1061 selunlock(sel); | 1076 selunlock(sel); |
1062 if(debug) | 1077 if(debug) |
1063 runtime·printf("syncrecv: sel=%p c=%p o=%d\n", sel, c, o); | 1078 runtime·printf("syncrecv: sel=%p c=%p o=%d\n", sel, c, o); |
1064 if(cas->receivedp != nil) | 1079 if(cas->receivedp != nil) |
1065 *cas->receivedp = true; | 1080 *cas->receivedp = true; |
1066 if(cas->sg.elem != nil) | 1081 if(cas->sg.elem != nil) |
1067 » » c->elemalg->copy(c->elemsize, cas->sg.elem, sg->elem); | 1082 » » c->elemtype->alg->copy(c->elemsize, cas->sg.elem, sg->elem); |
1068 gp = sg->g; | 1083 gp = sg->g; |
1069 gp->param = sg; | 1084 gp->param = sg; |
1070 if(sg->releasetime) | 1085 if(sg->releasetime) |
1071 sg->releasetime = runtime·cputicks(); | 1086 sg->releasetime = runtime·cputicks(); |
1072 runtime·ready(gp); | 1087 runtime·ready(gp); |
1073 goto retc; | 1088 goto retc; |
1074 | 1089 |
1075 rclose: | 1090 rclose: |
1076 // read at end of closed channel | 1091 // read at end of closed channel |
1077 selunlock(sel); | 1092 selunlock(sel); |
1078 if(cas->receivedp != nil) | 1093 if(cas->receivedp != nil) |
1079 *cas->receivedp = false; | 1094 *cas->receivedp = false; |
1080 if(cas->sg.elem != nil) | 1095 if(cas->sg.elem != nil) |
1081 » » c->elemalg->copy(c->elemsize, cas->sg.elem, nil); | 1096 » » c->elemtype->alg->copy(c->elemsize, cas->sg.elem, nil); |
1082 if(raceenabled) | 1097 if(raceenabled) |
1083 runtime·raceacquire(c); | 1098 runtime·raceacquire(c); |
1084 goto retc; | 1099 goto retc; |
1085 | 1100 |
1086 syncsend: | 1101 syncsend: |
1087 // can send to sleeping receiver (sg) | 1102 // can send to sleeping receiver (sg) |
1088 » if(raceenabled) | 1103 » if(raceenabled) { |
| 1104 » » runtime·racereadobjectpc(cas->sg.elem, c->elemtype, cas->pc, run
time·chansend); |
1089 racesync(c, sg); | 1105 racesync(c, sg); |
| 1106 } |
1090 selunlock(sel); | 1107 selunlock(sel); |
1091 if(debug) | 1108 if(debug) |
1092 runtime·printf("syncsend: sel=%p c=%p o=%d\n", sel, c, o); | 1109 runtime·printf("syncsend: sel=%p c=%p o=%d\n", sel, c, o); |
1093 if(sg->elem != nil) | 1110 if(sg->elem != nil) |
1094 » » c->elemalg->copy(c->elemsize, sg->elem, cas->sg.elem); | 1111 » » c->elemtype->alg->copy(c->elemsize, sg->elem, cas->sg.elem); |
1095 gp = sg->g; | 1112 gp = sg->g; |
1096 gp->param = sg; | 1113 gp->param = sg; |
1097 if(sg->releasetime) | 1114 if(sg->releasetime) |
1098 sg->releasetime = runtime·cputicks(); | 1115 sg->releasetime = runtime·cputicks(); |
1099 runtime·ready(gp); | 1116 runtime·ready(gp); |
1100 | 1117 |
1101 retc: | 1118 retc: |
1102 // return pc corresponding to chosen case. | 1119 // return pc corresponding to chosen case. |
1103 // Set boolean passed during select creation | 1120 // Set boolean passed during select creation |
1104 // (at offset selp + cas->so) to true. | 1121 // (at offset selp + cas->so) to true. |
(...skipping 216 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1321 } | 1338 } |
1322 | 1339 |
1323 static void | 1340 static void |
1324 racesync(Hchan *c, SudoG *sg) | 1341 racesync(Hchan *c, SudoG *sg) |
1325 { | 1342 { |
1326 runtime·racerelease(chanbuf(c, 0)); | 1343 runtime·racerelease(chanbuf(c, 0)); |
1327 runtime·raceacquireg(sg->g, chanbuf(c, 0)); | 1344 runtime·raceacquireg(sg->g, chanbuf(c, 0)); |
1328 runtime·racereleaseg(sg->g, chanbuf(c, 0)); | 1345 runtime·racereleaseg(sg->g, chanbuf(c, 0)); |
1329 runtime·raceacquire(chanbuf(c, 0)); | 1346 runtime·raceacquire(chanbuf(c, 0)); |
1330 } | 1347 } |
OLD | NEW |