Commit ece3e57c authored by Ken Thompson's avatar Ken Thompson

read select

R=r
APPROVED=r
DELTA=120  (108 added, 0 deleted, 12 changed)
OCL=13468
CL=13468
parent 5fc79191
......@@ -446,6 +446,7 @@ loop:
case OIF:
case OSWITCH:
case OFOR:
case OSELECT:
dodump(n->ninit, dep);
break;
}
......@@ -480,6 +481,11 @@ loop:
}
return;
case OSELECT:
print("%O%J\n", n->op, n);
dodump(n->nbody, dep+1);
return;
case OSWITCH:
case OFOR:
print("%O%J\n", n->op, n);
......
......@@ -915,13 +915,18 @@ loop:
}
Node*
selcase(Node *c, Node *var)
selcase(Node *n, Node *var)
{
Node *a, *r, *on;
Node *a, *r, *on, *c;
Type *t;
c = n->left;
if(c->op == ORECV)
goto recv;
walktype(c->left, Erv); // chan
walktype(c->right, Erv); // elem
t = fixchan(c->left->type);
if(t == T)
return;
......@@ -937,11 +942,44 @@ selcase(Node *c, Node *var)
argtype(on, t->type);
argtype(on, t->type);
a = c->right; // elem
a = c->right; // elem
r = a;
a = c->left; // chan
a = c->left; // chan
r = list(a, r);
a = var; // sel-var
a = var; // sel-var
r = list(a, r);
a = nod(OCALL, on, r);
r = nod(OIF, N, N);
r->ntest = a;
return r;
recv:
walktype(c->left, Elv); // elem
walktype(c->right, Erv); // chan
t = fixchan(c->right->type);
if(t == T)
return;
convlit(c->left, t->type);
if(!ascompat(t->type, c->left->type)) {
badtype(c->op, t->type, c->left->type);
return;
}
// selectrecv(sel *byte, hchan *chan any, elem *any) (selected bool);
on = syslook("selectrecv", 1);
argtype(on, t->type);
argtype(on, t->type);
a = c->left; // elem
a = nod(OADDR, a, N);
r = a;
a = c->right; // chan
r = list(a, r);
a = var; // sel-var
r = list(a, r);
a = nod(OCALL, on, r);
......@@ -991,11 +1029,12 @@ walkselect(Node *sel)
break;
case OSEND:
case ORECV:
if(oc != N) {
bod = list(bod, nod(OBREAK, N, N));
oc->nbody = rev(bod);
}
oc = selcase(n->left, var);
oc = selcase(n, var);
res = list(res, oc);
break;
}
......@@ -1030,6 +1069,8 @@ walkselect(Node *sel)
walktype(sel->ninit, Etop);
walktype(sel->nbody, Etop);
dump("sel", sel);
lineno = lno;
}
......
......@@ -54,7 +54,10 @@ struct Scase
byte* pc; // return pc
uint16 send; // 0-recv 1-send
uint16 so; // vararg of selected bool
byte elem[8]; // element
union {
byte elem[8]; // element (send)
byte* elemp; // pointer to element (recv)
} u;
};
struct Select
......@@ -390,7 +393,7 @@ sys·selectsend(Select *sel, Hchan *c, ...)
cas->send = 1;
ae = (byte*)&sel + eo;
c->elemalg->copy(c->elemsize, cas->elem, ae);
c->elemalg->copy(c->elemsize, cas->u.elem, ae);
as = (byte*)&sel + cas->so;
*as = false;
......@@ -414,7 +417,45 @@ sys·selectsend(Select *sel, Hchan *c, ...)
void
sys·selectrecv(Select *sel, Hchan *c, ...)
{
throw("selectrecv");
int32 i, epo;
Scase *cas;
byte *as;
// return val, selected, is preset to false
if(c == nil)
return;
i = sel->ncase;
if(i >= sel->tcase)
throw("selectsend: too many cases");
sel->ncase = i+1;
cas = &sel->scase[i];
cas->pc = sys·getcallerpc(&sel);
cas->chan = c;
epo = rnd(sizeof(sel), sizeof(c));
epo = rnd(epo+sizeof(c), sizeof(byte*));
cas->so = rnd(epo+sizeof(byte*), 1);
cas->send = 0;
cas->u.elemp = *(byte**)((byte*)&sel + epo);
as = (byte*)&sel + cas->so;
*as = false;
if(debug) {
prints("newselect s=");
sys·printpointer(sel);
prints(" pc=");
sys·printpointer(cas->pc);
prints(" chan=");
sys·printpointer(cas->chan);
prints(" so=");
sys·printint(cas->so);
prints(" send=");
sys·printint(cas->send);
prints("\n");
}
}
// selectgo(sel *byte);
......@@ -429,6 +470,9 @@ sys·selectgo(Select *sel)
SudoG *sgr;
G *gr;
SudoG *sgs;
G *gs;
if(sel->ncase < 1) {
throw("selectgo: no cases");
}
......@@ -453,16 +497,33 @@ sys·selectgo(Select *sel)
c = cas->chan;
if(cas->send) {
if(c->dataqsiz > 0) {
throw("selectgo: asynch");
throw("selectgo: send asynch");
}
sgr = dequeue(&c->recvq, c);
if(sgr == nil)
continue;
c->elemalg->copy(c->elemsize, sgr->elem, cas->elem);
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");
}
sgs = dequeue(&c->sendq, c);
if(sgs == nil)
continue;
if(cas->u.elemp != nil)
c->elemalg->copy(c->elemsize, cas->u.elemp, sgs->elem);
gs = sgs->g;
gs->status = Grunnable;
freesg(c, sgs);
goto retc;
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment