2014-07-29 Ed Smith-Rowland <3dw4rd@verizon.net>
[official-gcc.git] / libgo / runtime / chan.c
blob4559c0f2d0d28a8d8503a30ecfd70a4a4694d38f
1 // AUTO-GENERATED by autogen.sh; DO NOT EDIT
3 #include "runtime.h"
4 #include "arch.h"
5 #include "go-type.h"
6 #include "race.h"
7 #include "malloc.h"
8 #include "chan.h"
10 #line 13 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/chan.goc"
11 uint32 runtime_Hchansize = sizeof ( Hchan ) ;
12 #line 15 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/chan.goc"
13 static void dequeueg ( WaitQ* ) ;
14 static SudoG* dequeue ( WaitQ* ) ;
15 static void enqueue ( WaitQ* , SudoG* ) ;
16 static void racesync ( Hchan* , SudoG* ) ;
17 #line 20 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/chan.goc"
18 static Hchan*
19 makechan ( ChanType *t , int64 hint )
21 Hchan *c;
22 uintptr n;
23 const Type *elem;
24 #line 27 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/chan.goc"
25 elem = t->__element_type;
26 #line 30 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/chan.goc"
27 if ( elem->__size >= ( 1<<16 ) )
28 runtime_throw ( "makechan: invalid channel element type" ) ;
29 #line 33 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/chan.goc"
30 if ( hint < 0 || ( intgo ) hint != hint || ( elem->__size > 0 && ( uintptr ) hint > ( MaxMem - sizeof ( *c ) ) / elem->__size ) )
31 runtime_panicstring ( "makechan: size out of range" ) ;
32 #line 36 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/chan.goc"
33 n = sizeof ( *c ) ;
34 n = ROUND ( n , elem->__align ) ;
35 #line 40 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/chan.goc"
36 c = ( Hchan* ) runtime_mallocgc ( sizeof ( *c ) + hint*elem->__size , ( uintptr ) t | TypeInfo_Chan , 0 ) ;
37 c->elemsize = elem->__size;
38 c->elemtype = elem;
39 c->dataqsiz = hint;
40 #line 45 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/chan.goc"
41 if ( debug )
42 runtime_printf ( "makechan: chan=%p; elemsize=%D; dataqsiz=%D\n" ,
43 c , ( int64 ) elem->__size , ( int64 ) c->dataqsiz ) ;
44 #line 49 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/chan.goc"
45 return c;
47 Hchan* reflect_makechan(ChanType* t, uint64 size) __asm__ (GOSYM_PREFIX "reflect.makechan");
48 Hchan* reflect_makechan(ChanType* t, uint64 size)
50 Hchan* c;
51 #line 52 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/chan.goc"
53 c = makechan(t, size);
54 return c;
57 #line 56 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/chan.goc"
58 Hchan*
59 __go_new_channel ( ChanType *t , uintptr hint )
61 return makechan ( t , hint ) ;
63 #line 62 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/chan.goc"
64 Hchan*
65 __go_new_channel_big ( ChanType *t , uint64 hint )
67 return makechan ( t , hint ) ;
69 #line 82 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/chan.goc"
70 static bool
71 chansend ( ChanType *t , Hchan *c , byte *ep , bool block , void *pc )
73 SudoG *sg;
74 SudoG mysg;
75 G* gp;
76 int64 t0;
77 G* g;
78 #line 91 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/chan.goc"
79 g = runtime_g ( ) ;
80 #line 93 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/chan.goc"
81 if ( raceenabled )
82 runtime_racereadobjectpc ( ep , t->__element_type , runtime_getcallerpc ( &t ) , chansend ) ;
83 #line 96 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/chan.goc"
84 if ( c == nil ) {
85 USED ( t ) ;
86 if ( !block )
87 return false;
88 runtime_park ( nil , nil , "chan send (nil chan)" ) ;
89 return false;
91 #line 104 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/chan.goc"
92 if ( runtime_gcwaiting ( ) )
93 runtime_gosched ( ) ;
94 #line 107 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/chan.goc"
95 if ( debug ) {
96 runtime_printf ( "chansend: chan=%p\n" , c ) ;
98 #line 111 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/chan.goc"
99 t0 = 0;
100 mysg.releasetime = 0;
101 if ( runtime_blockprofilerate > 0 ) {
102 t0 = runtime_cputicks ( ) ;
103 mysg.releasetime = -1;
105 #line 118 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/chan.goc"
106 runtime_lock ( c ) ;
107 if ( raceenabled )
108 runtime_racereadpc ( c , pc , chansend ) ;
109 if ( c->closed )
110 goto closed;
111 #line 124 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/chan.goc"
112 if ( c->dataqsiz > 0 )
113 goto asynch;
114 #line 127 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/chan.goc"
115 sg = dequeue ( &c->recvq ) ;
116 if ( sg != nil ) {
117 if ( raceenabled )
118 racesync ( c , sg ) ;
119 runtime_unlock ( c ) ;
120 #line 133 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/chan.goc"
121 gp = sg->g;
122 gp->param = sg;
123 if ( sg->elem != nil )
124 runtime_memmove ( sg->elem , ep , c->elemsize ) ;
125 if ( sg->releasetime )
126 sg->releasetime = runtime_cputicks ( ) ;
127 runtime_ready ( gp ) ;
128 return true;
130 #line 143 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/chan.goc"
131 if ( !block ) {
132 runtime_unlock ( c ) ;
133 return false;
135 #line 148 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/chan.goc"
136 mysg.elem = ep;
137 mysg.g = g;
138 mysg.selectdone = nil;
139 g->param = nil;
140 enqueue ( &c->sendq , &mysg ) ;
141 runtime_parkunlock ( c , "chan send" ) ;
142 #line 155 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/chan.goc"
143 if ( g->param == nil ) {
144 runtime_lock ( c ) ;
145 if ( !c->closed )
146 runtime_throw ( "chansend: spurious wakeup" ) ;
147 goto closed;
149 #line 162 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/chan.goc"
150 if ( mysg.releasetime > 0 )
151 runtime_blockevent ( mysg.releasetime - t0 , 2 ) ;
152 #line 165 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/chan.goc"
153 return true;
154 #line 167 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/chan.goc"
155 asynch:
156 if ( c->closed )
157 goto closed;
158 #line 171 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/chan.goc"
159 if ( c->qcount >= c->dataqsiz ) {
160 if ( !block ) {
161 runtime_unlock ( c ) ;
162 return false;
164 mysg.g = g;
165 mysg.elem = nil;
166 mysg.selectdone = nil;
167 enqueue ( &c->sendq , &mysg ) ;
168 runtime_parkunlock ( c , "chan send" ) ;
169 #line 182 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/chan.goc"
170 runtime_lock ( c ) ;
171 goto asynch;
173 #line 186 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/chan.goc"
174 if ( raceenabled )
175 runtime_racerelease ( chanbuf ( c , c->sendx ) ) ;
176 #line 189 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/chan.goc"
177 runtime_memmove ( chanbuf ( c , c->sendx ) , ep , c->elemsize ) ;
178 if ( ++c->sendx == c->dataqsiz )
179 c->sendx = 0;
180 c->qcount++;
181 #line 194 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/chan.goc"
182 sg = dequeue ( &c->recvq ) ;
183 if ( sg != nil ) {
184 gp = sg->g;
185 runtime_unlock ( c ) ;
186 if ( sg->releasetime )
187 sg->releasetime = runtime_cputicks ( ) ;
188 runtime_ready ( gp ) ;
189 } else
190 runtime_unlock ( c ) ;
191 if ( mysg.releasetime > 0 )
192 runtime_blockevent ( mysg.releasetime - t0 , 2 ) ;
193 return true;
194 #line 207 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/chan.goc"
195 closed:
196 runtime_unlock ( c ) ;
197 runtime_panicstring ( "send on closed channel" ) ;
198 return false;
200 #line 214 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/chan.goc"
201 static bool
202 chanrecv ( ChanType *t , Hchan* c , byte *ep , bool block , bool *received )
204 SudoG *sg;
205 SudoG mysg;
206 G *gp;
207 int64 t0;
208 G *g;
209 #line 223 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/chan.goc"
210 if ( runtime_gcwaiting ( ) )
211 runtime_gosched ( ) ;
212 #line 228 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/chan.goc"
213 if ( debug )
214 runtime_printf ( "chanrecv: chan=%p\n" , c ) ;
215 #line 231 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/chan.goc"
216 g = runtime_g ( ) ;
217 #line 233 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/chan.goc"
218 if ( c == nil ) {
219 USED ( t ) ;
220 if ( !block )
221 return false;
222 runtime_park ( nil , nil , "chan receive (nil chan)" ) ;
223 return false;
225 #line 241 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/chan.goc"
226 t0 = 0;
227 mysg.releasetime = 0;
228 if ( runtime_blockprofilerate > 0 ) {
229 t0 = runtime_cputicks ( ) ;
230 mysg.releasetime = -1;
232 #line 248 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/chan.goc"
233 runtime_lock ( c ) ;
234 if ( c->dataqsiz > 0 )
235 goto asynch;
236 #line 252 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/chan.goc"
237 if ( c->closed )
238 goto closed;
239 #line 255 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/chan.goc"
240 sg = dequeue ( &c->sendq ) ;
241 if ( sg != nil ) {
242 if ( raceenabled )
243 racesync ( c , sg ) ;
244 runtime_unlock ( c ) ;
245 #line 261 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/chan.goc"
246 if ( ep != nil )
247 runtime_memmove ( ep , sg->elem , c->elemsize ) ;
248 gp = sg->g;
249 gp->param = sg;
250 if ( sg->releasetime )
251 sg->releasetime = runtime_cputicks ( ) ;
252 runtime_ready ( gp ) ;
253 #line 269 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/chan.goc"
254 if ( received != nil )
255 *received = true;
256 return true;
258 #line 274 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/chan.goc"
259 if ( !block ) {
260 runtime_unlock ( c ) ;
261 return false;
263 #line 279 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/chan.goc"
264 mysg.elem = ep;
265 mysg.g = g;
266 mysg.selectdone = nil;
267 g->param = nil;
268 enqueue ( &c->recvq , &mysg ) ;
269 runtime_parkunlock ( c , "chan receive" ) ;
270 #line 286 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/chan.goc"
271 if ( g->param == nil ) {
272 runtime_lock ( c ) ;
273 if ( !c->closed )
274 runtime_throw ( "chanrecv: spurious wakeup" ) ;
275 goto closed;
277 #line 293 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/chan.goc"
278 if ( received != nil )
279 *received = true;
280 if ( mysg.releasetime > 0 )
281 runtime_blockevent ( mysg.releasetime - t0 , 2 ) ;
282 return true;
283 #line 299 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/chan.goc"
284 asynch:
285 if ( c->qcount <= 0 ) {
286 if ( c->closed )
287 goto closed;
288 #line 304 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/chan.goc"
289 if ( !block ) {
290 runtime_unlock ( c ) ;
291 if ( received != nil )
292 *received = false;
293 return false;
295 mysg.g = g;
296 mysg.elem = nil;
297 mysg.selectdone = nil;
298 enqueue ( &c->recvq , &mysg ) ;
299 runtime_parkunlock ( c , "chan receive" ) ;
300 #line 316 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/chan.goc"
301 runtime_lock ( c ) ;
302 goto asynch;
304 #line 320 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/chan.goc"
305 if ( raceenabled )
306 runtime_raceacquire ( chanbuf ( c , c->recvx ) ) ;
307 #line 323 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/chan.goc"
308 if ( ep != nil )
309 runtime_memmove ( ep , chanbuf ( c , c->recvx ) , c->elemsize ) ;
310 runtime_memclr ( chanbuf ( c , c->recvx ) , c->elemsize ) ;
311 if ( ++c->recvx == c->dataqsiz )
312 c->recvx = 0;
313 c->qcount--;
314 #line 330 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/chan.goc"
315 sg = dequeue ( &c->sendq ) ;
316 if ( sg != nil ) {
317 gp = sg->g;
318 runtime_unlock ( c ) ;
319 if ( sg->releasetime )
320 sg->releasetime = runtime_cputicks ( ) ;
321 runtime_ready ( gp ) ;
322 } else
323 runtime_unlock ( c ) ;
324 #line 340 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/chan.goc"
325 if ( received != nil )
326 *received = true;
327 if ( mysg.releasetime > 0 )
328 runtime_blockevent ( mysg.releasetime - t0 , 2 ) ;
329 return true;
330 #line 346 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/chan.goc"
331 closed:
332 if ( ep != nil )
333 runtime_memclr ( ep , c->elemsize ) ;
334 if ( received != nil )
335 *received = false;
336 if ( raceenabled )
337 runtime_raceacquire ( c ) ;
338 runtime_unlock ( c ) ;
339 if ( mysg.releasetime > 0 )
340 runtime_blockevent ( mysg.releasetime - t0 , 2 ) ;
341 return true;
343 #line 361 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/chan.goc"
344 void
345 __go_send_small ( ChanType *t , Hchan* c , uint64 val )
347 union
349 byte b[sizeof ( uint64 ) ];
350 uint64 v;
351 } u;
352 byte *v;
353 #line 371 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/chan.goc"
354 u.v = val;
355 #ifndef WORDS_BIGENDIAN
356 v = u.b;
357 #else
358 v = u.b + sizeof ( uint64 ) - t->__element_type->__size;
359 #endif
360 chansend ( t , c , v , true , runtime_getcallerpc ( &t ) ) ;
362 #line 382 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/chan.goc"
363 void
364 __go_send_big ( ChanType *t , Hchan* c , byte* v )
366 chansend ( t , c , v , true , runtime_getcallerpc ( &t ) ) ;
368 #line 390 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/chan.goc"
369 void
370 __go_receive ( ChanType *t , Hchan* c , byte* v )
372 chanrecv ( t , c , v , true , nil ) ;
374 #line 396 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/chan.goc"
375 _Bool runtime_chanrecv2 ( ChanType *t , Hchan* c , byte* v )
376 __asm__ ( GOSYM_PREFIX "runtime.chanrecv2" ) ;
377 #line 399 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/chan.goc"
378 _Bool
379 runtime_chanrecv2 ( ChanType *t , Hchan* c , byte* v )
381 bool received = false;
382 #line 404 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/chan.goc"
383 chanrecv ( t , c , v , true , &received ) ;
384 return received;
386 bool runtime_selectnbsend(ChanType* t, Hchan* c, byte* elem) __asm__ (GOSYM_PREFIX "runtime.selectnbsend");
387 bool runtime_selectnbsend(ChanType* t, Hchan* c, byte* elem)
389 bool selected;
390 #line 425 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/chan.goc"
392 selected = chansend(t, c, elem, false, runtime_getcallerpc(&t));
393 return selected;
395 bool runtime_selectnbrecv(ChanType* t, byte* elem, Hchan* c) __asm__ (GOSYM_PREFIX "runtime.selectnbrecv");
396 bool runtime_selectnbrecv(ChanType* t, byte* elem, Hchan* c)
398 bool selected;
399 #line 446 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/chan.goc"
401 selected = chanrecv(t, c, elem, false, nil);
402 return selected;
404 bool runtime_selectnbrecv2(ChanType* t, byte* elem, bool* received, Hchan* c) __asm__ (GOSYM_PREFIX "runtime.selectnbrecv2");
405 bool runtime_selectnbrecv2(ChanType* t, byte* elem, bool* received, Hchan* c)
407 bool selected;
408 #line 467 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/chan.goc"
410 bool r;
412 selected = chanrecv(t, c, elem, false, received == nil ? nil : &r);
413 if(received != nil)
414 *received = r;
415 return selected;
417 bool reflect_chansend(ChanType* t, Hchan* c, byte* elem, bool nb) __asm__ (GOSYM_PREFIX "reflect.chansend");
418 bool reflect_chansend(ChanType* t, Hchan* c, byte* elem, bool nb)
420 bool selected;
421 #line 475 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/chan.goc"
423 selected = chansend(t, c, elem, !nb, runtime_getcallerpc(&t));
424 return selected;
426 struct reflect_chanrecv_ret {
427 bool selected;
428 bool received;
430 struct reflect_chanrecv_ret reflect_chanrecv(ChanType* t, Hchan* c, bool nb, byte* elem) __asm__ (GOSYM_PREFIX "reflect.chanrecv");
431 struct reflect_chanrecv_ret reflect_chanrecv(ChanType* t, Hchan* c, bool nb, byte* elem)
433 bool selected;
434 bool received;
435 #line 479 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/chan.goc"
437 received = false;
438 selected = chanrecv(t, c, elem, !nb, &received);
440 struct reflect_chanrecv_ret __ret;
441 __ret.selected = selected;
442 __ret.received = received;
443 return __ret;
447 #line 484 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/chan.goc"
448 static Select* newselect ( int32 ) ;
449 byte* runtime_newselect(int32 size) __asm__ (GOSYM_PREFIX "runtime.newselect");
450 byte* runtime_newselect(int32 size)
452 byte* sel;
453 #line 486 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/chan.goc"
455 sel = (byte*)newselect(size);
456 return sel;
459 #line 490 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/chan.goc"
460 static Select*
461 newselect ( int32 size )
463 int32 n;
464 Select *sel;
465 #line 496 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/chan.goc"
466 n = 0;
467 if ( size > 1 )
468 n = size-1;
469 #line 504 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/chan.goc"
470 sel = runtime_mal ( sizeof ( *sel ) +
471 n*sizeof ( sel->scase[0] ) +
472 size*sizeof ( sel->lockorder[0] ) +
473 size*sizeof ( sel->pollorder[0] ) ) ;
474 #line 509 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/chan.goc"
475 sel->tcase = size;
476 sel->ncase = 0;
477 sel->lockorder = ( void* ) ( sel->scase + size ) ;
478 sel->pollorder = ( void* ) ( sel->lockorder + size ) ;
479 #line 514 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/chan.goc"
480 if ( debug )
481 runtime_printf ( "newselect s=%p size=%d\n" , sel , size ) ;
482 return sel;
484 #line 520 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/chan.goc"
485 static void selectsend ( Select *sel , Hchan *c , int index , void *elem ) ;
486 void runtime_selectsend(Select* sel, Hchan* c, byte* elem, int32 index) __asm__ (GOSYM_PREFIX "runtime.selectsend");
487 void runtime_selectsend(Select* sel, Hchan* c, byte* elem, int32 index)
489 #line 522 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/chan.goc"
491 // nil cases do not compete
492 if(c != nil)
493 selectsend(sel, c, index, elem);
496 #line 528 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/chan.goc"
497 static void
498 selectsend ( Select *sel , Hchan *c , int index , void *elem )
500 int32 i;
501 Scase *cas;
502 #line 534 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/chan.goc"
503 i = sel->ncase;
504 if ( i >= sel->tcase )
505 runtime_throw ( "selectsend: too many cases" ) ;
506 sel->ncase = i+1;
507 cas = &sel->scase[i];
508 #line 540 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/chan.goc"
509 cas->index = index;
510 cas->chan = c;
511 cas->kind = CaseSend;
512 cas->sg.elem = elem;
513 #line 545 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/chan.goc"
514 if ( debug )
515 runtime_printf ( "selectsend s=%p index=%d chan=%p\n" ,
516 sel , cas->index , cas->chan ) ;
518 #line 551 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/chan.goc"
519 static void selectrecv ( Select *sel , Hchan *c , int index , void *elem , bool* ) ;
520 void runtime_selectrecv(Select* sel, Hchan* c, byte* elem, int32 index) __asm__ (GOSYM_PREFIX "runtime.selectrecv");
521 void runtime_selectrecv(Select* sel, Hchan* c, byte* elem, int32 index)
523 #line 553 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/chan.goc"
525 // nil cases do not compete
526 if(c != nil)
527 selectrecv(sel, c, index, elem, nil);
529 void runtime_selectrecv2(Select* sel, Hchan* c, byte* elem, bool* received, int32 index) __asm__ (GOSYM_PREFIX "runtime.selectrecv2");
530 void runtime_selectrecv2(Select* sel, Hchan* c, byte* elem, bool* received, int32 index)
532 #line 559 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/chan.goc"
534 // nil cases do not compete
535 if(c != nil)
536 selectrecv(sel, c, index, elem, received);
539 #line 565 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/chan.goc"
540 static void
541 selectrecv ( Select *sel , Hchan *c , int index , void *elem , bool *received )
543 int32 i;
544 Scase *cas;
545 #line 571 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/chan.goc"
546 i = sel->ncase;
547 if ( i >= sel->tcase )
548 runtime_throw ( "selectrecv: too many cases" ) ;
549 sel->ncase = i+1;
550 cas = &sel->scase[i];
551 cas->index = index;
552 cas->chan = c;
553 #line 579 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/chan.goc"
554 cas->kind = CaseRecv;
555 cas->sg.elem = elem;
556 cas->receivedp = received;
557 #line 583 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/chan.goc"
558 if ( debug )
559 runtime_printf ( "selectrecv s=%p index=%d chan=%p\n" ,
560 sel , cas->index , cas->chan ) ;
562 #line 589 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/chan.goc"
563 static void selectdefault ( Select* , int ) ;
564 void runtime_selectdefault(Select* sel, int32 index) __asm__ (GOSYM_PREFIX "runtime.selectdefault");
565 void runtime_selectdefault(Select* sel, int32 index)
567 #line 591 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/chan.goc"
569 selectdefault(sel, index);
572 #line 595 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/chan.goc"
573 static void
574 selectdefault ( Select *sel , int32 index )
576 int32 i;
577 Scase *cas;
578 #line 601 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/chan.goc"
579 i = sel->ncase;
580 if ( i >= sel->tcase )
581 runtime_throw ( "selectdefault: too many cases" ) ;
582 sel->ncase = i+1;
583 cas = &sel->scase[i];
584 cas->index = index;
585 cas->chan = nil;
586 #line 609 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/chan.goc"
587 cas->kind = CaseDefault;
588 #line 611 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/chan.goc"
589 if ( debug )
590 runtime_printf ( "selectdefault s=%p index=%d\n" ,
591 sel , cas->index ) ;
593 #line 616 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/chan.goc"
594 static void
595 sellock ( Select *sel )
597 uint32 i;
598 Hchan *c , *c0;
599 #line 622 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/chan.goc"
600 c = nil;
601 for ( i=0; i<sel->ncase; i++ ) {
602 c0 = sel->lockorder[i];
603 if ( c0 && c0 != c ) {
604 c = sel->lockorder[i];
605 runtime_lock ( c ) ;
609 #line 632 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/chan.goc"
610 static void
611 selunlock ( Select *sel )
613 int32 i , n , r;
614 Hchan *c;
615 #line 646 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/chan.goc"
616 n = ( int32 ) sel->ncase;
617 r = 0;
618 #line 649 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/chan.goc"
619 if ( n>0 && sel->lockorder[0] == nil )
620 r = 1;
621 for ( i = n-1; i >= r; i-- ) {
622 c = sel->lockorder[i];
623 if ( i>0 && sel->lockorder[i-1] == c )
624 continue;
625 runtime_unlock ( c ) ;
628 #line 659 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/chan.goc"
629 static bool
630 selparkcommit ( G *gp , void *sel )
632 USED ( gp ) ;
633 selunlock ( sel ) ;
634 return true;
636 void runtime_block() __asm__ (GOSYM_PREFIX "runtime.block");
637 void runtime_block()
639 #line 667 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/chan.goc"
641 runtime_park(nil, nil, "select (no cases)"); // forever
644 #line 671 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/chan.goc"
645 static int selectgo ( Select** ) ;
646 int32 runtime_selectgo(Select* sel) __asm__ (GOSYM_PREFIX "runtime.selectgo");
647 int32 runtime_selectgo(Select* sel)
649 int32 ret;
650 #line 675 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/chan.goc"
652 return selectgo(&sel);
653 return ret;
656 #line 679 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/chan.goc"
657 static int
658 selectgo ( Select **selp )
660 Select *sel;
661 uint32 o , i , j , k , done;
662 int64 t0;
663 Scase *cas , *dfl;
664 Hchan *c;
665 SudoG *sg;
666 G *gp;
667 int index;
668 G *g;
669 #line 692 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/chan.goc"
670 sel = *selp;
671 if ( runtime_gcwaiting ( ) )
672 runtime_gosched ( ) ;
673 #line 696 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/chan.goc"
674 if ( debug )
675 runtime_printf ( "select: sel=%p\n" , sel ) ;
676 #line 699 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/chan.goc"
677 g = runtime_g ( ) ;
678 #line 701 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/chan.goc"
679 t0 = 0;
680 if ( runtime_blockprofilerate > 0 ) {
681 t0 = runtime_cputicks ( ) ;
682 for ( i=0; i<sel->ncase; i++ )
683 sel->scase[i].sg.releasetime = -1;
685 #line 717 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/chan.goc"
686 for ( i=0; i<sel->ncase; i++ )
687 sel->pollorder[i] = i;
688 for ( i=1; i<sel->ncase; i++ ) {
689 o = sel->pollorder[i];
690 j = runtime_fastrand1 ( ) % ( i+1 ) ;
691 sel->pollorder[i] = sel->pollorder[j];
692 sel->pollorder[j] = o;
694 #line 728 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/chan.goc"
695 for ( i=0; i<sel->ncase; i++ ) {
696 j = i;
697 c = sel->scase[j].chan;
698 while ( j > 0 && sel->lockorder[k= ( j-1 ) /2] < c ) {
699 sel->lockorder[j] = sel->lockorder[k];
700 j = k;
702 sel->lockorder[j] = c;
704 for ( i=sel->ncase; i-->0; ) {
705 c = sel->lockorder[i];
706 sel->lockorder[i] = sel->lockorder[0];
707 j = 0;
708 for ( ;; ) {
709 k = j*2+1;
710 if ( k >= i )
711 break;
712 if ( k+1 < i && sel->lockorder[k] < sel->lockorder[k+1] )
713 k++;
714 if ( c < sel->lockorder[k] ) {
715 sel->lockorder[j] = sel->lockorder[k];
716 j = k;
717 continue;
719 break;
721 sel->lockorder[j] = c;
723 #line 763 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/chan.goc"
724 sellock ( sel ) ;
725 #line 765 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/chan.goc"
726 loop:
727 #line 767 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/chan.goc"
728 dfl = nil;
729 for ( i=0; i<sel->ncase; i++ ) {
730 o = sel->pollorder[i];
731 cas = &sel->scase[o];
732 c = cas->chan;
733 #line 773 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/chan.goc"
734 switch ( cas->kind ) {
735 case CaseRecv:
736 if ( c->dataqsiz > 0 ) {
737 if ( c->qcount > 0 )
738 goto asyncrecv;
739 } else {
740 sg = dequeue ( &c->sendq ) ;
741 if ( sg != nil )
742 goto syncrecv;
744 if ( c->closed )
745 goto rclose;
746 break;
747 #line 787 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/chan.goc"
748 case CaseSend:
749 if ( raceenabled )
750 runtime_racereadpc ( c , runtime_selectgo , chansend ) ;
751 if ( c->closed )
752 goto sclose;
753 if ( c->dataqsiz > 0 ) {
754 if ( c->qcount < c->dataqsiz )
755 goto asyncsend;
756 } else {
757 sg = dequeue ( &c->recvq ) ;
758 if ( sg != nil )
759 goto syncsend;
761 break;
762 #line 802 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/chan.goc"
763 case CaseDefault:
764 dfl = cas;
765 break;
768 #line 808 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/chan.goc"
769 if ( dfl != nil ) {
770 selunlock ( sel ) ;
771 cas = dfl;
772 goto retc;
774 #line 816 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/chan.goc"
775 done = 0;
776 for ( i=0; i<sel->ncase; i++ ) {
777 o = sel->pollorder[i];
778 cas = &sel->scase[o];
779 c = cas->chan;
780 sg = &cas->sg;
781 sg->g = g;
782 sg->selectdone = &done;
783 #line 825 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/chan.goc"
784 switch ( cas->kind ) {
785 case CaseRecv:
786 enqueue ( &c->recvq , sg ) ;
787 break;
788 #line 830 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/chan.goc"
789 case CaseSend:
790 enqueue ( &c->sendq , sg ) ;
791 break;
794 #line 836 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/chan.goc"
795 g->param = nil;
796 runtime_park ( selparkcommit , sel , "select" ) ;
797 #line 839 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/chan.goc"
798 sellock ( sel ) ;
799 sg = g->param;
800 #line 844 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/chan.goc"
801 for ( i=0; i<sel->ncase; i++ ) {
802 cas = &sel->scase[i];
803 if ( cas != ( Scase* ) sg ) {
804 c = cas->chan;
805 if ( cas->kind == CaseSend )
806 dequeueg ( &c->sendq ) ;
807 else
808 dequeueg ( &c->recvq ) ;
811 #line 855 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/chan.goc"
812 if ( sg == nil )
813 goto loop;
814 #line 858 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/chan.goc"
815 cas = ( Scase* ) sg;
816 c = cas->chan;
817 #line 861 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/chan.goc"
818 if ( c->dataqsiz > 0 )
819 runtime_throw ( "selectgo: shouldn't happen" ) ;
820 #line 864 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/chan.goc"
821 if ( debug )
822 runtime_printf ( "wait-return: sel=%p c=%p cas=%p kind=%d\n" ,
823 sel , c , cas , cas->kind ) ;
824 #line 868 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/chan.goc"
825 if ( cas->kind == CaseRecv ) {
826 if ( cas->receivedp != nil )
827 *cas->receivedp = true;
829 #line 873 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/chan.goc"
830 if ( raceenabled ) {
831 if ( cas->kind == CaseRecv && cas->sg.elem != nil )
832 runtime_racewriteobjectpc ( cas->sg.elem , c->elemtype , selectgo , chanrecv ) ;
833 else if ( cas->kind == CaseSend )
834 runtime_racereadobjectpc ( cas->sg.elem , c->elemtype , selectgo , chansend ) ;
836 #line 880 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/chan.goc"
837 selunlock ( sel ) ;
838 goto retc;
839 #line 883 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/chan.goc"
840 asyncrecv:
841 #line 885 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/chan.goc"
842 if ( raceenabled ) {
843 if ( cas->sg.elem != nil )
844 runtime_racewriteobjectpc ( cas->sg.elem , c->elemtype , selectgo , chanrecv ) ;
845 runtime_raceacquire ( chanbuf ( c , c->recvx ) ) ;
847 if ( cas->receivedp != nil )
848 *cas->receivedp = true;
849 if ( cas->sg.elem != nil )
850 runtime_memmove ( cas->sg.elem , chanbuf ( c , c->recvx ) , c->elemsize ) ;
851 runtime_memclr ( chanbuf ( c , c->recvx ) , c->elemsize ) ;
852 if ( ++c->recvx == c->dataqsiz )
853 c->recvx = 0;
854 c->qcount--;
855 sg = dequeue ( &c->sendq ) ;
856 if ( sg != nil ) {
857 gp = sg->g;
858 selunlock ( sel ) ;
859 if ( sg->releasetime )
860 sg->releasetime = runtime_cputicks ( ) ;
861 runtime_ready ( gp ) ;
862 } else {
863 selunlock ( sel ) ;
865 goto retc;
866 #line 910 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/chan.goc"
867 asyncsend:
868 #line 912 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/chan.goc"
869 if ( raceenabled ) {
870 runtime_racerelease ( chanbuf ( c , c->sendx ) ) ;
871 runtime_racereadobjectpc ( cas->sg.elem , c->elemtype , selectgo , chansend ) ;
873 runtime_memmove ( chanbuf ( c , c->sendx ) , cas->sg.elem , c->elemsize ) ;
874 if ( ++c->sendx == c->dataqsiz )
875 c->sendx = 0;
876 c->qcount++;
877 sg = dequeue ( &c->recvq ) ;
878 if ( sg != nil ) {
879 gp = sg->g;
880 selunlock ( sel ) ;
881 if ( sg->releasetime )
882 sg->releasetime = runtime_cputicks ( ) ;
883 runtime_ready ( gp ) ;
884 } else {
885 selunlock ( sel ) ;
887 goto retc;
888 #line 932 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/chan.goc"
889 syncrecv:
890 #line 934 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/chan.goc"
891 if ( raceenabled ) {
892 if ( cas->sg.elem != nil )
893 runtime_racewriteobjectpc ( cas->sg.elem , c->elemtype , selectgo , chanrecv ) ;
894 racesync ( c , sg ) ;
896 selunlock ( sel ) ;
897 if ( debug )
898 runtime_printf ( "syncrecv: sel=%p c=%p o=%d\n" , sel , c , o ) ;
899 if ( cas->receivedp != nil )
900 *cas->receivedp = true;
901 if ( cas->sg.elem != nil )
902 runtime_memmove ( cas->sg.elem , sg->elem , c->elemsize ) ;
903 gp = sg->g;
904 gp->param = sg;
905 if ( sg->releasetime )
906 sg->releasetime = runtime_cputicks ( ) ;
907 runtime_ready ( gp ) ;
908 goto retc;
909 #line 953 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/chan.goc"
910 rclose:
911 #line 955 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/chan.goc"
912 selunlock ( sel ) ;
913 if ( cas->receivedp != nil )
914 *cas->receivedp = false;
915 if ( cas->sg.elem != nil )
916 runtime_memclr ( cas->sg.elem , c->elemsize ) ;
917 if ( raceenabled )
918 runtime_raceacquire ( c ) ;
919 goto retc;
920 #line 964 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/chan.goc"
921 syncsend:
922 #line 966 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/chan.goc"
923 if ( raceenabled ) {
924 runtime_racereadobjectpc ( cas->sg.elem , c->elemtype , selectgo , chansend ) ;
925 racesync ( c , sg ) ;
927 selunlock ( sel ) ;
928 if ( debug )
929 runtime_printf ( "syncsend: sel=%p c=%p o=%d\n" , sel , c , o ) ;
930 if ( sg->elem != nil )
931 runtime_memmove ( sg->elem , cas->sg.elem , c->elemsize ) ;
932 gp = sg->g;
933 gp->param = sg;
934 if ( sg->releasetime )
935 sg->releasetime = runtime_cputicks ( ) ;
936 runtime_ready ( gp ) ;
937 #line 981 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/chan.goc"
938 retc:
939 #line 983 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/chan.goc"
940 index = cas->index;
941 if ( cas->sg.releasetime > 0 )
942 runtime_blockevent ( cas->sg.releasetime - t0 , 2 ) ;
943 runtime_free ( sel ) ;
944 return index;
945 #line 989 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/chan.goc"
946 sclose:
947 #line 991 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/chan.goc"
948 selunlock ( sel ) ;
949 runtime_panicstring ( "send on closed channel" ) ;
950 return 0;
952 #line 997 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/chan.goc"
953 typedef struct runtimeSelect runtimeSelect;
954 struct runtimeSelect
956 uintptr dir;
957 ChanType *typ;
958 Hchan *ch;
959 byte *val;
960 } ;
961 #line 1007 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/chan.goc"
962 enum SelectDir {
963 SelectSend = 1 ,
964 SelectRecv ,
965 SelectDefault ,
966 } ;
967 struct reflect_rselect_ret {
968 intgo chosen;
969 bool recvOK;
971 struct reflect_rselect_ret reflect_rselect(Slice cases) __asm__ (GOSYM_PREFIX "reflect.rselect");
972 struct reflect_rselect_ret reflect_rselect(Slice cases)
974 intgo chosen;
975 bool recvOK;
976 #line 1013 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/chan.goc"
978 int32 i;
979 Select *sel;
980 runtimeSelect* rcase, *rc;
982 chosen = -1;
983 recvOK = false;
985 rcase = (runtimeSelect*)cases.__values;
987 sel = newselect(cases.__count);
988 for(i=0; i<cases.__count; i++) {
989 rc = &rcase[i];
990 switch(rc->dir) {
991 case SelectDefault:
992 selectdefault(sel, i);
993 break;
994 case SelectSend:
995 if(rc->ch == nil)
996 break;
997 selectsend(sel, rc->ch, i, rc->val);
998 break;
999 case SelectRecv:
1000 if(rc->ch == nil)
1001 break;
1002 selectrecv(sel, rc->ch, i, rc->val, &recvOK);
1003 break;
1007 chosen = (intgo)(uintptr)selectgo(&sel);
1009 struct reflect_rselect_ret __ret;
1010 __ret.chosen = chosen;
1011 __ret.recvOK = recvOK;
1012 return __ret;
1016 #line 1046 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/chan.goc"
1017 static void closechan ( Hchan *c , void *pc ) ;
1018 void runtime_closechan(Hchan* c) __asm__ (GOSYM_PREFIX "runtime.closechan");
1019 void runtime_closechan(Hchan* c)
1021 #line 1048 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/chan.goc"
1023 closechan(c, runtime_getcallerpc(&c));
1025 void reflect_chanclose(Hchan* c) __asm__ (GOSYM_PREFIX "reflect.chanclose");
1026 void reflect_chanclose(Hchan* c)
1028 #line 1052 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/chan.goc"
1030 closechan(c, runtime_getcallerpc(&c));
1033 #line 1056 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/chan.goc"
1034 static void
1035 closechan ( Hchan *c , void *pc )
1037 SudoG *sg;
1038 G* gp;
1039 #line 1062 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/chan.goc"
1040 if ( c == nil )
1041 runtime_panicstring ( "close of nil channel" ) ;
1042 #line 1065 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/chan.goc"
1043 if ( runtime_gcwaiting ( ) )
1044 runtime_gosched ( ) ;
1045 #line 1068 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/chan.goc"
1046 runtime_lock ( c ) ;
1047 if ( c->closed ) {
1048 runtime_unlock ( c ) ;
1049 runtime_panicstring ( "close of closed channel" ) ;
1051 #line 1074 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/chan.goc"
1052 if ( raceenabled ) {
1053 runtime_racewritepc ( c , pc , runtime_closechan ) ;
1054 runtime_racerelease ( c ) ;
1056 #line 1079 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/chan.goc"
1057 c->closed = true;
1058 #line 1082 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/chan.goc"
1059 for ( ;; ) {
1060 sg = dequeue ( &c->recvq ) ;
1061 if ( sg == nil )
1062 break;
1063 gp = sg->g;
1064 gp->param = nil;
1065 if ( sg->releasetime )
1066 sg->releasetime = runtime_cputicks ( ) ;
1067 runtime_ready ( gp ) ;
1069 #line 1094 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/chan.goc"
1070 for ( ;; ) {
1071 sg = dequeue ( &c->sendq ) ;
1072 if ( sg == nil )
1073 break;
1074 gp = sg->g;
1075 gp->param = nil;
1076 if ( sg->releasetime )
1077 sg->releasetime = runtime_cputicks ( ) ;
1078 runtime_ready ( gp ) ;
1080 #line 1105 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/chan.goc"
1081 runtime_unlock ( c ) ;
1083 #line 1108 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/chan.goc"
1084 void
1085 __go_builtin_close ( Hchan *c )
1087 runtime_closechan ( c ) ;
1089 intgo reflect_chanlen(Hchan* c) __asm__ (GOSYM_PREFIX "reflect.chanlen");
1090 intgo reflect_chanlen(Hchan* c)
1092 intgo len;
1093 #line 1114 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/chan.goc"
1095 if(c == nil)
1096 len = 0;
1097 else
1098 len = c->qcount;
1099 return len;
1102 #line 1121 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/chan.goc"
1103 intgo
1104 __go_chan_len ( Hchan *c )
1106 return reflect_chanlen ( c ) ;
1108 intgo reflect_chancap(Hchan* c) __asm__ (GOSYM_PREFIX "reflect.chancap");
1109 intgo reflect_chancap(Hchan* c)
1111 intgo cap;
1112 #line 1127 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/chan.goc"
1114 if(c == nil)
1115 cap = 0;
1116 else
1117 cap = c->dataqsiz;
1118 return cap;
1121 #line 1134 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/chan.goc"
1122 intgo
1123 __go_chan_cap ( Hchan *c )
1125 return reflect_chancap ( c ) ;
1127 #line 1140 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/chan.goc"
1128 static SudoG*
1129 dequeue ( WaitQ *q )
1131 SudoG *sgp;
1132 #line 1145 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/chan.goc"
1133 loop:
1134 sgp = q->first;
1135 if ( sgp == nil )
1136 return nil;
1137 q->first = sgp->link;
1138 #line 1152 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/chan.goc"
1139 if ( sgp->selectdone != nil ) {
1140 #line 1154 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/chan.goc"
1141 if ( *sgp->selectdone != 0 || !runtime_cas ( sgp->selectdone , 0 , 1 ) )
1142 goto loop;
1144 #line 1158 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/chan.goc"
1145 return sgp;
1147 #line 1161 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/chan.goc"
1148 static void
1149 dequeueg ( WaitQ *q )
1151 SudoG **l , *sgp , *prevsgp;
1152 G *g;
1153 #line 1167 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/chan.goc"
1154 g = runtime_g ( ) ;
1155 prevsgp = nil;
1156 for ( l=&q->first; ( sgp=*l ) != nil; l=&sgp->link , prevsgp=sgp ) {
1157 if ( sgp->g == g ) {
1158 *l = sgp->link;
1159 if ( q->last == sgp )
1160 q->last = prevsgp;
1161 break;
1165 #line 1179 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/chan.goc"
1166 static void
1167 enqueue ( WaitQ *q , SudoG *sgp )
1169 sgp->link = nil;
1170 if ( q->first == nil ) {
1171 q->first = sgp;
1172 q->last = sgp;
1173 return;
1175 q->last->link = sgp;
1176 q->last = sgp;
1178 #line 1192 "../../../trunk/libgo/runtime/../../../trunk/libgo/runtime/chan.goc"
1179 static void
1180 racesync ( Hchan *c , SudoG *sg )
1182 runtime_racerelease ( chanbuf ( c , 0 ) ) ;
1183 runtime_raceacquireg ( sg->g , chanbuf ( c , 0 ) ) ;
1184 runtime_racereleaseg ( sg->g , chanbuf ( c , 0 ) ) ;
1185 runtime_raceacquire ( chanbuf ( c , 0 ) ) ;