~ubuntu-branches/ubuntu/saucy/golang/saucy

« back to all changes in this revision

Viewing changes to src/pkg/runtime/chan.c

  • Committer: Package Import Robot
  • Author(s): Adam Conrad
  • Date: 2013-07-08 05:52:37 UTC
  • mfrom: (29.1.1 sid)
  • Revision ID: package-import@ubuntu.com-20130708055237-at01839e0hp8z3ni
Tags: 2:1.1-1ubuntu1
016-armhf-elf-header.patch: Use correct ELF header for armhf binaries.

Show diffs side-by-side

added added

removed removed

Lines of Context:
3
3
// license that can be found in the LICENSE file.
4
4
 
5
5
#include "runtime.h"
 
6
#include "arch_GOARCH.h"
6
7
#include "type.h"
 
8
#include "race.h"
 
9
#include "malloc.h"
7
10
 
8
11
#define MAXALIGN        7
9
12
#define NOSELGEN        1
20
23
        G*      g;              // g and selgen constitute
21
24
        uint32  selgen;         // a weak pointer to g
22
25
        SudoG*  link;
 
26
        int64   releasetime;
23
27
        byte*   elem;           // data element
24
28
};
25
29
 
29
33
        SudoG*  last;
30
34
};
31
35
 
 
36
// The garbage collector is assuming that Hchan can only contain pointers into the stack
 
37
// and cannot contain pointers into the heap.
32
38
struct  Hchan
33
39
{
34
 
        uint32  qcount;                 // total data in the q
35
 
        uint32  dataqsiz;               // size of the circular q
 
40
        uintgo  qcount;                 // total data in the q
 
41
        uintgo  dataqsiz;               // size of the circular q
36
42
        uint16  elemsize;
37
43
        bool    closed;
38
44
        uint8   elemalign;
39
45
        Alg*    elemalg;                // interface for element type
40
 
        uint32  sendx;                  // send index
41
 
        uint32  recvx;                  // receive index
 
46
        uintgo  sendx;                  // send index
 
47
        uintgo  recvx;                  // receive index
42
48
        WaitQ   recvq;                  // list of recv waiters
43
49
        WaitQ   sendq;                  // list of send waiters
44
50
        Lock;
45
51
};
46
52
 
 
53
uint32 runtime·Hchansize = sizeof(Hchan);
 
54
 
47
55
// Buffer follows Hchan immediately in memory.
48
56
// chanbuf(c, i) is pointer to the i'th slot in the buffer.
49
57
#define chanbuf(c, i) ((byte*)((c)+1)+(uintptr)(c)->elemsize*(i))
79
87
static  SudoG*  dequeue(WaitQ*);
80
88
static  void    enqueue(WaitQ*, SudoG*);
81
89
static  void    destroychan(Hchan*);
 
90
static  void    racesync(Hchan*, SudoG*);
82
91
 
83
92
Hchan*
84
93
runtime·makechan_c(ChanType *t, int64 hint)
85
94
{
86
95
        Hchan *c;
87
 
        int32 n;
 
96
        uintptr n;
88
97
        Type *elem;
89
 
        
 
98
 
90
99
        elem = t->elem;
91
100
 
92
 
        if(hint < 0 || (int32)hint != hint || (elem->size > 0 && hint > ((uintptr)-1) / elem->size))
 
101
        // compiler checks this but be safe.
 
102
        if(elem->size >= (1<<16))
 
103
                runtime·throw("makechan: invalid channel element type");
 
104
 
 
105
        if(hint < 0 || (intgo)hint != hint || (elem->size > 0 && hint > MaxMem / elem->size))
93
106
                runtime·panicstring("makechan: size out of range");
94
107
 
95
108
        // calculate rounded size of Hchan
103
116
        c->elemalg = elem->alg;
104
117
        c->elemalign = elem->align;
105
118
        c->dataqsiz = hint;
 
119
        runtime·settype(c, (uintptr)t | TypeInfo_Chan);
106
120
 
107
121
        if(debug)
108
 
                runtime·printf("makechan: chan=%p; elemsize=%D; elemalg=%p; elemalign=%d; dataqsiz=%d\n",
109
 
                        c, (int64)elem->size, elem->alg, elem->align, c->dataqsiz);
 
122
                runtime·printf("makechan: chan=%p; elemsize=%D; elemalg=%p; elemalign=%d; dataqsiz=%D\n",
 
123
                        c, (int64)elem->size, elem->alg, elem->align, (int64)c->dataqsiz);
110
124
 
111
125
        return c;
112
126
}
113
127
 
