LEFT | RIGHT |
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 "type.h" | 6 #include "type.h" |
7 | 7 |
8 #define MAXALIGN 7 | 8 #define MAXALIGN 7 |
9 #define NOSELGEN 1 | 9 #define NOSELGEN 1 |
10 | 10 |
(...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
148 SudoG *sg; | 148 SudoG *sg; |
149 SudoG mysg; | 149 SudoG mysg; |
150 G* gp; | 150 G* gp; |
151 | 151 |
152 if(c == nil) { | 152 if(c == nil) { |
153 USED(t); | 153 USED(t); |
154 if(pres != nil) { | 154 if(pres != nil) { |
155 *pres = false; | 155 *pres = false; |
156 return; | 156 return; |
157 } | 157 } |
158 » » g->status = Gwaiting; | 158 » » runtime·park(nil, nil, "chan send (nil chan)"); |
159 » » g->waitreason = "chan send (nil chan)"; | |
160 » » runtime·gosched(); | |
161 return; // not reached | 159 return; // not reached |
162 } | 160 } |
163 | 161 |
164 if(runtime·gcwaiting) | 162 if(runtime·gcwaiting) |
165 runtime·gosched(); | 163 runtime·gosched(); |
166 | 164 |
167 if(debug) { | 165 if(debug) { |
168 runtime·printf("chansend: chan=%p; elem=", c); | 166 runtime·printf("chansend: chan=%p; elem=", c); |
169 c->elemalg->print(c->elemsize, ep); | 167 c->elemalg->print(c->elemsize, ep); |
170 runtime·prints("\n"); | 168 runtime·prints("\n"); |
(...skipping 24 matching lines...) Expand all Loading... |
195 if(pres != nil) { | 193 if(pres != nil) { |
196 runtime·unlock(c); | 194 runtime·unlock(c); |
197 *pres = false; | 195 *pres = false; |
198 return; | 196 return; |
199 } | 197 } |
200 | 198 |
201 mysg.elem = ep; | 199 mysg.elem = ep; |
202 mysg.g = g; | 200 mysg.g = g; |
203 mysg.selgen = NOSELGEN; | 201 mysg.selgen = NOSELGEN; |
204 g->param = nil; | 202 g->param = nil; |
205 g->status = Gwaiting; | |
206 g->waitreason = "chan send"; | |
207 enqueue(&c->sendq, &mysg); | 203 enqueue(&c->sendq, &mysg); |
208 » runtime·unlock(c); | 204 » runtime·park(runtime·unlock, c, "chan send"); |
209 » runtime·gosched(); | |
210 | 205 |
211 if(g->param == nil) { | 206 if(g->param == nil) { |
212 runtime·lock(c); | 207 runtime·lock(c); |
213 if(!c->closed) | 208 if(!c->closed) |
214 runtime·throw("chansend: spurious wakeup"); | 209 runtime·throw("chansend: spurious wakeup"); |
215 goto closed; | 210 goto closed; |
216 } | 211 } |
217 | 212 |
218 return; | 213 return; |
219 | 214 |
220 asynch: | 215 asynch: |
221 if(c->closed) | 216 if(c->closed) |
222 goto closed; | 217 goto closed; |
223 | 218 |
224 if(c->qcount >= c->dataqsiz) { | 219 if(c->qcount >= c->dataqsiz) { |
225 if(pres != nil) { | 220 if(pres != nil) { |
226 runtime·unlock(c); | 221 runtime·unlock(c); |
227 *pres = false; | 222 *pres = false; |
228 return; | 223 return; |
229 } | 224 } |
230 mysg.g = g; | 225 mysg.g = g; |
231 mysg.elem = nil; | 226 mysg.elem = nil; |
232 mysg.selgen = NOSELGEN; | 227 mysg.selgen = NOSELGEN; |
233 g->status = Gwaiting; | |
234 g->waitreason = "chan send"; | |
235 enqueue(&c->sendq, &mysg); | 228 enqueue(&c->sendq, &mysg); |
236 » » runtime·unlock(c); | 229 » » runtime·park(runtime·unlock, c, "chan send"); |
237 » » runtime·gosched(); | |
238 | 230 |
239 runtime·lock(c); | 231 runtime·lock(c); |
240 goto asynch; | 232 goto asynch; |
241 } | 233 } |
242 c->elemalg->copy(c->elemsize, chanbuf(c, c->sendx), ep); | 234 c->elemalg->copy(c->elemsize, chanbuf(c, c->sendx), ep); |
243 if(++c->sendx == c->dataqsiz) | 235 if(++c->sendx == c->dataqsiz) |
244 c->sendx = 0; | 236 c->sendx = 0; |
245 c->qcount++; | 237 c->qcount++; |
246 | 238 |
247 sg = dequeue(&c->recvq); | 239 sg = dequeue(&c->recvq); |
(...skipping 25 matching lines...) Expand all Loading... |
273 | 265 |
274 if(debug) | 266 if(debug) |
275 runtime·printf("chanrecv: chan=%p\n", c); | 267 runtime·printf("chanrecv: chan=%p\n", c); |
276 | 268 |
277 if(c == nil) { | 269 if(c == nil) { |
278 USED(t); | 270 USED(t); |
279 if(selected != nil) { | 271 if(selected != nil) { |
280 *selected = false; | 272 *selected = false; |
281 return; | 273 return; |
282 } | 274 } |
283 » » g->status = Gwaiting; | 275 » » runtime·park(nil, nil, "chan receive (nil chan)"); |
284 » » g->waitreason = "chan receive (nil chan)"; | |
285 » » runtime·gosched(); | |
286 return; // not reached | 276 return; // not reached |
287 } | 277 } |
288 | 278 |
289 runtime·lock(c); | 279 runtime·lock(c); |
290 if(c->dataqsiz > 0) | 280 if(c->dataqsiz > 0) |
291 goto asynch; | 281 goto asynch; |
292 | 282 |
293 if(c->closed) | 283 if(c->closed) |
294 goto closed; | 284 goto closed; |
295 | 285 |
(...skipping 17 matching lines...) Expand all Loading... |
313 if(selected != nil) { | 303 if(selected != nil) { |
314 runtime·unlock(c); | 304 runtime·unlock(c); |
315 *selected = false; | 305 *selected = false; |
316 return; | 306 return; |
317 } | 307 } |
318 | 308 |
319 mysg.elem = ep; | 309 mysg.elem = ep; |
320 mysg.g = g; | 310 mysg.g = g; |
321 mysg.selgen = NOSELGEN; | 311 mysg.selgen = NOSELGEN; |
322 g->param = nil; | 312 g->param = nil; |
323 g->status = Gwaiting; | |
324 g->waitreason = "chan receive"; | |
325 enqueue(&c->recvq, &mysg); | 313 enqueue(&c->recvq, &mysg); |
326 » runtime·unlock(c); | 314 » runtime·park(runtime·unlock, c, "chan receive"); |
327 » runtime·gosched(); | |
328 | 315 |
329 if(g->param == nil) { | 316 if(g->param == nil) { |
330 runtime·lock(c); | 317 runtime·lock(c); |
331 if(!c->closed) | 318 if(!c->closed) |
332 runtime·throw("chanrecv: spurious wakeup"); | 319 runtime·throw("chanrecv: spurious wakeup"); |
333 goto closed; | 320 goto closed; |
334 } | 321 } |
335 | 322 |
336 if(received != nil) | 323 if(received != nil) |
337 *received = true; | 324 *received = true; |
338 return; | 325 return; |
339 | 326 |
340 asynch: | 327 asynch: |
341 if(c->qcount <= 0) { | 328 if(c->qcount <= 0) { |
342 if(c->closed) | 329 if(c->closed) |
343 goto closed; | 330 goto closed; |
344 | 331 |
345 if(selected != nil) { | 332 if(selected != nil) { |
346 runtime·unlock(c); | 333 runtime·unlock(c); |
347 *selected = false; | 334 *selected = false; |
348 if(received != nil) | 335 if(received != nil) |
349 *received = false; | 336 *received = false; |
350 return; | 337 return; |
351 } | 338 } |
352 mysg.g = g; | 339 mysg.g = g; |
353 mysg.elem = nil; | 340 mysg.elem = nil; |
354 mysg.selgen = NOSELGEN; | 341 mysg.selgen = NOSELGEN; |
355 g->status = Gwaiting; | |
356 g->waitreason = "chan receive"; | |
357 enqueue(&c->recvq, &mysg); | 342 enqueue(&c->recvq, &mysg); |
358 » » runtime·unlock(c); | 343 » » runtime·park(runtime·unlock, c, "chan receive"); |
359 » » runtime·gosched(); | |
360 | 344 |
361 runtime·lock(c); | 345 runtime·lock(c); |
362 goto asynch; | 346 goto asynch; |
363 } | 347 } |
364 if(ep != nil) | 348 if(ep != nil) |
365 c->elemalg->copy(c->elemsize, ep, chanbuf(c, c->recvx)); | 349 c->elemalg->copy(c->elemsize, ep, chanbuf(c, c->recvx)); |
366 c->elemalg->copy(c->elemsize, chanbuf(c, c->recvx), nil); | 350 c->elemalg->copy(c->elemsize, chanbuf(c, c->recvx), nil); |
367 if(++c->recvx == c->dataqsiz) | 351 if(++c->recvx == c->dataqsiz) |
368 c->recvx = 0; | 352 c->recvx = 0; |
369 c->qcount--; | 353 c->qcount--; |
(...skipping 397 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
767 if(c0 && c0 != c) { | 751 if(c0 && c0 != c) { |
768 c = c0; | 752 c = c0; |
769 runtime·unlock(c); | 753 runtime·unlock(c); |
770 } | 754 } |
771 } | 755 } |
772 } | 756 } |
773 | 757 |
774 void | 758 void |
775 runtime·block(void) | 759 runtime·block(void) |
776 { | 760 { |
777 » g->status = Gwaiting;» // forever | 761 » runtime·park(nil, nil, "select (no cases)");» // forever |
778 » g->waitreason = "select (no cases)"; | |
779 » runtime·gosched(); | |
780 } | 762 } |
781 | 763 |
782 static void* selectgo(Select**); | 764 static void* selectgo(Select**); |
783 | 765 |
784 // selectgo(sel *byte); | 766 // selectgo(sel *byte); |
785 // | 767 // |
786 // overwrites return pc on stack to signal which case of the select | 768 // overwrites return pc on stack to signal which case of the select |
787 // to run, so cannot appear at the top of a split stack. | 769 // to run, so cannot appear at the top of a split stack. |
788 #pragma textflag 7 | 770 #pragma textflag 7 |
789 void | 771 void |
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
900 enqueue(&c->recvq, sg); | 882 enqueue(&c->recvq, sg); |
901 break; | 883 break; |
902 | 884 |
903 case CaseSend: | 885 case CaseSend: |
904 enqueue(&c->sendq, sg); | 886 enqueue(&c->sendq, sg); |
905 break; | 887 break; |
906 } | 888 } |
907 } | 889 } |
908 | 890 |
909 g->param = nil; | 891 g->param = nil; |
910 » g->status = Gwaiting; | 892 » runtime·park((void(*)(Lock*))selunlock, (Lock*)sel, "select"); |
911 » g->waitreason = "select"; | |
912 » selunlock(sel); | |
913 » runtime·gosched(); | |
914 | 893 |
915 sellock(sel); | 894 sellock(sel); |
916 sg = g->param; | 895 sg = g->param; |
917 | 896 |
918 // pass 3 - dequeue from unsuccessful chans | 897 // pass 3 - dequeue from unsuccessful chans |
919 // otherwise they stack up on quiet channels | 898 // otherwise they stack up on quiet channels |
920 for(i=0; i<sel->ncase; i++) { | 899 for(i=0; i<sel->ncase; i++) { |
921 cas = &sel->scase[i]; | 900 cas = &sel->scase[i]; |
922 if(cas != (Scase*)sg) { | 901 if(cas != (Scase*)sg) { |
923 c = cas->chan; | 902 c = cas->chan; |
(...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1069 uintptr maxsize; | 1048 uintptr maxsize; |
1070 | 1049 |
1071 chosen = -1; | 1050 chosen = -1; |
1072 word = 0; | 1051 word = 0; |
1073 recvOK = false; | 1052 recvOK = false; |
1074 | 1053 |
1075 maxsize = 0; | 1054 maxsize = 0; |
1076 rcase = (runtimeSelect*)cases.array; | 1055 rcase = (runtimeSelect*)cases.array; |
1077 for(i=0; i<cases.len; i++) { | 1056 for(i=0; i<cases.len; i++) { |
1078 rc = &rcase[i]; | 1057 rc = &rcase[i]; |
1079 » » if(rc->dir == RecvDir && rc->ch != nil && maxsize < rc->typ->ele
m->size) | 1058 » » if(rc->dir == SelectRecv && rc->ch != nil && maxsize < rc->typ->
elem->size) |
1080 maxsize = rc->typ->elem->size; | 1059 maxsize = rc->typ->elem->size; |
1081 } | 1060 } |
1082 | 1061 |
1083 recvptr = nil; | 1062 recvptr = nil; |
1084 if(maxsize > sizeof(void*)) | 1063 if(maxsize > sizeof(void*)) |
1085 recvptr = runtime·mal(maxsize); | 1064 recvptr = runtime·mal(maxsize); |
1086 | 1065 |
1087 newselect(cases.len, &sel); | 1066 newselect(cases.len, &sel); |
1088 for(i=0; i<cases.len; i++) { | 1067 for(i=0; i<cases.len; i++) { |
1089 rc = &rcase[i]; | 1068 rc = &rcase[i]; |
(...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1240 { | 1219 { |
1241 sgp->link = nil; | 1220 sgp->link = nil; |
1242 if(q->first == nil) { | 1221 if(q->first == nil) { |
1243 q->first = sgp; | 1222 q->first = sgp; |
1244 q->last = sgp; | 1223 q->last = sgp; |
1245 return; | 1224 return; |
1246 } | 1225 } |
1247 q->last->link = sgp; | 1226 q->last->link = sgp; |
1248 q->last = sgp; | 1227 q->last = sgp; |
1249 } | 1228 } |
LEFT | RIGHT |