1
0
mirror of https://github.com/golang/go synced 2024-11-26 18:06:55 -07:00
R=r
APPROVED=r
DELTA=147  (94 added, 14 deleted, 39 changed)
OCL=13477
CL=13477
This commit is contained in:
Ken Thompson 2008-07-25 15:55:12 -07:00
parent 756c63cd02
commit e963cba8a1
3 changed files with 126 additions and 46 deletions

View File

@ -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;
} }

View File

@ -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) {
if(sel->ncase < 1)
throw("selectgo: no cases"); 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;
} }

View File

@ -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
{ {