114
128
// For reflect
115
 
//      func makechan(typ *ChanType, size uint32) (chan)
 
129
//      func makechan(typ *ChanType, size uint64) (chan)
116
130
void
117
 
reflect·makechan(ChanType *t, uint32 size, Hchan *c)
 
131
reflect·makechan(ChanType *t, uint64 size, Hchan *c)
118
132
{
119
133
        c = runtime·makechan_c(t, size);
120
134
        FLUSH(&c);
143
157
 * the operation; we'll see that it's now closed.
144
158
 */
145
159
void
146
 
runtime·chansend(ChanType *t, Hchan *c, byte *ep, bool *pres)
 
160
runtime·chansend(ChanType *t, Hchan *c, byte *ep, bool *pres, void *pc)
147
161
{
148
162
        SudoG *sg;
149
163
        SudoG mysg;
150
164
        G* gp;
 
165
        int64 t0;
151
166
 
152
167
        if(c == nil) {
153
168
                USED(t);
155
170
                        *pres = false;
156
171
                        return;
157
172
                }
158
 
                g->status = Gwaiting;
159
 
                g->waitreason = "chan send (nil chan)";
160
 
                runtime·gosched();
 
173
                runtime·park(nil, nil, "chan send (nil chan)");
161
174
                return;  // not reached
162
175
        }
163
176
 
170
183
                runtime·prints("\n");
171
184
        }
172
185
 
 
186
        t0 = 0;
 
187
        mysg.releasetime = 0;
 
188
        if(runtime·blockprofilerate > 0) {
 
189
                t0 = runtime·cputicks();
 
190
                mysg.releasetime = -1;
 
191
        }
 
192
 
173
193
        runtime·lock(c);
 
194
        // TODO(dvyukov): add similar instrumentation to select.
 
195
        if(raceenabled)
 
196
                runtime·racereadpc(c, pc, runtime·chansend);
174
197
        if(c->closed)
175
198
                goto closed;
176
199
 
179
202
 
180
203
        sg = dequeue(&c->recvq);
181
204
        if(sg != nil) {
 
205
                if(raceenabled)
 
206
                        racesync(c, sg);
182
207
                runtime·unlock(c);
183
 
                
 
208
 
184
209
                gp = sg->g;
185
210
                gp->param = sg;
186
211
                if(sg->elem != nil)
187
212
                        c->elemalg->copy(c->elemsize, sg->elem, ep);
 
213
                if(sg->releasetime)
 
214
                        sg->releasetime = runtime·cputicks();
188
215
                runtime·ready(gp);
189
216
 
190
217
                if(pres != nil)
202
229
        mysg.g = g;
203
230
        mysg.selgen = NOSELGEN;
204
231
        g->param = nil;
205
 
        g->status = Gwaiting;
206
 
        g->waitreason = "chan send";
207
232
        enqueue(&c->sendq, &mysg);
208
 
        runtime·unlock(c);
209
 
        runtime·gosched();
 
233
        runtime·park(runtime·unlock, c, "chan send");
210
234
 
211
235
        if(g->param == nil) {
212
236
                runtime·lock(c);
215
239
                goto closed;
216
240
        }
217
241
 
 
242
        if(mysg.releasetime > 0)
 
243
                runtime·blockevent(mysg.releasetime - t0, 2);
 
244
 
218
245
        return;
219
246
 
220
247
asynch:
230
257
                mysg.g = g;
231
258
                mysg.elem = nil;
232
259
                mysg.selgen = NOSELGEN;
233
 
                g->status = Gwaiting;
234
 
                g->waitreason = "chan send";
235
260
                enqueue(&c->sendq, &mysg);
236
 
                runtime·unlock(c);
237
 
                runtime·gosched();
 
261
                runtime·park(runtime·unlock, c, "chan send");
238
262
 
239
263
                runtime·lock(c);
240
264
                goto asynch;
241
265
        }
 
266
 
 
267
        if(raceenabled)
 
268
                runtime·racerelease(chanbuf(c, c->sendx));
 
269
 
242
270
        c->elemalg->copy(c->elemsize, chanbuf(c, c->sendx), ep);
