mirror of
https://github.com/golang/go
synced 2024-11-22 21:50:03 -07:00
select
R=r APPROVED=r DELTA=147 (94 added, 14 deleted, 39 changed) OCL=13477 CL=13477
This commit is contained in:
parent
756c63cd02
commit
e963cba8a1
@ -1069,7 +1069,7 @@ walkselect(Node *sel)
|
|||||||
walktype(sel->ninit, Etop);
|
walktype(sel->ninit, Etop);
|
||||||
walktype(sel->nbody, Etop);
|
walktype(sel->nbody, Etop);
|
||||||
|
|
||||||
dump("sel", sel);
|
//dump("sel", sel);
|
||||||
|
|
||||||
lineno = lno;
|
lineno = lno;
|
||||||
}
|
}
|
||||||
|
@ -17,7 +17,8 @@ struct SudoG
|
|||||||
{
|
{
|
||||||
G* g; // g and selgen constitute
|
G* g; // g and selgen constitute
|
||||||
byte elem[8]; // synch data element
|
byte elem[8]; // synch data element
|
||||||
int64 selgen; // a weak pointer to g
|
int16 offset; // offset of case number
|
||||||
|
int32 selgen; // a weak pointer to g
|
||||||
SudoG* link;
|
SudoG* link;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -162,6 +163,7 @@ sys·chansend1(Hchan* c, ...)
|
|||||||
c->elemalg->copy(c->elemsize, sgr->elem, ae);
|
c->elemalg->copy(c->elemsize, sgr->elem, ae);
|
||||||
|
|
||||||
gr = sgr->g;
|
gr = sgr->g;
|
||||||
|
gr->param = sgr;
|
||||||
gr->status = Grunnable;
|
gr->status = Grunnable;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -217,6 +219,7 @@ sys·chansend2(Hchan* c, ...)
|
|||||||
gr = sgr->g;
|
gr = sgr->g;
|
||||||
c->elemalg->copy(c->elemsize, sgr->elem, ae);
|
c->elemalg->copy(c->elemsize, sgr->elem, ae);
|
||||||
|
|
||||||
|
gr->param = sgr;
|
||||||
gr->status = Grunnable;
|
gr->status = Grunnable;
|
||||||
*ap = true;
|
*ap = true;
|
||||||
return;
|
return;
|
||||||
@ -263,6 +266,7 @@ sys·chanrecv1(Hchan* c, ...)
|
|||||||
c->elemalg->copy(c->elemsize, ae, sgs->elem);
|
c->elemalg->copy(c->elemsize, ae, sgs->elem);
|
||||||
|
|
||||||
gs = sgs->g;
|
gs = sgs->g;
|
||||||
|
gs->param = sgs;
|
||||||
gs->status = Grunnable;
|
gs->status = Grunnable;
|
||||||
|
|
||||||
freesg(c, sgs);
|
freesg(c, sgs);
|
||||||
@ -319,6 +323,7 @@ sys·chanrecv2(Hchan* c, ...)
|
|||||||
c->elemalg->copy(c->elemsize, ae, sgs->elem);
|
c->elemalg->copy(c->elemsize, ae, sgs->elem);
|
||||||
|
|
||||||
gs = sgs->g;
|
gs = sgs->g;
|
||||||
|
gs->param = sgs;
|
||||||
gs->status = Grunnable;
|
gs->status = Grunnable;
|
||||||
|
|
||||||
freesg(c, sgs);
|
freesg(c, sgs);
|
||||||
@ -374,7 +379,7 @@ sys·selectsend(Select *sel, Hchan *c, ...)
|
|||||||
Scase *cas;
|
Scase *cas;
|
||||||
byte *as, *ae;
|
byte *as, *ae;
|
||||||
|
|
||||||
// return val, selected, is preset to false
|
// nil cases do not compete
|
||||||
if(c == nil)
|
if(c == nil)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -421,7 +426,7 @@ sys·selectrecv(Select *sel, Hchan *c, ...)
|
|||||||
Scase *cas;
|
Scase *cas;
|
||||||
byte *as;
|
byte *as;
|
||||||
|
|
||||||
// return val, selected, is preset to false
|
// nil cases do not compete
|
||||||
if(c == nil)
|
if(c == nil)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -465,16 +470,21 @@ sys·selectgo(Select *sel)
|
|||||||
uint32 p, o, i;
|
uint32 p, o, i;
|
||||||
Scase *cas;
|
Scase *cas;
|
||||||
Hchan *c;
|
Hchan *c;
|
||||||
|
SudoG *sg;
|
||||||
|
G *gp;
|
||||||
|
|
||||||
byte *ae, *as;
|
byte *ae, *as;
|
||||||
SudoG *sgr;
|
|
||||||
G *gr;
|
|
||||||
|
|
||||||
SudoG *sgs;
|
if(0) {
|
||||||
G *gs;
|
prints("selectgo: sel=");
|
||||||
|
sys·printpointer(sel);
|
||||||
|
prints("\n");
|
||||||
|
}
|
||||||
|
|
||||||
if(sel->ncase < 1) {
|
if(sel->ncase < 2) {
|
||||||
throw("selectgo: no cases");
|
if(sel->ncase < 1)
|
||||||
|
throw("selectgo: no cases");
|
||||||
|
// make special case of one.
|
||||||
}
|
}
|
||||||
|
|
||||||
// select a (relative) prime
|
// select a (relative) prime
|
||||||
@ -486,45 +496,33 @@ sys·selectgo(Select *sel)
|
|||||||
throw("selectgo: failed to select prime");
|
throw("selectgo: failed to select prime");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// select an initial offset
|
||||||
o = fastrand2();
|
o = fastrand2();
|
||||||
|
|
||||||
p %= sel->ncase;
|
p %= sel->ncase;
|
||||||
o %= sel->ncase;
|
o %= sel->ncase;
|
||||||
|
|
||||||
// pass 1 - look for something that can go
|
// pass 1 - look for something already waiting
|
||||||
for(i=0; i<sel->ncase; i++) {
|
for(i=0; i<sel->ncase; i++) {
|
||||||
cas = &sel->scase[o];
|
cas = &sel->scase[o];
|
||||||
c = cas->chan;
|
c = cas->chan;
|
||||||
if(cas->send) {
|
|
||||||
if(c->dataqsiz > 0) {
|
if(c->dataqsiz > 0) {
|
||||||
|
if(cas->send)
|
||||||
throw("selectgo: send asynch");
|
throw("selectgo: send asynch");
|
||||||
}
|
else
|
||||||
sgr = dequeue(&c->recvq, c);
|
|
||||||
if(sgr == nil)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
c->elemalg->copy(c->elemsize, sgr->elem, cas->u.elem);
|
|
||||||
gr = sgr->g;
|
|
||||||
gr->status = Grunnable;
|
|
||||||
|
|
||||||
goto retc;
|
|
||||||
} else {
|
|
||||||
if(c->dataqsiz > 0) {
|
|
||||||
throw("selectgo: recv asynch");
|
throw("selectgo: recv asynch");
|
||||||
}
|
}
|
||||||
sgs = dequeue(&c->sendq, c);
|
|
||||||
if(sgs == nil)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if(cas->u.elemp != nil)
|
if(cas->send) {
|
||||||
c->elemalg->copy(c->elemsize, cas->u.elemp, sgs->elem);
|
sg = dequeue(&c->recvq, c);
|
||||||
|
if(sg != nil)
|
||||||
gs = sgs->g;
|
goto gotr;
|
||||||
gs->status = Grunnable;
|
} else {
|
||||||
|
sg = dequeue(&c->sendq, c);
|
||||||
freesg(c, sgs);
|
if(sg != nil)
|
||||||
|
goto gots;
|
||||||
goto retc;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
o += p;
|
o += p;
|
||||||
@ -532,15 +530,96 @@ sys·selectgo(Select *sel)
|
|||||||
o -= sel->ncase;
|
o -= sel->ncase;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(debug) {
|
// pass 2 - enqueue on all chans
|
||||||
prints("selectgo s=");
|
for(i=0; i<sel->ncase; i++) {
|
||||||
|
cas = &sel->scase[o];
|
||||||
|
c = cas->chan;
|
||||||
|
if(cas->send) {
|
||||||
|
sg = dequeue(&c->recvq, c);
|
||||||
|
if(sg != nil)
|
||||||
|
goto gotr; // probably an error
|
||||||
|
sg = allocsg(c);
|
||||||
|
sg->offset = o;
|
||||||
|
c->elemalg->copy(c->elemsize, sg->elem, cas->u.elem);
|
||||||
|
enqueue(&c->sendq, sg);
|
||||||
|
} else {
|
||||||
|
sg = dequeue(&c->sendq, c);
|
||||||
|
if(sg != nil)
|
||||||
|
goto gots; // probably an error
|
||||||
|
|
||||||
|
sg = allocsg(c);
|
||||||
|
sg->offset = o;
|
||||||
|
enqueue(&c->recvq, sg);
|
||||||
|
}
|
||||||
|
|
||||||
|
o += p;
|
||||||
|
if(o >= sel->ncase)
|
||||||
|
o -= sel->ncase;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(0) {
|
||||||
|
prints("wait: sel=");
|
||||||
|
sys·printpointer(sel);
|
||||||
|
prints("\n");
|
||||||
|
}
|
||||||
|
g->status = Gwaiting;
|
||||||
|
sys·gosched();
|
||||||
|
|
||||||
|
if(0) {
|
||||||
|
prints("wait-return: sel=");
|
||||||
sys·printpointer(sel);
|
sys·printpointer(sel);
|
||||||
prints(" p=");
|
|
||||||
sys·printpointer((void*)p);
|
|
||||||
prints("\n");
|
prints("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
throw("selectgo");
|
sg = g->param;
|
||||||
|
o = sg->offset;
|
||||||
|
cas = &sel->scase[o];
|
||||||
|
c = cas->chan;
|
||||||
|
|
||||||
|
if(0) {
|
||||||
|
prints("wake: sel=");
|
||||||
|
sys·printpointer(sel);
|
||||||
|
prints(" c=");
|
||||||
|
sys·printpointer(c);
|
||||||
|
prints(" o=");
|
||||||
|
sys·printint(o);
|
||||||
|
prints("\n");
|
||||||
|
}
|
||||||
|
if(cas->send)
|
||||||
|
goto gots;
|
||||||
|
|
||||||
|
gotr:
|
||||||
|
if(0) {
|
||||||
|
prints("gotr: sel=");
|
||||||
|
sys·printpointer(sel);
|
||||||
|
prints(" c=");
|
||||||
|
sys·printpointer(c);
|
||||||
|
prints(" o=");
|
||||||
|
sys·printint(o);
|
||||||
|
prints("\n");
|
||||||
|
}
|
||||||
|
c->elemalg->copy(c->elemsize, sg->elem, cas->u.elem);
|
||||||
|
gp = sg->g;
|
||||||
|
gp->param = sg;
|
||||||
|
gp->status = Grunnable;
|
||||||
|
goto retc;
|
||||||
|
|
||||||
|
gots:
|
||||||
|
if(0) {
|
||||||
|
prints("gots: sel=");
|
||||||
|
sys·printpointer(sel);
|
||||||
|
prints(" c=");
|
||||||
|
sys·printpointer(c);
|
||||||
|
prints(" o=");
|
||||||
|
sys·printint(o);
|
||||||
|
prints("\n");
|
||||||
|
}
|
||||||
|
if(cas->u.elemp != nil)
|
||||||
|
c->elemalg->copy(c->elemsize, cas->u.elemp, sg->elem);
|
||||||
|
gp = sg->g;
|
||||||
|
gp->param = sg;
|
||||||
|
gp->status = Grunnable;
|
||||||
|
freesg(c, sg);
|
||||||
|
|
||||||
retc:
|
retc:
|
||||||
sys·setcallerpc(&sel, cas->pc);
|
sys·setcallerpc(&sel, cas->pc);
|
||||||
@ -561,7 +640,7 @@ loop:
|
|||||||
|
|
||||||
// if sgp is stale, ignore it
|
// if sgp is stale, ignore it
|
||||||
if(sgp->selgen != sgp->g->selgen) {
|
if(sgp->selgen != sgp->g->selgen) {
|
||||||
prints("INVALID PSEUDOG POINTER\n");
|
//prints("INVALID PSEUDOG POINTER\n");
|
||||||
freesg(c, sgp);
|
freesg(c, sgp);
|
||||||
goto loop;
|
goto loop;
|
||||||
}
|
}
|
||||||
|
@ -107,9 +107,10 @@ struct G
|
|||||||
byte* stack0; // first stack segment
|
byte* stack0; // first stack segment
|
||||||
Gobuf sched;
|
Gobuf sched;
|
||||||
G* alllink; // on allq
|
G* alllink; // on allq
|
||||||
int32 status;
|
void* param; // passed parameter on wakeup
|
||||||
|
int16 status;
|
||||||
int32 goid;
|
int32 goid;
|
||||||
int64 selgen; // valid sudog pointer
|
int32 selgen; // valid sudog pointer
|
||||||
};
|
};
|
||||||
struct M
|
struct M
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user