From 8a9752dcfbecb1ef4fc6ab9e1f94cc84e7ccaba9 Mon Sep 17 00:00:00 2001 From: Ken Thompson Date: Sat, 20 Sep 2008 19:56:40 -0700 Subject: [PATCH] another async select bug R=r OCL=15599 CL=15599 --- src/cmd/gc/walk.c | 12 +- src/runtime/chan.c | 1 + test/ken/chan.go | 324 ++++++++++++++++++++++++++------------------- 3 files changed, 194 insertions(+), 143 deletions(-) diff --git a/src/cmd/gc/walk.c b/src/cmd/gc/walk.c index 9f27ac753e..2bf23de211 100644 --- a/src/cmd/gc/walk.c +++ b/src/cmd/gc/walk.c @@ -563,7 +563,7 @@ loop: goto ret; } - // structure literal + // array literal if(t->etype == TARRAY) { r = arraylit(n); indir(n, r); @@ -2149,9 +2149,13 @@ chanop(Node *n, int top) if(t == T) break; - a = n->left; // hint - if(n->left == N) + if(n->left != N) { + // async buf size + a = nod(OCONV, n->left, N); + a->type = types[TUINT32]; + } else a = nodintconst(0); + r = a; a = nodintconst(algtype(t->type)); // elem algorithm r = list(a, r); @@ -2991,10 +2995,10 @@ arraylit(Node *n) if(t->bound < 0) { // make it a closed array - // should there be a type copy here? r = listfirst(&saver, &n->left); for(idx=0; r!=N; idx++) r = listnext(&saver); + t = deep(t); t->bound = idx; } diff --git a/src/runtime/chan.c b/src/runtime/chan.c index 17f00d4ce7..b90e9ac543 100644 --- a/src/runtime/chan.c +++ b/src/runtime/chan.c @@ -652,6 +652,7 @@ asynr: sg = dequeue(&c->sendq, c); if(sg != nil) { gp = sg->g; + gp->param = sg; freesg(c, sg); ready(gp); } diff --git a/test/ken/chan.go b/test/ken/chan.go index be4fa86c33..8913528a87 100644 --- a/test/ken/chan.go +++ b/test/ken/chan.go @@ -8,32 +8,42 @@ package main import rand "rand" +type Chan +struct +{ + sc,rc *chan int; // send and recv chan + sv,rv int; // send and recv seq +} + var ( - c0 *chan int; - c1 *chan int; - c2 *chan int; - c3 *chan int; - n int; - End int = 1000; - totr int; - tots int; + nproc int; + cval int; + End int = 10000; + totr,tots int; + nc *Chan; ) func -mkchan(c uint) +init() { - n = 0; - - c0 = new(chan int, c); - c1 = new(chan int, c); - c2 = new(chan int, c); - c3 = new(chan int, c); + nc = new(Chan); +} -// print("c0=", c0, "\n"); -// print("c1=", c1, "\n"); -// print("c2=", c2, "\n"); -// print("c3=", c3, "\n"); +func +mkchan(c,n int) *[]*Chan +{ + ca := new([]*Chan, n); + for i:=0; i=0; r-- { sys.gosched(); } - c <- v0; - tots++; - v0 = expect(v0, v0); - if v0 == End { + c.sc <- c.sv; + if c.send() { break; } } - n--; + nproc--; } -func -selsend() +func (c *Chan) +recv(v int) bool { - var v int; - - a := 4; // local chans running - n += a; // total chans running - v0 := 100; - v1 := 200; - v2 := 300; - v3 := 400; - - // local copies of the chans - // so we can nil them out - l0 := c0; - l1 := c1; - l2 := c2; - l3 := c3; - - for { - for r:=rand.nrand(5); r>=0; r-- { - sys.gosched(); - } - - select { - case l0 <- v0: - v0 = expect(v0, v0); - if v0 == End { - l0 = nil; - a--; - } - case l1 <- v1: - v1 = expect(v1, v1); - if v1 == End { - l1 = nil; - a--; - } - case l2 <- v2: - v2 = expect(v2, v2); - if v2 == End { - l2 = nil; - a--; - } - case l3 <- v3: - v3 = expect(v3, v3); - if v3 == End { - l3 = nil; - a--; - } - } - - tots++; - if a == 0 { - break; - } +// print("recv ", v, "\n"); + totr++; + c.rv = expect(c.rv, v); + if c.rv == End { + c.rc = nil; + return true; } - n -= 4; + return false; } func -recv(c *chan int, v0 int) +recv(c *Chan) { var v int; - n++; - for i:=0; i<100; i++ { + nproc++; // total goroutines running + for { for r:=rand.nrand(10); r>=0; r-- { sys.gosched(); } - v = <- c; - totr++; - v0 = expect(v0, v); - if v0 == End { + v = <-c.rc; + if c.recv(v) { break; } } - n--; + nproc--; } func -selrecv() +sel(r0,r1,r2,r3, s0,s1,s2,s3 *Chan) { var v int; - a := 4; // local chans running - n += a; // total chans running - v0 := 100; - v1 := 200; - v2 := 300; - v3 := 400; + nproc++; // total goroutines running + a := 0; // local chans running + + if r0.rc != nil { a++ } + if r1.rc != nil { a++ } + if r2.rc != nil { a++ } + if r3.rc != nil { a++ } + if s0.sc != nil { a++ } + if s1.sc != nil { a++ } + if s2.sc != nil { a++ } + if s3.sc != nil { a++ } for { for r:=rand.nrand(5); r>=0; r-- { @@ -163,64 +141,118 @@ selrecv() } select { - case v = <- c0: - v0 = expect(v0, v); - if v0 == End { + case v = <-r0.rc: + if r0.recv(v) { a--; } - case v = <- c1: - v1 = expect(v1, v); - if v1 == End { + case v = <-r1.rc: + if r1.recv(v) { a--; } - case v = <- c2: - v2 = expect(v2, v); - if v2 == End { + case v = <-r2.rc: + if r2.recv(v) { a--; } - case v = <- c3: - v3 = expect(v3, v); - if v3 == End { + case v = <-r3.rc: + if r3.recv(v) { + a--; + } + case s0.sc <- s0.sv: + if s0.send() { + a--; + } + case s1.sc <- s1.sv: + if s1.send() { + a--; + } + case s2.sc <- s2.sv: + if s2.send() { + a--; + } + case s3.sc <- s3.sv: + if s3.send() { a--; } } - - totr++; if a == 0 { break; } } - n -= 4; + nproc--; } // direct send to direct recv func -test1(c *chan int, v0 int) +test1(c *Chan) { - go send(c, v0); - go recv(c, v0); + go send(c); + go recv(c); } // direct send to select recv func -test2() +test2(c int) { - go send(c0, 100); - go send(c1, 200); - go send(c2, 300); - go send(c3, 400); - go selrecv(); + ca := mkchan(c,4); + + go send(ca[0]); + go send(ca[1]); + go send(ca[2]); + go send(ca[3]); + + go sel(ca[0],ca[1],ca[2],ca[3], nc,nc,nc,nc); } // select send to direct recv func -test3() +test3(c int) +{ + ca := mkchan(c,4); + + go recv(ca[0]); + go recv(ca[1]); + go recv(ca[2]); + go recv(ca[3]); + + go sel(nc,nc,nc,nc, ca[0],ca[1],ca[2],ca[3]); +} + +// select send to select recv +func +test4(c int) +{ + ca := mkchan(c,4); + + go sel(nc,nc,nc,nc, ca[0],ca[1],ca[2],ca[3]); + go sel(ca[0],ca[1],ca[2],ca[3], nc,nc,nc,nc); +} + +func +test5(c int) { - go recv(c0, 100); - go recv(c1, 200); - go recv(c2, 300); - go recv(c3, 400); - go selsend(); + ca := mkchan(c,8); + + go sel(ca[4],ca[5],ca[6],ca[7], ca[0],ca[1],ca[2],ca[3]); + go sel(ca[0],ca[1],ca[2],ca[3], ca[4],ca[5],ca[6],ca[7]); +} + +func +test6(c int) +{ + ca := mkchan(c,12); + + go send(ca[4]); + go send(ca[5]); + go send(ca[6]); + go send(ca[7]); + + go recv(ca[8]); + go recv(ca[9]); + go recv(ca[10]); + go recv(ca[11]); + + go sel(ca[4],ca[5],ca[6],ca[7], ca[0],ca[1],ca[2],ca[3]); + go sel(ca[0],ca[1],ca[2],ca[3], ca[8],ca[9],ca[10],ca[11]); } // wait for outstanding tests to finish @@ -228,28 +260,35 @@ func wait() { sys.gosched(); - for n != 0 { + for nproc != 0 { sys.gosched(); } } // run all tests with specified buffer size func -tests(c uint) +tests(c int) { - mkchan(c); - test1(c0, 100); - test1(c1, 200); - test1(c2, 300); - test1(c3, 400); + ca := mkchan(c,4); + test1(ca[0]); + test1(ca[1]); + test1(ca[2]); + test1(ca[3]); + wait(); + + test2(c); + wait(); + + test3(c); wait(); - mkchan(c); - test2(); + test4(c); wait(); - mkchan(c); - test3(); + test5(c); + wait(); + + test6(c); wait(); } @@ -257,13 +296,20 @@ tests(c uint) func main() { + tests(0); tests(1); tests(10); tests(100); - if tots != totr || tots != 3648 { - print("tots=", tots, " totr=", totr, "\n"); + t := 4 // buffer sizes + * ( 4*4 // tests 1,2,3,4 channels + + 8 // test 5 channels + + 12 // test 6 channels + ) * 76; // sends/recvs on a channel + + if tots != t || totr != t { + print("tots=", tots, " totr=", totr, " sb=", t, "\n"); sys.exit(1); } sys.exit(0); -- 2.48.1