243
271
        if(++c->sendx == c->dataqsiz)
244
272
                c->sendx = 0;
248
276
        if(sg != nil) {
249
277
                gp = sg->g;
250
278
                runtime·unlock(c);
 
279
                if(sg->releasetime)
 
280
                        sg->releasetime = runtime·cputicks();
251
281
                runtime·ready(gp);
252
282
        } else
253
283
                runtime·unlock(c);
254
284
        if(pres != nil)
255
285
                *pres = true;
 
286
        if(mysg.releasetime > 0)
 
287
                runtime·blockevent(mysg.releasetime - t0, 2);
256
288
        return;
257
289
 
258
290
closed:
267
299
        SudoG *sg;
268
300
        SudoG mysg;
269
301
        G *gp;
 
302
        int64 t0;
270
303
 
271
304
        if(runtime·gcwaiting)
272
305
                runtime·gosched();
280
313
                        *selected = false;
281
314
                        return;
282
315
                }
283
 
                g->status = Gwaiting;
284
 
                g->waitreason = "chan receive (nil chan)";
285
 
                runtime·gosched();
 
316
                runtime·park(nil, nil, "chan receive (nil chan)");
286
317
                return;  // not reached
287
318
        }
288
319
 
 
320
        t0 = 0;
 
321
        mysg.releasetime = 0;
 
322
        if(runtime·blockprofilerate > 0) {
 
323
                t0 = runtime·cputicks();
 
324
                mysg.releasetime = -1;
 
325
        }
 
326
 
289
327
        runtime·lock(c);
290
328
        if(c->dataqsiz > 0)
291
329
                goto asynch;
295
333
 
296
334
        sg = dequeue(&c->sendq);
297
335
        if(sg != nil) {
 
336
                if(raceenabled)
 
337
                        racesync(c, sg);
298
338
                runtime·unlock(c);
299
339
 
300
340
                if(ep != nil)
301
341
                        c->elemalg->copy(c->elemsize, ep, sg->elem);
302
342
                gp = sg->g;
303
343
                gp->param = sg;
 
344
                if(sg->releasetime)
 
345
                        sg->releasetime = runtime·cputicks();
304
346
                runtime·ready(gp);
305
347
 
306
348
                if(selected != nil)
320
362
        mysg.g = g;
321
363
        mysg.selgen = NOSELGEN;
322
364
        g->param = nil;
323
 
        g->status = Gwaiting;
324
 
        g->waitreason = "chan receive";
325
365
        enqueue(&c->recvq, &mysg);
326
 
        runtime·unlock(c);
327
 
        runtime·gosched();
 
366
        runtime·park(runtime·unlock, c, "chan receive");
328
367
 
329
368
        if(g->param == nil) {
330
369
                runtime·lock(c);
335
374
 
336
375
        if(received != nil)
337
376
                *received = true;
 
377
        if(mysg.releasetime > 0)
 
378
                runtime·blockevent(mysg.releasetime - t0, 2);
338
379
        return;
339
380
 
340
381
asynch:
352
393
                mysg.g = g;
353
394
                mysg.elem = nil;
354
395
                mysg.selgen = NOSELGEN;
355
 
                g->status = Gwaiting;
356
 
                g->waitreason = "chan receive";
357
396
                enqueue(&c->recvq, &mysg);
358
 
                runtime·unlock(c);
359
 
                runtime·gosched();
 
397
                runtime·park(runtime·unlock, c, "chan receive");
360
398
 
361
399
                runtime·lock(c);
362
400
                goto asynch;
363
401
        }
 
402
 
 
403
        if(raceenabled)
 
404
                runtime·raceacquire(chanbuf(c, c->recvx));
 
405
 
364
406
        if(ep != nil)
365
407
                c->elemalg->copy(c->elemsize, ep, chanbuf(c, c->recvx));
366
408
        c->elemalg->copy(c->elemsize, chanbuf(c, c->recvx), nil);
372
414
        if(sg != nil) {
373
415
                gp = sg->g;
374
416
                runtime·unlock(c);
 
417
                if(sg->releasetime)
 
418
                        sg->releasetime = runtime·cputicks();
375
419
                runtime·ready(gp);
376
420
        } else
377
421
                runtime·unlock(c);
380
424
                *selected = true;
381
425
        if(received != nil)
382
426
                *received = true;
 
427
        if(mysg.releasetime > 0)
 
428
                runtime·blockevent(mysg.releasetime - t0, 2);
383
429
        return;
384
430
 
385
431
closed:
389
435
                *selected = true;
390
436
        if(received != nil)
391
437
                *received = false;
 
438
        if(raceenabled)
 
439
                runtime·raceacquire(c);
392
440
        runtime·unlock(c);
 
441
        if(mysg.releasetime > 0)
 
442
                runtime·blockevent(mysg.releasetime - t0, 2);
393
443
}
394
444
 
