From: Ken Thompson Date: Mon, 21 Jul 2008 03:13:07 +0000 (-0700) Subject: start of select X-Git-Tag: weekly.2009-11-06~3451 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=b78676a49d77f6bde1c54bc4a6389120e5a8c391;p=gostls13.git start of select random bugs fixed SVN=128149 --- diff --git a/src/cmd/6g/gen.c b/src/cmd/6g/gen.c index 6dfafc46a6..3bab7425f7 100644 --- a/src/cmd/6g/gen.c +++ b/src/cmd/6g/gen.c @@ -902,6 +902,11 @@ cgen_as(Node *nl, Node *nr, int op) case TPTR32: case TPTR64: + if(isptrto(tl, TSTRING)) { + nr->val.sval = mal(8); + nr->val.ctype = CTSTR; + break; + } nr->val.ctype = CTNIL; nr->val.vval = 0; break; diff --git a/src/cmd/gc/const.c b/src/cmd/gc/const.c index 12a7ef83b8..1d8b921c65 100644 --- a/src/cmd/gc/const.c +++ b/src/cmd/gc/const.c @@ -20,9 +20,13 @@ convlit(Node *n, Type *t) goto bad1; case Wlitnil: - if(isptr[et] || et == TINTER) - break; - goto bad1; + if(!isptr[et] && et != TINTER) + goto bad1; + if(isptrto(t, TSTRING)) { + n->val.sval = mal(8); + n->val.ctype = CTSTR; + } + break; case Wlitstr: if(isptrto(t, TSTRING)) diff --git a/src/cmd/gc/go.h b/src/cmd/gc/go.h index 1002f2b51a..9a49f6f12c 100644 --- a/src/cmd/gc/go.h +++ b/src/cmd/gc/go.h @@ -219,7 +219,7 @@ enum OLIST, OCMP, OPTR, OARRAY, ORETURN, OFOR, OIF, OSWITCH, OI2S, OS2I, OI2I, - OAS, OASOP, OCASE, OXCASE, OFALL, OXFALL, + OAS, OASOP, OCASE, OXCASE, OFALL, OXFALL, OSELECT, OGOTO, OPROC, ONEW, OPANIC, OPRINT, OEMPTY, OOROR, diff --git a/src/cmd/gc/go.y b/src/cmd/gc/go.y index c0d01124c5..13c08baf02 100644 --- a/src/cmd/gc/go.y +++ b/src/cmd/gc/go.y @@ -18,7 +18,7 @@ %token LMAP LCHAN LINTERFACE LFUNC LSTRUCT %token LCOLAS LFALL LRETURN %token LNEW LLEN -%token LVAR LTYPE LCONST LCONVERT +%token LVAR LTYPE LCONST LCONVERT LSELECT %token LFOR LIF LELSE LSWITCH LCASE LDEFAULT %token LBREAK LCONTINUE LGO LGOTO LRANGE %token LOROR LANDAND LEQ LNE LLE LLT LGE LGT @@ -37,7 +37,7 @@ %type Astmt Bstmt Cstmt Dstmt %type for_stmt for_body for_header %type if_stmt if_body if_header -%type range_header range_body range_stmt +%type range_header range_body range_stmt select_stmt %type simple_stmt osimple_stmt semi_stmt %type expr uexpr pexpr expr_list oexpr oexpr_list expr_list_r %type name name_name new_name new_name_list_r conexpr @@ -360,6 +360,11 @@ complex_stmt: //if($$->ninit != N && $$->ntest == N) // yyerror("if conditional should not be missing"); } +| LSELECT select_stmt + { + popdcl(); + $$ = $2; + } | LRANGE range_stmt { popdcl(); @@ -529,6 +534,15 @@ range_stmt: $$ = $2; } +select_stmt: + { + markdcl(); + } + compound_stmt + { + $$ = nod(OSELECT, $2, N); + } + /* * expressions */ diff --git a/src/cmd/gc/lex.c b/src/cmd/gc/lex.c index 19233085ce..b12ab05d68 100644 --- a/src/cmd/gc/lex.c +++ b/src/cmd/gc/lex.c @@ -962,20 +962,20 @@ static struct "string", LBASETYPE, TSTRING, "any", LBASETYPE, TANY, + "sys", LPACK, Txxx, /* keywords */ -// "any", LANY, Txxx, "break", LBREAK, Txxx, "case", LCASE, Txxx, "chan", LCHAN, Txxx, "const", LCONST, Txxx, "continue", LCONTINUE, Txxx, - "convert", LCONVERT, Txxx, + "convert", LCONVERT, Txxx, // should be a var "default", LDEFAULT, Txxx, "else", LELSE, Txxx, "export", LEXPORT, Txxx, "fallthrough", LFALL, Txxx, - "false", LFALSE, Txxx, + "false", LFALSE, Txxx, // should be a var "for", LFOR, Txxx, "func", LFUNC, Txxx, "go", LGO, Txxx, @@ -985,20 +985,20 @@ static struct "interface", LINTERFACE, Txxx, "iota", LIOTA, Txxx, "map", LMAP, Txxx, - "new", LNEW, Txxx, - "len", LLEN, Txxx, - "nil", LNIL, Txxx, + "new", LNEW, Txxx, // should be a var + "len", LLEN, Txxx, // should be a var + "nil", LNIL, Txxx, // should be a var "package", LPACKAGE, Txxx, - "panic", LPANIC, Txxx, - "print", LPRINT, Txxx, + "panic", LPANIC, Txxx, // temp + "print", LPRINT, Txxx, // temp "range", LRANGE, Txxx, "return", LRETURN, Txxx, + "select", LSELECT, Txxx, "struct", LSTRUCT, Txxx, "switch", LSWITCH, Txxx, - "true", LTRUE, Txxx, + "true", LTRUE, Txxx, // should be a var "type", LTYPE, Txxx, "var", LVAR, Txxx, - "sys", LPACK, Txxx, "notwithstanding", LIGNORE, Txxx, "thetruthofthematter", LIGNORE, Txxx, diff --git a/src/cmd/gc/subr.c b/src/cmd/gc/subr.c index 17f837e293..b9c0da5407 100644 --- a/src/cmd/gc/subr.c +++ b/src/cmd/gc/subr.c @@ -659,6 +659,7 @@ opnames[] = [OI2I] = "I2I", [OSLICE] = "SLICE", [OSUB] = "SUB", + [OSELECT] = "SELECT", [OSWITCH] = "SWITCH", [OTYPE] = "TYPE", [OVAR] = "VAR", diff --git a/src/runtime/chan.c b/src/runtime/chan.c index 6282c785a0..99f9b23857 100644 --- a/src/runtime/chan.c +++ b/src/runtime/chan.c @@ -8,6 +8,21 @@ static int32 debug = 0; typedef struct Hchan Hchan; typedef struct Link Link; +typedef struct WaitQ WaitQ; +typedef struct SudoG SudoG; + +struct SudoG +{ + G* g; // g and selgen constitute + int64 selgen; // a weak pointer to g + SudoG* link; +}; + +struct WaitQ +{ + SudoG* first; + SudoG* last; +}; struct Hchan { @@ -21,6 +36,7 @@ struct Hchan Link* recvdataq; // pointer for receiver WaitQ recvq; // list of recv waiters WaitQ sendq; // list of send waiters + SudoG* free; // freelist }; struct Link @@ -29,6 +45,11 @@ struct Link byte elem[8]; }; +static SudoG* dequeue(WaitQ*, Hchan*); +static void enqueue(WaitQ*, SudoG*); +static SudoG* allocsg(Hchan*); +static void freesg(Hchan*, SudoG*); + // newchan(elemsize uint32, elemalg uint32, hint uint32) (hchan *chan any); void sys·newchan(uint32 elemsize, uint32 elemalg, uint32 hint, @@ -97,7 +118,8 @@ void sys·chansend1(Hchan* c, ...) { byte *ae; - G *gr; + SudoG *sgr; + G* gr; ae = (byte*)&c + c->eo; if(debug) { @@ -110,30 +132,39 @@ sys·chansend1(Hchan* c, ...) if(c->dataqsiz > 0) goto asynch; - gr = dequeue(&c->recvq); - if(gr != nil) { + sgr = dequeue(&c->recvq, c); + if(sgr != nil) { + gr = sgr->g; + freesg(c, sgr); + c->elemalg->copy(c->elemsize, gr->elem, ae); gr->status = Grunnable; return; } + c->elemalg->copy(c->elemsize, g->elem, ae); + sgr = allocsg(c); g->status = Gwaiting; - enqueue(&c->sendq, g); + enqueue(&c->sendq, sgr); sys·gosched(); return; asynch: while(c->qcount >= c->dataqsiz) { + sgr = allocsg(c); g->status = Gwaiting; - enqueue(&c->sendq, g); + enqueue(&c->sendq, sgr); sys·gosched(); } c->elemalg->copy(c->elemsize, c->senddataq->elem, ae); c->senddataq = c->senddataq->link; c->qcount++; - gr = dequeue(&c->recvq); - if(gr != nil) + sgr = dequeue(&c->recvq, c); + if(sgr != nil) { + gr = sgr->g; + freesg(c, sgr); gr->status = Grunnable; + } } // chansend2(hchan *chan any, elem any) (pres bool); @@ -141,6 +172,7 @@ void sys·chansend2(Hchan* c, ...) { byte *ae, *ap; + SudoG *sgr; G *gr; ae = (byte*)&c + c->eo; @@ -156,8 +188,11 @@ sys·chansend2(Hchan* c, ...) if(c->dataqsiz > 0) goto asynch; - gr = dequeue(&c->recvq); - if(gr != nil) { + sgr = dequeue(&c->recvq, c); + if(sgr != nil) { + gr = sgr->g; + freesg(c, sgr); + c->elemalg->copy(c->elemsize, gr->elem, ae); gr->status = Grunnable; *ap = true; @@ -174,9 +209,12 @@ asynch: c->elemalg->copy(c->elemsize, c->senddataq->elem, ae); c->senddataq = c->senddataq->link; c->qcount++; - gr = dequeue(&c->recvq); - if(gr != nil) + sgr = dequeue(&c->recvq, c); + if(gr != nil) { + gr = sgr->g; + freesg(c, sgr); gr->status = Grunnable; + } *ap = true; } @@ -185,6 +223,7 @@ void sys·chanrecv1(Hchan* c, ...) { byte *ae; + SudoG *sgs; G *gs; ae = (byte*)&c + c->eo; @@ -196,30 +235,39 @@ sys·chanrecv1(Hchan* c, ...) if(c->dataqsiz > 0) goto asynch; - gs = dequeue(&c->sendq); - if(gs != nil) { + sgs = dequeue(&c->sendq, c); + if(sgs != nil) { + gs = sgs->g; + freesg(c, sgs); + c->elemalg->copy(c->elemsize, ae, gs->elem); gs->status = Grunnable; return; } + sgs = allocsg(c); g->status = Gwaiting; - enqueue(&c->recvq, g); + enqueue(&c->recvq, sgs); sys·gosched(); c->elemalg->copy(c->elemsize, ae, g->elem); return; asynch: while(c->qcount <= 0) { + sgs = allocsg(c); g->status = Gwaiting; - enqueue(&c->recvq, g); + enqueue(&c->recvq, sgs); sys·gosched(); } c->elemalg->copy(c->elemsize, ae, c->recvdataq->elem); c->recvdataq = c->recvdataq->link; c->qcount--; - gs = dequeue(&c->sendq); - if(gs != nil) + sgs = dequeue(&c->sendq, c); + if(gs != nil) { + gs = sgs->g; + freesg(c, sgs); + gs->status = Grunnable; + } } // chanrecv2(hchan *chan any) (elem any, pres bool); @@ -227,6 +275,7 @@ void sys·chanrecv2(Hchan* c, ...) { byte *ae, *ap; + SudoG *sgs; G *gs; ae = (byte*)&c + c->eo; @@ -240,8 +289,11 @@ sys·chanrecv2(Hchan* c, ...) if(c->dataqsiz > 0) goto asynch; - gs = dequeue(&c->sendq); - if(gs != nil) { + sgs = dequeue(&c->sendq, c); + if(sgs != nil) { + gs = sgs->g; + freesg(c, sgs); + c->elemalg->copy(c->elemsize, ae, gs->elem); gs->status = Grunnable; *ap = true; @@ -258,8 +310,70 @@ asynch: c->elemalg->copy(c->elemsize, ae, c->recvdataq->elem); c->recvdataq = c->recvdataq->link; c->qcount--; - gs = dequeue(&c->sendq); - if(gs != nil) + sgs = dequeue(&c->sendq, c); + if(sgs != nil) { + gs = sgs->g; + freesg(c, sgs); + gs->status = Grunnable; + } *ap = true; } + +static SudoG* +dequeue(WaitQ *q, Hchan *c) +{ + SudoG *sgp; + +loop: + sgp = q->first; + if(sgp == nil) + return nil; + q->first = sgp->link; + + // if sgp is stale, ignore it + if(sgp->selgen != sgp->g->selgen) { +prints("INVALID PSEUDOG POINTER\n"); + freesg(c, sgp); + goto loop; + } + + // invalidate any others + sgp->g->selgen++; + return sgp; +} + +static void +enqueue(WaitQ *q, SudoG *sgp) +{ + sgp->link = nil; + if(q->first == nil) { + q->first = sgp; + q->last = sgp; + return; + } + q->last->link = sgp; + q->last = sgp; +} + +static SudoG* +allocsg(Hchan *c) +{ + SudoG* sg; + + sg = c->free; + if(sg != nil) { + c->free = sg->link; + } else + sg = mal(sizeof(*sg)); + sg->selgen = g->selgen; + sg->g = g; + return sg; +} + +static void +freesg(Hchan *c, SudoG *sg) +{ + sg->link = c->free; + c->free = sg; +} diff --git a/src/runtime/proc.c b/src/runtime/proc.c index 807c70b60b..ecd4cedab0 100644 --- a/src/runtime/proc.c +++ b/src/runtime/proc.c @@ -254,28 +254,3 @@ sys·morestack(uint64 u) *(int32*)234 = 123; // never return } - -G* -dequeue(WaitQ *q) -{ - G *gp; - - gp = q->first; - if(gp == nil) - return nil; - q->first = gp->qlink; - return gp; -} - -void -enqueue(WaitQ *q, G *gp) -{ - gp->qlink = nil; - if(q->first == nil) { - q->first = gp; - q->last = gp; - return; - } - q->last->qlink = gp; - q->last = gp; -} diff --git a/src/runtime/runtime.h b/src/runtime/runtime.h index b1e8b69b25..df14b76783 100644 --- a/src/runtime/runtime.h +++ b/src/runtime/runtime.h @@ -42,7 +42,6 @@ typedef struct G G; typedef struct M M; typedef struct Stktop Stktop; typedef struct Alg Alg; -typedef struct WaitQ WaitQ; /* * per cpu declaration @@ -108,9 +107,9 @@ struct G byte* stack0; // first stack segment Gobuf sched; G* alllink; // on allq - G* qlink; // on wait q int32 status; int32 goid; + int64 selgen; // valid sudog pointer byte elem[8]; // transfer element for chan }; struct M @@ -126,11 +125,6 @@ struct M int32 siz1; int32 siz2; }; -struct WaitQ -{ - G* first; - G* last; -}; struct Stktop { uint8* oldbase; @@ -176,8 +170,6 @@ int32 findnull(int8*); void dump(byte*, int32); int32 runetochar(byte*, int32); int32 chartorune(uint32*, byte*); -G* dequeue(WaitQ*); -void enqueue(WaitQ*, G*); /* * very low level c-called diff --git a/test/chan/powser1.go b/test/chan/powser1.go index abafc469ba..65ea0db2fe 100644 --- a/test/chan/powser1.go +++ b/test/chan/powser1.go @@ -233,24 +233,6 @@ type PS2 *[2] PS; // pair of power series var Ones PS var Twos PS -// print eval in floating point of PS at x=c to n terms -func -Evaln(c *rat, U PS, n int) -{ - xn := float64(1); - x := float64(c.num)/float64(c.den); - val := float64(0); - for i:=0; i0; n-- { @@ -352,7 +351,6 @@ func Print(U PS){ } // Evaluate n terms of power series U at x=c - func eval(c *rat, U PS, n int) *rat{ if n==0 { return zero } y := get(U);