1
0
mirror of https://github.com/golang/go synced 2024-11-21 21:44:40 -07:00

Add explicit locking.

Since gcco runs goroutines in independent threads, it needs
locking for the global variables.  This shows up when I use
ordinary increments rather than locked increments for var++.

R=ken2, ken3
CC=golang-dev
https://golang.org/cl/190074
This commit is contained in:
Ian Lance Taylor 2010-01-19 21:09:58 -08:00
parent dfc0ed9559
commit b2beb8abf0

View File

@ -8,6 +8,7 @@ package main
import "os" import "os"
import "runtime" import "runtime"
import "sync"
var randx int; var randx int;
@ -28,9 +29,11 @@ type Chan struct {
var var
( (
nproc int; nproc int;
nprocLock sync.Mutex;
cval int; cval int;
end int = 10000; end int = 10000;
totr,tots int; totr,tots int;
totLock sync.Mutex;
nc *Chan; nc *Chan;
) )
@ -39,6 +42,14 @@ init() {
nc = new(Chan); nc = new(Chan);
} }
func changeNproc(adjust int) int {
nprocLock.Lock()
nproc += adjust
ret := nproc
nprocLock.Unlock()
return ret
}
func func
mkchan(c,n int) []*Chan { mkchan(c,n int) []*Chan {
ca := make([]*Chan, n); ca := make([]*Chan, n);
@ -67,7 +78,9 @@ expect(v, v0 int) (newv int) {
func (c *Chan) send() bool { func (c *Chan) send() bool {
// print("send ", c.sv, "\n"); // print("send ", c.sv, "\n");
totLock.Lock();
tots++; tots++;
totLock.Unlock();
c.sv = expect(c.sv, c.sv); c.sv = expect(c.sv, c.sv);
if c.sv == end { if c.sv == end {
c.sc = nil; c.sc = nil;
@ -78,7 +91,6 @@ func (c *Chan) send() bool {
func func
send(c *Chan) { send(c *Chan) {
nproc++; // total goroutines running
for { for {
for r:=nrand(10); r>=0; r-- { for r:=nrand(10); r>=0; r-- {
runtime.Gosched(); runtime.Gosched();
@ -88,12 +100,14 @@ send(c *Chan) {
break; break;
} }
} }
nproc--; changeNproc(-1)
} }
func (c *Chan) recv(v int) bool { func (c *Chan) recv(v int) bool {
// print("recv ", v, "\n"); // print("recv ", v, "\n");
totLock.Lock();
totr++; totr++;
totLock.Unlock();
c.rv = expect(c.rv, v); c.rv = expect(c.rv, v);
if c.rv == end { if c.rv == end {
c.rc = nil; c.rc = nil;
@ -106,7 +120,6 @@ func
recv(c *Chan) { recv(c *Chan) {
var v int; var v int;
nproc++; // total goroutines running
for { for {
for r:=nrand(10); r>=0; r-- { for r:=nrand(10); r>=0; r-- {
runtime.Gosched(); runtime.Gosched();
@ -116,14 +129,13 @@ recv(c *Chan) {
break; break;
} }
} }
nproc--; changeNproc(-1);
} }
func func
sel(r0,r1,r2,r3, s0,s1,s2,s3 *Chan) { sel(r0,r1,r2,r3, s0,s1,s2,s3 *Chan) {
var v int; var v int;
nproc++; // total goroutines running
a := 0; // local chans running a := 0; // local chans running
if r0.rc != nil { a++ } if r0.rc != nil { a++ }
@ -178,12 +190,13 @@ sel(r0,r1,r2,r3, s0,s1,s2,s3 *Chan) {
break; break;
} }
} }
nproc--; changeNproc(-1);
} }
// direct send to direct recv // direct send to direct recv
func func
test1(c *Chan) { test1(c *Chan) {
changeNproc(2)
go send(c); go send(c);
go recv(c); go recv(c);
} }
@ -193,11 +206,13 @@ func
test2(c int) { test2(c int) {
ca := mkchan(c,4); ca := mkchan(c,4);
changeNproc(4)
go send(ca[0]); go send(ca[0]);
go send(ca[1]); go send(ca[1]);
go send(ca[2]); go send(ca[2]);
go send(ca[3]); go send(ca[3]);
changeNproc(1)
go sel(ca[0],ca[1],ca[2],ca[3], nc,nc,nc,nc); go sel(ca[0],ca[1],ca[2],ca[3], nc,nc,nc,nc);
} }
@ -206,11 +221,13 @@ func
test3(c int) { test3(c int) {
ca := mkchan(c,4); ca := mkchan(c,4);
changeNproc(4)
go recv(ca[0]); go recv(ca[0]);
go recv(ca[1]); go recv(ca[1]);
go recv(ca[2]); go recv(ca[2]);
go recv(ca[3]); go recv(ca[3]);
changeNproc(1)
go sel(nc,nc,nc,nc, ca[0],ca[1],ca[2],ca[3]); go sel(nc,nc,nc,nc, ca[0],ca[1],ca[2],ca[3]);
} }
@ -219,6 +236,7 @@ func
test4(c int) { test4(c int) {
ca := mkchan(c,4); ca := mkchan(c,4);
changeNproc(2)
go sel(nc,nc,nc,nc, ca[0],ca[1],ca[2],ca[3]); 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); go sel(ca[0],ca[1],ca[2],ca[3], nc,nc,nc,nc);
} }
@ -227,6 +245,7 @@ func
test5(c int) { test5(c int) {
ca := mkchan(c,8); ca := mkchan(c,8);
changeNproc(2)
go sel(ca[4],ca[5],ca[6],ca[7], ca[0],ca[1],ca[2],ca[3]); 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]); go sel(ca[0],ca[1],ca[2],ca[3], ca[4],ca[5],ca[6],ca[7]);
} }
@ -235,16 +254,19 @@ func
test6(c int) { test6(c int) {
ca := mkchan(c,12); ca := mkchan(c,12);
changeNproc(4)
go send(ca[4]); go send(ca[4]);
go send(ca[5]); go send(ca[5]);
go send(ca[6]); go send(ca[6]);
go send(ca[7]); go send(ca[7]);
changeNproc(4)
go recv(ca[8]); go recv(ca[8]);
go recv(ca[9]); go recv(ca[9]);
go recv(ca[10]); go recv(ca[10]);
go recv(ca[11]); go recv(ca[11]);
changeNproc(2)
go sel(ca[4],ca[5],ca[6],ca[7], ca[0],ca[1],ca[2],ca[3]); 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]); go sel(ca[0],ca[1],ca[2],ca[3], ca[8],ca[9],ca[10],ca[11]);
} }
@ -253,7 +275,7 @@ test6(c int) {
func func
wait() { wait() {
runtime.Gosched(); runtime.Gosched();
for nproc != 0 { for changeNproc(0) != 0 {
runtime.Gosched(); runtime.Gosched();
} }
} }