395
445
// chansend1(hchan *chan any, elem any);
397
447
void
398
448
runtime·chansend1(ChanType *t, Hchan* c, ...)
399
449
{
400
 
        runtime·chansend(t, c, (byte*)(&c+1), nil);
 
450
        runtime·chansend(t, c, (byte*)(&c+1), nil, runtime·getcallerpc(&t));
401
451
}
402
452
 
403
453
// chanrecv1(hchan *chan any) (elem any);
446
496
        byte *ae, *ap;
447
497
 
448
498
        ae = (byte*)(&c + 1);
449
 
        ap = ae + runtime·rnd(t->elem->size, Structrnd);
450
 
        runtime·chansend(t, c, ae, ap);
 
499
        ap = ae + ROUND(t->elem->size, Structrnd);
 
500
        runtime·chansend(t, c, ae, ap, runtime·getcallerpc(&t));
451
501
}
452
502
 
453
503
// func selectnbrecv(elem *any, c chan any) bool
474
524
runtime·selectnbrecv(ChanType *t, byte *v, Hchan *c, bool selected)
475
525
{
476
526
        runtime·chanrecv(t, c, v, &selected, nil);
477
 
}       
 
527
}
478
528
 
479
529
// func selectnbrecv2(elem *any, ok *bool, c chan any) bool
480
530
//
500
550
runtime·selectnbrecv2(ChanType *t, byte *v, bool *received, Hchan *c, bool selected)
501
551
{
502
552
        runtime·chanrecv(t, c, v, &selected, received);
503
 
}       
 
553
}
504
554
 
505
555
// For reflect:
506
556
//      func chansend(c chan, val iword, nb bool) (selected bool)
509
559
//
510
560
// The "uintptr selected" is really "bool selected" but saying
511
561
// uintptr gets us the right alignment for the output parameter block.
 
562
#pragma textflag 7
512
563
void
513
564
reflect·chansend(ChanType *t, Hchan *c, uintptr val, bool nb, uintptr selected)
514
565
{
515
566
        bool *sp;
516
567
        byte *vp;
517
 
        
 
568
 
518
569
        if(nb) {
519
570
                selected = false;
520
571
                sp = (bool*)&selected;
527
578
                vp = (byte*)&val;
528
579
        else
529
580
                vp = (byte*)val;
530
 
        runtime·chansend(t, c, vp, sp);
 
581
        runtime·chansend(t, c, vp, sp, runtime·getcallerpc(&t));
531
582
}
532
583
 
533
584
// For reflect:
571
622
        int32 o;
572
623
        Select **selp;
573
624
 
574
 
        o = runtime·rnd(sizeof(size), Structrnd);
 
625
        o = ROUND(sizeof(size), Structrnd);
575
626
        selp = (Select**)((byte*)&size + o);
576
627
        newselect(size, selp);
577
628
}
619
670
        // nil cases do not compete
620
671
        if(c == nil)
621
672
                return;
622
 
        
 
673
 
623
674
        selectsend(sel, c, runtime·getcallerpc(&sel), elem, (byte*)&selected - (byte*)&sel);
624
675
}
625
676
 
