36
// The garbage collector is assuming that Hchan can only contain pointers into the stack
37
// and cannot contain pointers into the heap.
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
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
53
uint32 runtime·Hchansize = sizeof(Hchan);
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*);
84
93
runtime·makechan_c(ChanType *t, int64 hint)
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");
105
if(hint < 0 || (intgo)hint != hint || (elem->size > 0 && hint > MaxMem / elem->size))
93
106
runtime·panicstring("makechan: size out of range");
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);
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);
115
// func makechan(typ *ChanType, size uint32) (chan)
129
// func makechan(typ *ChanType, size uint64) (chan)
117
reflect·makechan(ChanType *t, uint32 size, Hchan *c)
131
reflect·makechan(ChanType *t, uint64 size, Hchan *c)
119
133
c = runtime·makechan_c(t, size);
143
157
* the operation; we'll see that it's now closed.
146
runtime·chansend(ChanType *t, Hchan *c, byte *ep, bool *pres)
160
runtime·chansend(ChanType *t, Hchan *c, byte *ep, bool *pres, void *pc)
232
259
mysg.selgen = NOSELGEN;
233
g->status = Gwaiting;
234
g->waitreason = "chan send";
235
260
enqueue(&c->sendq, &mysg);
261
runtime·park(runtime·unlock, c, "chan send");
268
runtime·racerelease(chanbuf(c, c->sendx));
242
270
c->elemalg->copy(c->elemsize, chanbuf(c, c->sendx), ep);
243
271
if(++c->sendx == c->dataqsiz)
321
363
mysg.selgen = NOSELGEN;
323
g->status = Gwaiting;
324
g->waitreason = "chan receive";
325
365
enqueue(&c->recvq, &mysg);
366
runtime·park(runtime·unlock, c, "chan receive");
329
368
if(g->param == nil) {
354
395
mysg.selgen = NOSELGEN;
355
g->status = Gwaiting;
356
g->waitreason = "chan receive";
357
396
enqueue(&c->recvq, &mysg);
397
runtime·park(runtime·unlock, c, "chan receive");
404
runtime·raceacquire(chanbuf(c, c->recvx));
365
407
c->elemalg->copy(c->elemsize, ep, chanbuf(c, c->recvx));
366
408
c->elemalg->copy(c->elemsize, chanbuf(c, c->recvx), nil);
398
448
runtime·chansend1(ChanType *t, Hchan* c, ...)
400
runtime·chansend(t, c, (byte*)(&c+1), nil);
450
runtime·chansend(t, c, (byte*)(&c+1), nil, runtime·getcallerpc(&t));
403
453
// chanrecv1(hchan *chan any) (elem any);
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));
453
503
// func selectnbrecv(elem *any, c chan any) bool
474
524
runtime·selectnbrecv(ChanType *t, byte *v, Hchan *c, bool selected)
476
526
runtime·chanrecv(t, c, v, &selected, nil);
479
529
// func selectnbrecv2(elem *any, ok *bool, c chan any) bool
500
550
runtime·selectnbrecv2(ChanType *t, byte *v, bool *received, Hchan *c, bool selected)
502
552
runtime·chanrecv(t, c, v, &selected, received);
506
556
// func chansend(c chan, val iword, nb bool) (selected bool)
510
560
// The "uintptr selected" is really "bool selected" but saying
511
561
// uintptr gets us the right alignment for the output parameter block.
513
564
reflect·chansend(ChanType *t, Hchan *c, uintptr val, bool nb, uintptr selected)
519
570
selected = false;
520
571
sp = (bool*)&selected;
527
578
vp = (byte*)&val;
530
runtime·chansend(t, c, vp, sp);
581
runtime·chansend(t, c, vp, sp, runtime·getcallerpc(&t));
759
810
selunlock(Select *sel)
765
for(i=sel->ncase; i-->0;) {
766
c0 = sel->lockorder[i];
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;
825
// skip the default case
826
if(n>0 && sel->lockorder[0] == nil)
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
775
837
runtime·block(void)
777
g->status = Gwaiting; // forever
778
g->waitreason = "select (no cases)";
839
runtime·park(nil, nil, "select (no cases)"); // forever
782
842
static void* selectgo(Select**);
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;
896
c = sel->scase[j].chan;
897
while(j > 0 && sel->lockorder[k=(j-1)/2] < c) {
898
sel->lockorder[j] = sel->lockorder[k];
901
sel->lockorder[j] = c;
903
for(i=sel->ncase; i-->0; ) {
904
c = sel->lockorder[i];
905
sel->lockorder[i] = sel->lockorder[0];
911
if(k+1 < i && sel->lockorder[k] < sel->lockorder[k+1])
913
if(c < sel->lockorder[k]) {
914
sel->lockorder[j] = sel->lockorder[k];
920
sel->lockorder[j] = c;
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");
973
1062
// can send to buffer
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)
1006
1099
*cas->receivedp = false;
1007
1100
if(cas->sg.elem != nil)
1008
1101
c->elemalg->copy(c->elemsize, cas->sg.elem, nil);
1103
runtime·raceacquire(c);
1012
1107
// can send to sleeping receiver (sg)
1013
1110
selunlock(sel);
1015
1112
runtime·printf("syncsend: sel=%p c=%p o=%d\n", sel, c, o);
1020
1117
runtime·ready(gp);
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.
1025
as = (byte*)selp + cas->so;
1127
as = (byte*)selp + cas->so;
1026
1130
runtime·free(sel);
1034
1137
return nil; // not reached
1140
// This struct must match ../reflect/value.go:/runtimeSelect.
1141
typedef struct runtimeSelect runtimeSelect;
1142
struct runtimeSelect
1150
// This enum must match ../reflect/value.go:/SelectDir.
1157
// func rselect(cases []runtimeSelect) (chosen int, word uintptr, recvOK bool)
1159
reflect·rselect(Slice cases, intgo chosen, uintptr word, bool recvOK)
1163
runtimeSelect* rcase, *rc;
1173
rcase = (runtimeSelect*)cases.array;
1174
for(i=0; i<cases.len; i++) {
1176
if(rc->dir == SelectRecv && rc->ch != nil && maxsize < rc->typ->elem->size)
1177
maxsize = rc->typ->elem->size;
1181
if(maxsize > sizeof(void*))
1182
recvptr = runtime·mal(maxsize);
1184
newselect(cases.len, &sel);
1185
for(i=0; i<cases.len; i++) {
1189
selectdefault(sel, (void*)i, 0);
1194
if(rc->typ->elem->size > sizeof(void*))
1195
elem = (void*)rc->val;
1197
elem = (void*)&rc->val;
1198
selectsend(sel, rc->ch, (void*)i, elem, 0);
1203
if(rc->typ->elem->size > sizeof(void*))
1207
selectrecv(sel, rc->ch, (void*)i, elem, &recvOK, 0);
1212
chosen = (intgo)(uintptr)selectgo(&sel);
1213
if(rcase[chosen].dir == SelectRecv && rcase[chosen].typ->elem->size > sizeof(void*))
1214
word = (uintptr)recvptr;
1037
1221
// closechan(sel *byte);
1039
1224
runtime·closechan(Hchan *c)
1090
// func chanlen(c chan) (len int32)
1280
// func chanlen(c chan) (len int)
1092
reflect·chanlen(Hchan *c, int32 len)
1282
reflect·chanlen(Hchan *c, intgo len)
1102
// func chancap(c chan) (cap int32)
1292
// func chancap(c chan) int
1104
reflect·chancap(Hchan *c, int32 cap)
1294
reflect·chancap(Hchan *c, intgo cap)
1160
1350
q->last->link = sgp;
1355
racesync(Hchan *c, SudoG *sg)
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));