start of select
random bugs fixed
SVN=128149
diff --git a/src/cmd/6g/gen.c b/src/cmd/6g/gen.c
index 6dfafc4..3bab742 100644
--- a/src/cmd/6g/gen.c
+++ b/src/cmd/6g/gen.c
@@ -902,6 +902,11 @@
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 12a7ef8..1d8b921 100644
--- a/src/cmd/gc/const.c
+++ b/src/cmd/gc/const.c
@@ -20,9 +20,13 @@
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 1002f2b..9a49f6f 100644
--- a/src/cmd/gc/go.h
+++ b/src/cmd/gc/go.h
@@ -219,7 +219,7 @@
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 c0d0112..13c08ba 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 <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 @@
//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 @@
$$ = $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 1923308..b12ab05 100644
--- a/src/cmd/gc/lex.c
+++ b/src/cmd/gc/lex.c
@@ -962,20 +962,20 @@
"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 @@
"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 17f837e..b9c0da5 100644
--- a/src/cmd/gc/subr.c
+++ b/src/cmd/gc/subr.c
@@ -659,6 +659,7 @@
[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 6282c78..99f9b23 100644
--- a/src/runtime/chan.c
+++ b/src/runtime/chan.c
@@ -8,6 +8,21 @@
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 @@
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 @@
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 @@
sys·chansend1(Hchan* c, ...)
{
byte *ae;
- G *gr;
+ SudoG *sgr;
+ G* gr;
ae = (byte*)&c + c->eo;
if(debug) {
@@ -110,30 +132,39 @@
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 @@
sys·chansend2(Hchan* c, ...)
{
byte *ae, *ap;
+ SudoG *sgr;
G *gr;
ae = (byte*)&c + c->eo;
@@ -156,8 +188,11 @@
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 @@
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 @@
sys·chanrecv1(Hchan* c, ...)
{
byte *ae;
+ SudoG *sgs;
G *gs;
ae = (byte*)&c + c->eo;
@@ -196,30 +235,39 @@
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 @@
sys·chanrecv2(Hchan* c, ...)
{
byte *ae, *ap;
+ SudoG *sgs;
G *gs;
ae = (byte*)&c + c->eo;
@@ -240,8 +289,11 @@
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 @@
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 807c70b..ecd4ced 100644
--- a/src/runtime/proc.c
+++ b/src/runtime/proc.c
@@ -254,28 +254,3 @@
*(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 b1e8b69..df14b76 100644
--- a/src/runtime/runtime.h
+++ b/src/runtime/runtime.h
@@ -42,7 +42,6 @@
typedef struct M M;
typedef struct Stktop Stktop;
typedef struct Alg Alg;
-typedef struct WaitQ WaitQ;
/*
* per cpu declaration
@@ -108,9 +107,9 @@
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 @@
int32 siz1;
int32 siz2;
};
-struct WaitQ
-{
- G* first;
- G* last;
-};
struct Stktop
{
uint8* oldbase;
@@ -176,8 +170,6 @@
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 abafc46..65ea0db 100644
--- a/test/chan/powser1.go
+++ b/test/chan/powser1.go
@@ -233,24 +233,6 @@
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 @@
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 @@
}
// 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);