628
679
{
629
680
        int32 i;
630
681
        Scase *cas;
631
 
        
 
682
 
632
683
        i = sel->ncase;
633
684
        if(i >= sel->tcase)
634
685
                runtime·throw("selectsend: too many cases");
758
809
static void
759
810
selunlock(Select *sel)
760
811
{
761
 
        uint32 i;
762
 
        Hchan *c, *c0;
 
812
        int32 i, n, r;
 
813
        Hchan *c;
763
814
 
764
 
        c = nil;
765
 
        for(i=sel->ncase; i-->0;) {
766
 
                c0 = sel->lockorder[i];
767
 
                if(c0 && c0 != c) {
768
 
                        c = c0;
769
 
                        runtime·unlock(c);
770
 
                }
 
815
        // We must be very careful here to not touch sel after we have unlocked
 
816
        // the last lock, because sel can be freed right after the last unlock.
 
817
        // Consider the following situation.
 
818
        // First M calls runtime·park() in runtime·selectgo() passing the sel.
 
819
        // Once runtime·park() has unlocked the last lock, another M makes
 
820
        // the G that calls select runnable again and schedules it for execution.
 
821
        // When the G runs on another M, it locks all the locks and frees sel.
 
822
        // Now if the first M touches sel, it will access freed memory.
 
823
        n = (int32)sel->ncase;
 
824
        r = 0;
 
825
        // skip the default case
 
826
        if(n>0 && sel->lockorder[0] == nil)
 
827
                r = 1;
 
828
        for(i = n-1; i >= r; i--) {
 
829
                c = sel->lockorder[i];
 
830
                if(i>0 && sel->lockorder[i-1] == c)
 
831
                        continue;  // will unlock it on the next iteration
 
832
                runtime·unlock(c);
771
833
        }
772
834
}
773
835
 
774
836
void
775
837
runtime·block(void)
776
838
{
777
 
        g->status = Gwaiting;   // forever
778
 
        g->waitreason = "select (no cases)";
779
 
        runtime·gosched();
 
839
        runtime·park(nil, nil, "select (no cases)");    // forever
780
840
}
781
841
 
782
842
static void* selectgo(Select**);
796
856
selectgo(Select **selp)
797
857
{
798
858
        Select *sel;
799
 
        uint32 o, i, j;
 
859
        uint32 o, i, j, k;
800
860
        Scase *cas, *dfl;
801
861
        Hchan *c;
802
862
        SudoG *sg;
830
890
        }
831
891
 
832
892
        // sort the cases by Hchan address to get the locking order.
 
893
        // simple heap sort, to guarantee n log n time and constant stack footprint.
833
894
        for(i=0; i<sel->ncase; i++) {
834
 
                c = sel->scase[i].chan;
835
 
                for(j=i; j>0 && sel->lockorder[j-1] >= c; j--)
836
 
                        sel->lockorder[j] = sel->lockorder[j-1];
837
 
                sel->lockorder[j] = c;
838
 
        }
 
895
                j = i;
 
896
                c = sel->scase[j].chan;
 
897
                while(j > 0 && sel->lockorder[k=(j-1)/2] < c) {
 
898
                        sel->lockorder[j] = sel->lockorder[k];
 
899
                        j = k;
 
900
                }
 
901
                sel->lockorder[j] = c;
 
902
        }
 
903
        for(i=sel->ncase; i-->0; ) {
 
904
                c = sel->lockorder[i];
 
905
                sel->lockorder[i] = sel->lockorder[0];
 
906
                j = 0;
 
907
                for(;;) {
 
908
                        k = j*2+1;
 
909
                        if(k >= i)
 
910
                                break;
 
911
                        if(k+1 < i && sel->lockorder[k] < sel->lockorder[k+1])
 
912
                                k++;
 
913
                        if(c < sel->lockorder[k]) {
 
914
                                sel->lockorder[j] = sel->lockorder[k];
 
915
                                j = k;
 
916
                                continue;
 
917
                        }
 
918
                        break;
 
919
                }
 
920
                sel->lockorder[j] = c;
 
921
        }
 
922
        /*
 
923
        for(i=0; i+1<sel->ncase; i++)
 
924
                if(sel->lockorder[i] > sel->lockorder[i+1]) {
 
925
                        runtime·printf("i=%d %p %p\n", i, sel->lockorder[i], sel->lockorder[i+1]);
 
926
                        runtime·throw("select: broken sort");
 
927
                }
 
928
        */
839
929
        sellock(sel);
840
930
 
841
931
loop:
899
989
                case CaseRecv:
900
990
                        enqueue(&c->recvq, sg);
901
991
                        break;
902
 
                
 
992
 
903
993
                case CaseSend:
904
994
                        enqueue(&c->sendq, sg);
905
995
                        break;
907
997
        }
908
998
 
909
999
        g->param = nil;
910
 
        g->status = Gwaiting;
911
 
        g->waitreason = "select";
912
 
        selunlock(sel);
913
 
        runtime·gosched();
 
1000
        runtime·park((void(*)(Lock*))selunlock, (Lock*)sel, "select");
