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: ...@@ -446,6 +446,7 @@ loop:
case OIF: case OIF:
case OSWITCH: case OSWITCH:
case OFOR: case OFOR:
case OSELECT:
dodump(n->ninit, dep); dodump(n->ninit, dep);
break; break;
} }
...@@ -480,6 +481,11 @@ loop: ...@@ -480,6 +481,11 @@ loop:
} }
return; return;
case OSELECT:
print("%O%J\n", n->op, n);
dodump(n->nbody, dep+1);
return;
case OSWITCH: case OSWITCH:
case OFOR: case OFOR:
print("%O%J\n", n->op, n); print("%O%J\n", n->op, n);
......
...@@ -915,13 +915,18 @@ loop: ...@@ -915,13 +915,18 @@ loop:
} }
Node* Node*
selcase(Node *c, Node *var) selcase(Node *n, Node *var)
{ {
Node *a, *r, *on; Node *a, *r, *on, *c;
Type *t; Type *t;
c = n->left;
if(c->op == ORECV)
goto recv;
walktype(c->left, Erv); // chan walktype(c->left, Erv); // chan
walktype(c->right, Erv); // elem walktype(c->right, Erv); // elem
t = fixchan(c->left->type); t = fixchan(c->left->type);
if(t == T) if(t == T)
return; return;
...@@ -950,6 +955,39 @@ selcase(Node *c, Node *var) ...@@ -950,6 +955,39 @@ selcase(Node *c, Node *var)
return r; 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);
r = nod(OIF, N, N);
r->ntest = a;
return r;
} }
void void
...@@ -991,11 +1029,12 @@ walkselect(Node *sel) ...@@ -991,11 +1029,12 @@ walkselect(Node *sel)
break; break;
case OSEND: case OSEND:
case ORECV:
if(oc != N) { if(oc != N) {
bod = list(bod, nod(OBREAK, N, N)); bod = list(bod, nod(OBREAK, N, N));
oc->nbody = rev(bod); oc->nbody = rev(bod);
} }
oc = selcase(n->left, var); oc = selcase(n, var);
res = list(res, oc); res = list(res, oc);
break; break;
} }
...@@ -1030,6 +1069,8 @@ walkselect(Node *sel) ...@@ -1030,6 +1069,8 @@ walkselect(Node *sel)
walktype(sel->ninit, Etop); walktype(sel->ninit, Etop);
walktype(sel->nbody, Etop); walktype(sel->nbody, Etop);
dump("sel", sel);
lineno = lno; lineno = lno;
} }
......
...@@ -54,7 +54,10 @@ struct Scase ...@@ -54,7 +54,10 @@ struct Scase
byte* pc; // return pc byte* pc; // return pc
uint16 send; // 0-recv 1-send uint16 send; // 0-recv 1-send
uint16 so; // vararg of selected bool 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 struct Select
...@@ -390,7 +393,7 @@ sys·selectsend(Select *sel, Hchan *c, ...) ...@@ -390,7 +393,7 @@ sys·selectsend(Select *sel, Hchan *c, ...)
cas->send = 1; cas->send = 1;
ae = (byte*)&sel + eo; 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 = (byte*)&sel + cas->so;
*as = false; *as = false;
...@@ -414,7 +417,45 @@ sys·selectsend(Select *sel, Hchan *c, ...) ...@@ -414,7 +417,45 @@ sys·selectsend(Select *sel, Hchan *c, ...)
void void
sys·selectrecv(Select *sel, Hchan *c, ...) 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); // selectgo(sel *byte);
...@@ -429,6 +470,9 @@ sys·selectgo(Select *sel) ...@@ -429,6 +470,9 @@ sys·selectgo(Select *sel)
SudoG *sgr; SudoG *sgr;
G *gr; G *gr;
SudoG *sgs;
G *gs;
if(sel->ncase < 1) { if(sel->ncase < 1) {
throw("selectgo: no cases"); throw("selectgo: no cases");
} }
...@@ -453,16 +497,33 @@ sys·selectgo(Select *sel) ...@@ -453,16 +497,33 @@ sys·selectgo(Select *sel)
c = cas->chan; c = cas->chan;
if(cas->send) { if(cas->send) {
if(c->dataqsiz > 0) { if(c->dataqsiz > 0) {
throw("selectgo: asynch"); throw("selectgo: send asynch");
} }
sgr = dequeue(&c->recvq, c); sgr = dequeue(&c->recvq, c);
if(sgr == nil) if(sgr == nil)
continue; continue;
c->elemalg->copy(c->elemsize, sgr->elem, cas->elem); c->elemalg->copy(c->elemsize, sgr->elem, cas->u.elem);
gr = sgr->g; gr = sgr->g;
gr->status = Grunnable; 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; 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