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

Side by Side Diff: src/pkg/runtime/chan.c

Issue 54220043: code review 54220043: runtime/race: race instrument reads/writes in select cases (Closed)
Patch Set: diff -r 32309d9c952e https://dvyukov%40google.com@code.google.com/p/go/ Created 11 years, 1 month 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 | « no previous file | src/pkg/runtime/race/testdata/chan_test.go » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
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
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
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 }
OLDNEW
« no previous file with comments | « no previous file | src/pkg/runtime/race/testdata/chan_test.go » ('j') | no next file with comments »

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