Commit 8a9752dc authored by Ken Thompson's avatar Ken Thompson

another async select bug

R=r
OCL=15599
CL=15599
parent 9ebd9d3b
...@@ -563,7 +563,7 @@ loop: ...@@ -563,7 +563,7 @@ loop:
goto ret; goto ret;
} }
// structure literal // array literal
if(t->etype == TARRAY) { if(t->etype == TARRAY) {
r = arraylit(n); r = arraylit(n);
indir(n, r); indir(n, r);
...@@ -2149,9 +2149,13 @@ chanop(Node *n, int top) ...@@ -2149,9 +2149,13 @@ chanop(Node *n, int top)
if(t == T) if(t == T)
break; 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); a = nodintconst(0);
r = a; r = a;
a = nodintconst(algtype(t->type)); // elem algorithm a = nodintconst(algtype(t->type)); // elem algorithm
r = list(a, r); r = list(a, r);
...@@ -2991,10 +2995,10 @@ arraylit(Node *n) ...@@ -2991,10 +2995,10 @@ arraylit(Node *n)
if(t->bound < 0) { if(t->bound < 0) {
// make it a closed array // make it a closed array
// should there be a type copy here?
r = listfirst(&saver, &n->left); r = listfirst(&saver, &n->left);
for(idx=0; r!=N; idx++) for(idx=0; r!=N; idx++)
r = listnext(&saver); r = listnext(&saver);
t = deep(t);
t->bound = idx; t->bound = idx;
} }
......
...@@ -652,6 +652,7 @@ asynr: ...@@ -652,6 +652,7 @@ asynr:
sg = dequeue(&c->sendq, c); sg = dequeue(&c->sendq, c);
if(sg != nil) { if(sg != nil) {
gp = sg->g; gp = sg->g;
gp->param = sg;
freesg(c, sg); freesg(c, sg);
ready(gp); ready(gp);
} }
......
...@@ -8,32 +8,42 @@ package main ...@@ -8,32 +8,42 @@ package main
import rand "rand" import rand "rand"
type Chan
struct
{
sc,rc *chan int; // send and recv chan
sv,rv int; // send and recv seq
}
var var
( (
c0 *chan int; nproc int;
c1 *chan int; cval int;
c2 *chan int; End int = 10000;
c3 *chan int; totr,tots int;
n int; nc *Chan;
End int = 1000;
totr int;
tots int;
) )
func func
mkchan(c uint) init()
{ {
n = 0; nc = new(Chan);
}
c0 = new(chan int, c);
c1 = new(chan int, c);
c2 = new(chan int, c);
c3 = new(chan int, c);
// print("c0=", c0, "\n"); func
// print("c1=", c1, "\n"); mkchan(c,n int) *[]*Chan
// print("c2=", c2, "\n"); {
// print("c3=", c3, "\n"); 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 func
...@@ -48,114 +58,82 @@ expect(v, v0 int) (newv int) ...@@ -48,114 +58,82 @@ expect(v, v0 int) (newv int)
panic("got ", v, " expected ", v0+1, "\n"); panic("got ", v, " expected ", v0+1, "\n");
} }
func func (c *Chan)
send(c *chan int, v0 int) send() bool
{ {
n++; // print("send ", c.sv, "\n");
for {
for r:=rand.nrand(10); r>=0; r-- {
sys.gosched();
}
c <- v0;
tots++; tots++;
v0 = expect(v0, v0); c.sv = expect(c.sv, c.sv);
if v0 == End { if c.sv == End {
break; c.sc = nil
} return true;
} }
n--; return false;
} }
func func
selsend() send(c *Chan)
{ {
var v int; nproc++; // total goroutines running
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 {
for r:=rand.nrand(5); r>=0; r-- { for r:=rand.nrand(10); r>=0; r-- {
sys.gosched(); sys.gosched();
} }
c.sc <- c.sv;
select { if c.send() {
case l0 <- v0: break;
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--;
} }
} }
nproc--;
}
tots++; func (c *Chan)
if a == 0 { recv(v int) bool
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 func
recv(c *chan int, v0 int) recv(c *Chan)
{ {
var v int; var v int;
n++; nproc++; // total goroutines running
for i:=0; i<100; i++ { for {
for r:=rand.nrand(10); r>=0; r-- { for r:=rand.nrand(10); r>=0; r-- {
sys.gosched(); sys.gosched();
} }
v = <- c; v = <-c.rc;
totr++; if c.recv(v) {
v0 = expect(v0, v);
if v0 == End {
break; break;
} }
} }
n--; nproc--;
} }
func func
selrecv() sel(r0,r1,r2,r3, s0,s1,s2,s3 *Chan)
{ {
var v int; var v int;
a := 4; // local chans running nproc++; // total goroutines running
n += a; // total chans running a := 0; // local chans running
v0 := 100;
v1 := 200; if r0.rc != nil { a++ }
v2 := 300; if r1.rc != nil { a++ }
v3 := 400; 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 {
for r:=rand.nrand(5); r>=0; r-- { for r:=rand.nrand(5); r>=0; r-- {
...@@ -163,64 +141,118 @@ selrecv() ...@@ -163,64 +141,118 @@ selrecv()
} }
select { select {
case v = <- c0: case v = <-r0.rc:
v0 = expect(v0, v); if r0.recv(v) {
if v0 == End {
a--; a--;
} }
case v = <- c1: case v = <-r1.rc:
v1 = expect(v1, v); if r1.recv(v) {
if v1 == End {
a--; a--;
} }
case v = <- c2: case v = <-r2.rc:
v2 = expect(v2, v); if r2.recv(v) {
if v2 == End {
a--; a--;
} }
case v = <- c3: case v = <-r3.rc:
v3 = expect(v3, v); if r3.recv(v) {
if v3 == End { 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--; a--;
} }
} }
totr++;
if a == 0 { if a == 0 {
break; break;
} }
} }
n -= 4; nproc--;
} }
// direct send to direct recv // direct send to direct recv
func func
test1(c *chan int, v0 int) test1(c *Chan)
{ {
go send(c, v0); go send(c);
go recv(c, v0); go recv(c);
} }
// direct send to select recv // direct send to select recv
func func
test2() test2(c int)
{ {
go send(c0, 100); ca := mkchan(c,4);
go send(c1, 200);
go send(c2, 300); go send(ca[0]);
go send(c3, 400); go send(ca[1]);
go selrecv(); 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 // select send to direct recv
func 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)
{
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)
{ {
go recv(c0, 100); ca := mkchan(c,12);
go recv(c1, 200);
go recv(c2, 300); go send(ca[4]);
go recv(c3, 400); go send(ca[5]);
go selsend(); 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 // wait for outstanding tests to finish
...@@ -228,28 +260,35 @@ func ...@@ -228,28 +260,35 @@ func
wait() wait()
{ {
sys.gosched(); sys.gosched();
for n != 0 { for nproc != 0 {
sys.gosched(); sys.gosched();
} }
} }
// run all tests with specified buffer size // run all tests with specified buffer size
func func
tests(c uint) tests(c int)
{ {
mkchan(c); ca := mkchan(c,4);
test1(c0, 100); test1(ca[0]);
test1(c1, 200); test1(ca[1]);
test1(c2, 300); test1(ca[2]);
test1(c3, 400); test1(ca[3]);
wait();
test2(c);
wait();
test3(c);
wait();
test4(c);
wait(); wait();
mkchan(c); test5(c);
test2();
wait(); wait();
mkchan(c); test6(c);
test3();
wait(); wait();
} }
...@@ -257,13 +296,20 @@ tests(c uint) ...@@ -257,13 +296,20 @@ tests(c uint)
func func
main() main()
{ {
tests(0); tests(0);
tests(1); tests(1);
tests(10); tests(10);
tests(100); tests(100);
if tots != totr || tots != 3648 { t := 4 // buffer sizes
print("tots=", tots, " totr=", totr, "\n"); * ( 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(1);
} }
sys.exit(0); sys.exit(0);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment