]> Cypherpunks repositories - gostls13.git/commitdiff
another async select bug
authorKen Thompson <ken@golang.org>
Sun, 21 Sep 2008 02:56:40 +0000 (19:56 -0700)
committerKen Thompson <ken@golang.org>
Sun, 21 Sep 2008 02:56:40 +0000 (19:56 -0700)
R=r
OCL=15599
CL=15599

src/cmd/gc/walk.c
src/runtime/chan.c
test/ken/chan.go

index 9f27ac753e9254cf98455143c85468a9745b7e74..2bf23de211f7a8c485c2a3950686e01ae3a89530 100644 (file)
@@ -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;
        }
 
index 17f00d4ce7fdc8b7d7cb03cbf250f375414c979e..b90e9ac543adff7cff138a4d57bc32fb8f6adaca 100644 (file)
@@ -652,6 +652,7 @@ asynr:
        sg = dequeue(&c->sendq, c);
        if(sg != nil) {
                gp = sg->g;
+               gp->param = sg;
                freesg(c, sg);
                ready(gp);
        }
index be4fa86c33889cea9947cda0b4ca2cd8b4ba09e4..8913528a87ae19bc1e11cd3cea2f0f87b61fc4fc 100644 (file)
@@ -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<n; i++ {
+               cval = cval+100;
+               ch := new(Chan);
+               ch.sc = new(chan int, c);
+               ch.rc = ch.sc;
+               ch.sv = cval;
+               ch.rv = cval;
+               ca[i] = ch;
+       }
+       return ca;
 }
 
 func
@@ -48,114 +58,82 @@ expect(v, v0 int) (newv int)
        panic("got ", v, " expected ", v0+1, "\n");
 }
 
+func (c *Chan)
+send() bool
+{
+//     print("send ", c.sv, "\n");
+       tots++;
+       c.sv = expect(c.sv, c.sv);
+       if c.sv == End {
+               c.sc = nil
+               return true;
+       }
+       return false;
+}
+
 func
-send(c *chan int, v0 int)
+send(c *Chan)
 {
-       n++;
+       nproc++;        // total goroutines running
        for {
                for r:=rand.nrand(10); r>=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);