]> Cypherpunks repositories - gostls13.git/commitdiff
start of select
authorKen Thompson <ken@golang.org>
Mon, 21 Jul 2008 03:13:07 +0000 (20:13 -0700)
committerKen Thompson <ken@golang.org>
Mon, 21 Jul 2008 03:13:07 +0000 (20:13 -0700)
random bugs fixed

SVN=128149

src/cmd/6g/gen.c
src/cmd/gc/const.c
src/cmd/gc/go.h
src/cmd/gc/go.y
src/cmd/gc/lex.c
src/cmd/gc/subr.c
src/runtime/chan.c
src/runtime/proc.c
src/runtime/runtime.h
test/chan/powser1.go

index 6dfafc46a6e60879f5b3b0dd7547edc51e330ccb..3bab7425f7361f64a15881e7384f2ca4205029e7 100644 (file)
@@ -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;
index 12a7ef83b86e30686f3569989cccc099ade7aa2a..1d8b921c657fefc7b1ecc89d644bf861df0b5e55 100644 (file)
@@ -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))
index 1002f2b51ac9314f6eb2bac63257b699ba7f30f9..9a49f6f12ca88c53c179bfa88ed0350f72e1d64b 100644 (file)
@@ -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,
index c0d01124c5833eb6a9318a7c9c924d17e882faac..13c08baf023fe86f0786b198999bfd4854a94d4d 100644 (file)
@@ -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  <node>          Astmt Bstmt Cstmt Dstmt
 %type  <node>          for_stmt for_body for_header
 %type  <node>          if_stmt if_body if_header
-%type  <node>          range_header range_body range_stmt
+%type  <node>          range_header range_body range_stmt select_stmt
 %type  <node>          simple_stmt osimple_stmt semi_stmt
 %type  <node>          expr uexpr pexpr expr_list oexpr oexpr_list expr_list_r
 %type  <node>          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
  */
index 19233085cee72539880feb147b3488525216567d..b12ab05d68e6d42ac424831363a98710ef2098fa 100644 (file)
@@ -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,
index 17f837e29386b0d5cec9922ebdd9234e1f597b0c..b9c0da5407dab004a019db22f79ee09910eb77c4 100644 (file)
@@ -659,6 +659,7 @@ opnames[] =
        [OI2I]          = "I2I",
        [OSLICE]        = "SLICE",
        [OSUB]          = "SUB",
+       [OSELECT]       = "SELECT",
        [OSWITCH]       = "SWITCH",
        [OTYPE]         = "TYPE",
        [OVAR]          = "VAR",
index 6282c785a0163219c5e04c7e54c52f6d498854e1..99f9b23857ea368555b4c7864908eee95892bacc 100644 (file)
@@ -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;
+}
index 807c70b60bf4db48a9d89fdba91426ec28830b59..ecd4cedab047e7bb2fc4fe138881847170f09fba 100644 (file)
@@ -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;
-}
index b1e8b69b259fb9c64c9f6451d683e56b242814ec..df14b7678377cd8b3ee339920b934772d06a5f50 100644 (file)
@@ -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
index abafc469babd922734f031daec60613ae5203f52..65ea0db2fe6bef9145e58a99b090adf9755b4859 100644 (file)
@@ -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; i<n; i++ {
-               u := get(U);
-               if end(u) != 0 {
-                       break;
-               }
-               val = val + x * float64(u.num)/float64(u.den);
-               xn = xn*x;
-       }
-       print val, "\n";
-}
-
 func mkPS() *dch {
        return mkdch()
 }
@@ -335,8 +317,25 @@ func inv(u *rat) *rat{     // invert a rat
        return i2tor(u.den, u.num);
 }
 
-// Print n terms of a power series
+// 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; i<n; i++ {
+               u := get(U);
+               if end(u) != 0 {
+                       break;
+               }
+               val = val + x * float64(u.num)/float64(u.den);
+               xn = xn*x;
+       }
+       print val, "\n";
+}
 
+// Print n terms of a power series
 func Printn(U PS, n int){
        done := false;
        for ; !done && n>0; 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);