914
1001
 
915
1002
        sellock(sel);
916
1003
        sg = g->param;
935
1022
        c = cas->chan;
936
1023
 
937
1024
        if(c->dataqsiz > 0)
938
 
                runtime·throw("selectgo: shouldnt happen");
 
1025
                runtime·throw("selectgo: shouldn't happen");
939
1026
 
940
1027
        if(debug)
941
1028
                runtime·printf("wait-return: sel=%p c=%p cas=%p kind=%d\n",
951
1038
 
952
1039
asyncrecv:
953
1040
        // can receive from buffer
 
1041
        if(raceenabled)
 
1042
                runtime·raceacquire(chanbuf(c, c->recvx));
954
1043
        if(cas->receivedp != nil)
955
1044
                *cas->receivedp = true;
956
1045
        if(cas->sg.elem != nil)
971
1060
 
972
1061
asyncsend:
973
1062
        // can send to buffer
 
1063
        if(raceenabled)
 
1064
                runtime·racerelease(chanbuf(c, c->sendx));
974
1065
        c->elemalg->copy(c->elemsize, chanbuf(c, c->sendx), cas->sg.elem);
975
1066
        if(++c->sendx == c->dataqsiz)
976
1067
                c->sendx = 0;
987
1078
 
988
1079
syncrecv:
989
1080
        // can receive from sleeping sender (sg)
 
1081
        if(raceenabled)
 
1082
                racesync(c, sg);
990
1083
        selunlock(sel);
991
1084
        if(debug)
992
1085
                runtime·printf("syncrecv: sel=%p c=%p o=%d\n", sel, c, o);
1006
1099
                *cas->receivedp = false;
1007
1100
        if(cas->sg.elem != nil)
1008
1101
                c->elemalg->copy(c->elemsize, cas->sg.elem, nil);
 
1102
        if(raceenabled)
 
1103
                runtime·raceacquire(c);
1009
1104
        goto retc;
1010
1105
 
1011
1106
syncsend:
1012
1107
        // can send to sleeping receiver (sg)
 
1108
        if(raceenabled)
 
1109
                racesync(c, sg);
1013
1110
        selunlock(sel);
1014
1111
        if(debug)
1015
1112
                runtime·printf("syncsend: sel=%p c=%p o=%d\n", sel, c, o);
1020
1117
        runtime·ready(gp);
1021
1118
 
1022
1119
retc:
1023
 
        // return to pc corresponding to chosen case
 
1120
        // return pc corresponding to chosen case.
 
1121
        // Set boolean passed during select creation
 
1122
        // (at offset selp + cas->so) to true.
 
1123
        // If cas->so == 0, this is a reflect-driven select and we
 
1124
        // don't need to update the boolean.
1024
1125
        pc = cas->pc;
1025
 
        as = (byte*)selp + cas->so;
 
1126
        if(cas->so > 0) {
 
1127
                as = (byte*)selp + cas->so;
 
1128
                *as = true;
 
1129
        }
1026
1130
        runtime·free(sel);
1027
 
        *as = true;
1028
1131
        return pc;
1029
1132
 
1030
1133
sclose:
1034
1137
        return nil;  // not reached
1035
1138
}
1036
1139
 
 
1140
// This struct must match ../reflect/value.go:/runtimeSelect.
 
1141
typedef struct runtimeSelect runtimeSelect;
 
1142
struct runtimeSelect
 
1143
{
 
1144
        uintptr dir;
 
1145
        ChanType *typ;
 
1146
        Hchan *ch;
 
1147
        uintptr val;
 
1148
};
 
1149
 
 
1150
// This enum must match ../reflect/value.go:/SelectDir.
 
1151
enum SelectDir {
 
1152
        SelectSend = 1,
 
1153
        SelectRecv,
 
1154
        SelectDefault,
 
1155
};
 
1156
 
 
1157
// func rselect(cases []runtimeSelect) (chosen int, word uintptr, recvOK bool)
 
1158
void
 
1159
reflect·rselect(Slice cases, intgo chosen, uintptr word, bool recvOK)
 
