Commit d89a7383 authored by Dmitriy Vyukov's avatar Dmitriy Vyukov

runtime: support channel-based mutex in race detector

Update channel race annotations to support change in
cl/75130045: doc: allow buffered channel as semaphore without initialization
The new annotations are added only for channels with capacity 1.
Strictly saying it's possible to construct a counter-example that
will produce a false positive with capacity > 1. But it's hardly can
lead to false positives in real programs, at least I would like to see such programs first.
Any additional annotations also increase probability of false negatives,
so I would prefer to add them lazily.

LGTM=rsc
R=golang-codereviews
CC=golang-codereviews, iant, khr, rsc
https://golang.org/cl/76970043
parent f8c35087
...@@ -171,8 +171,11 @@ asynch: ...@@ -171,8 +171,11 @@ asynch:
goto asynch; goto asynch;
} }
if(raceenabled) if(raceenabled) {
if(c->dataqsiz == 1)
runtime·raceacquire(chanbuf(c, c->sendx));
runtime·racerelease(chanbuf(c, c->sendx)); runtime·racerelease(chanbuf(c, c->sendx));
}
c->elemtype->alg->copy(c->elemsize, chanbuf(c, c->sendx), ep); c->elemtype->alg->copy(c->elemsize, chanbuf(c, c->sendx), ep);
if(++c->sendx == c->dataqsiz) if(++c->sendx == c->dataqsiz)
...@@ -299,8 +302,11 @@ asynch: ...@@ -299,8 +302,11 @@ asynch:
goto asynch; goto asynch;
} }
if(raceenabled) if(raceenabled) {
runtime·raceacquire(chanbuf(c, c->recvx)); runtime·raceacquire(chanbuf(c, c->recvx));
if(c->dataqsiz == 1)
runtime·racerelease(chanbuf(c, c->recvx));
}
if(ep != nil) if(ep != nil)
c->elemtype->alg->copy(c->elemsize, ep, chanbuf(c, c->recvx)); c->elemtype->alg->copy(c->elemsize, ep, chanbuf(c, c->recvx));
...@@ -849,6 +855,8 @@ asyncrecv: ...@@ -849,6 +855,8 @@ asyncrecv:
if(cas->sg.elem != nil) if(cas->sg.elem != nil)
runtime·racewriteobjectpc(cas->sg.elem, c->elemtype, cas->pc, chanrecv); runtime·racewriteobjectpc(cas->sg.elem, c->elemtype, cas->pc, chanrecv);
runtime·raceacquire(chanbuf(c, c->recvx)); runtime·raceacquire(chanbuf(c, c->recvx));
if(c->dataqsiz == 1)
runtime·racerelease(chanbuf(c, c->recvx));
} }
if(cas->receivedp != nil) if(cas->receivedp != nil)
*cas->receivedp = true; *cas->receivedp = true;
...@@ -873,6 +881,8 @@ asyncrecv: ...@@ -873,6 +881,8 @@ asyncrecv:
asyncsend: asyncsend:
// can send to buffer // can send to buffer
if(raceenabled) { if(raceenabled) {
if(c->dataqsiz == 1)
runtime·raceacquire(chanbuf(c, c->sendx));
runtime·racerelease(chanbuf(c, c->sendx)); runtime·racerelease(chanbuf(c, c->sendx));
runtime·racereadobjectpc(cas->sg.elem, c->elemtype, cas->pc, chansend); runtime·racereadobjectpc(cas->sg.elem, c->elemtype, cas->pc, chansend);
} }
......
...@@ -568,12 +568,14 @@ func TestRaceChanCloseLen(t *testing.T) { ...@@ -568,12 +568,14 @@ func TestRaceChanCloseLen(t *testing.T) {
} }
func TestRaceChanSameCell(t *testing.T) { func TestRaceChanSameCell(t *testing.T) {
c := make(chan int, 1) c := make(chan int, 2)
v := 0 v := 0
go func() { go func() {
v = 1 v = 1
c <- 42 c <- 42
<-c <-c
c <- 42
<-c
}() }()
time.Sleep(1e7) time.Sleep(1e7)
c <- 43 c <- 43
...@@ -591,3 +593,64 @@ func TestRaceChanCloseSend(t *testing.T) { ...@@ -591,3 +593,64 @@ func TestRaceChanCloseSend(t *testing.T) {
c <- 0 c <- 0
<-compl <-compl
} }
func TestNoRaceChanMutex(t *testing.T) {
done := make(chan struct{})
mtx := make(chan struct{}, 1)
data := 0
go func() {
mtx <- struct{}{}
data = 42
<-mtx
done <- struct{}{}
}()
mtx <- struct{}{}
data = 43
<-mtx
<-done
}
func TestNoRaceSelectMutex(t *testing.T) {
done := make(chan struct{})
mtx := make(chan struct{}, 1)
aux := make(chan bool)
data := 0
go func() {
select {
case mtx <- struct{}{}:
case <-aux:
}
data = 42
select {
case <-mtx:
case <-aux:
}
done <- struct{}{}
}()
select {
case mtx <- struct{}{}:
case <-aux:
}
data = 43
select {
case <-mtx:
case <-aux:
}
<-done
}
func TestRaceChanSem(t *testing.T) {
done := make(chan struct{})
mtx := make(chan struct{}, 2)
data := 0
go func() {
mtx <- struct{}{}
data = 42
<-mtx
done <- struct{}{}
}()
mtx <- struct{}{}
data = 43
<-mtx
<-done
}
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