1160
{
 
1161
        int32 i;
 
1162
        Select *sel;
 
1163
        runtimeSelect* rcase, *rc;
 
1164
        void *elem;
 
1165
        void *recvptr;
 
1166
        uintptr maxsize;
 
1167
 
 
1168
        chosen = -1;
 
1169
        word = 0;
 
1170
        recvOK = false;
 
1171
 
 
1172
        maxsize = 0;
 
1173
        rcase = (runtimeSelect*)cases.array;
 
1174
        for(i=0; i<cases.len; i++) {
 
1175
                rc = &rcase[i];
 
1176
                if(rc->dir == SelectRecv && rc->ch != nil && maxsize < rc->typ->elem->size)
 
1177
                        maxsize = rc->typ->elem->size;
 
1178
        }
 
1179
 
 
1180
        recvptr = nil;
 
1181
        if(maxsize > sizeof(void*))
 
1182
                recvptr = runtime·mal(maxsize);
 
1183
 
 
1184
        newselect(cases.len, &sel);
 
1185
        for(i=0; i<cases.len; i++) {
 
1186
                rc = &rcase[i];
 
1187
                switch(rc->dir) {
 
1188
                case SelectDefault:
 
1189
                        selectdefault(sel, (void*)i, 0);
 
1190
                        break;
 
1191
                case SelectSend:
 
1192
                        if(rc->ch == nil)
 
1193
                                break;
 
1194
                        if(rc->typ->elem->size > sizeof(void*))
 
1195
                                elem = (void*)rc->val;
 
1196
                        else
 
1197
                                elem = (void*)&rc->val;
 
1198
                        selectsend(sel, rc->ch, (void*)i, elem, 0);
 
1199
                        break;
 
1200
                case SelectRecv:
 
1201
                        if(rc->ch == nil)
 
1202
                                break;
 
1203
                        if(rc->typ->elem->size > sizeof(void*))
 
1204
                                elem = recvptr;
 
1205
                        else
 
1206
                                elem = &word;
 
1207
                        selectrecv(sel, rc->ch, (void*)i, elem, &recvOK, 0);
 
1208
                        break;
 
1209
                }
 
1210
        }
 
1211
 
 
1212
        chosen = (intgo)(uintptr)selectgo(&sel);
 
1213
        if(rcase[chosen].dir == SelectRecv && rcase[chosen].typ->elem->size > sizeof(void*))
 
1214
                word = (uintptr)recvptr;
 
1215
 
 
1216
        FLUSH(&chosen);
 
1217
        FLUSH(&word);
 
1218
        FLUSH(&recvOK);
 
1219
}
 
1220
 
1037
1221
// closechan(sel *byte);
 
1222
#pragma textflag 7
1038
1223
void
1039
1224
runtime·closechan(Hchan *c)
1040
1225
{
1053
1238
                runtime·panicstring("close of closed channel");
1054
1239
        }
1055
1240
 
 
1241
        if(raceenabled) {
 
1242
                runtime·racewritepc(c, runtime·getcallerpc(&c), runtime·closechan);
 
1243
                runtime·racerelease(c);
 
1244
        }
 
1245
 
1056
1246
        c->closed = true;
1057
1247
 
1058
1248
        // release all readers
1087
1277
}
1088
1278
 
1089
1279
// For reflect
1090
 
//      func chanlen(c chan) (len int32)
 
1280
//      func chanlen(c chan) (len int)
1091
1281
void
1092
 
reflect·chanlen(Hchan *c, int32 len)
 
1282
reflect·chanlen(Hchan *c, intgo len)
1093
1283
{
1094
1284
        if(c == nil)
1095
1285
                len = 0;
1099
1289
}
1100
1290
 
1101
1291
// For reflect
1102
 
//      func chancap(c chan) (cap int32)
 
1292
//      func chancap(c chan) int
1103
1293
void
1104
 
reflect·chancap(Hchan *c, int32 cap)
 
1294
reflect·chancap(Hchan *c, intgo cap)
1105
1295
{
1106
1296
        if(c == nil)
1107
1297
                cap = 0;
1160
1350
        q->last->link = sgp;
1161
1351
        q->last = sgp;
1162
1352
}
 
1353
 
 
1354
static void
 
1355
racesync(Hchan *c, SudoG *sg)
 
1356
{
 
1357
        runtime·racerelease(chanbuf(c, 0));
 
1358
        runtime·raceacquireg(sg->g, chanbuf(c, 0));
 
1359
        runtime·racereleaseg(sg->g, chanbuf(c, 0));
 
1360
        runtime·raceacquire(chanbuf(c, 0));
 
1361
}