Skip to content

Commit ed8cc5c

Browse files
committed
runtime: fix race instrumentation of append
typedslicecopy is another write barrier that is not understood by racewalk. It seems quite complex to handle it in the compiler, so instead just instrument it in runtime. Update #9796 Change-Id: I0eb6abf3a2cd2491a338fab5f7da22f01bf7e89b Reviewed-on: https://go-review.googlesource.com/4370 Reviewed-by: Russ Cox <[email protected]>
1 parent c1bbf0a commit ed8cc5c

File tree

3 files changed

+103
-0
lines changed

3 files changed

+103
-0
lines changed

src/cmd/gc/racewalk.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,7 @@ racewalknode(Node **np, NodeList **init, int wr, int skip)
205205
case OCALLFUNC:
206206
// Instrument dst argument of runtime.writebarrier* calls
207207
// as we do not instrument runtime code.
208+
// typedslicecopy is instrumented in runtime.
208209
if(n->left->sym != S && n->left->sym->pkg == runtimepkg &&
209210
(strncmp(n->left->sym->name, "writebarrier", 12) == 0 || strcmp(n->left->sym->name, "typedmemmove") == 0)) {
210211
// Find the dst argument.

src/runtime/mbarrier.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -328,6 +328,13 @@ func typedslicecopy(typ *_type, dst, src slice) int {
328328
dstp := unsafe.Pointer(dst.array)
329329
srcp := unsafe.Pointer(src.array)
330330

331+
if raceenabled {
332+
callerpc := getcallerpc(unsafe.Pointer(&typ))
333+
pc := funcPC(slicecopy)
334+
racewriterangepc(dstp, uintptr(n)*typ.size, callerpc, pc)
335+
racereadrangepc(srcp, uintptr(n)*typ.size, callerpc, pc)
336+
}
337+
331338
if !needwb() {
332339
memmove(dstp, srcp, uintptr(n)*typ.size)
333340
return int(n)

src/runtime/race/testdata/slice_test.go

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,54 @@ func TestNoRaceSliceCopyRead(t *testing.T) {
144144
<-ch
145145
}
146146

147+
func TestRacePointerSliceCopyRead(t *testing.T) {
148+
ch := make(chan bool, 1)
149+
a := make([]*int, 10)
150+
b := make([]*int, 10)
151+
go func() {
152+
_ = a[5]
153+
ch <- true
154+
}()
155+
copy(a, b)
156+
<-ch
157+
}
158+
159+
func TestNoRacePointerSliceWriteCopy(t *testing.T) {
160+
ch := make(chan bool, 1)
161+
a := make([]*int, 10)
162+
b := make([]*int, 10)
163+
go func() {
164+
a[5] = new(int)
165+
ch <- true
166+
}()
167+
copy(a[:5], b[:5])
168+
<-ch
169+
}
170+
171+
func TestRacePointerSliceCopyWrite2(t *testing.T) {
172+
ch := make(chan bool, 1)
173+
a := make([]*int, 10)
174+
b := make([]*int, 10)
175+
go func() {
176+
b[5] = new(int)
177+
ch <- true
178+
}()
179+
copy(a, b)
180+
<-ch
181+
}
182+
183+
func TestNoRacePointerSliceCopyRead(t *testing.T) {
184+
ch := make(chan bool, 1)
185+
a := make([]*int, 10)
186+
b := make([]*int, 10)
187+
go func() {
188+
_ = b[5]
189+
ch <- true
190+
}()
191+
copy(a, b)
192+
<-ch
193+
}
194+
147195
func TestNoRaceSliceWriteSlice2(t *testing.T) {
148196
ch := make(chan bool, 1)
149197
a := make([]float64, 10)
@@ -395,6 +443,53 @@ func TestRaceSliceAppendString(t *testing.T) {
395443
<-c
396444
}
397445

446+
func TestRacePointerSliceAppend(t *testing.T) {
447+
c := make(chan bool, 1)
448+
s := make([]*int, 10, 20)
449+
go func() {
450+
_ = append(s, new(int))
451+
c <- true
452+
}()
453+
_ = append(s, new(int))
454+
<-c
455+
}
456+
457+
func TestRacePointerSliceAppendWrite(t *testing.T) {
458+
c := make(chan bool, 1)
459+
s := make([]*int, 10)
460+
go func() {
461+
_ = append(s, new(int))
462+
c <- true
463+
}()
464+
s[0] = new(int)
465+
<-c
466+
}
467+
468+
func TestRacePointerSliceAppendSlice(t *testing.T) {
469+
c := make(chan bool, 1)
470+
s := make([]*int, 10)
471+
go func() {
472+
s2 := make([]*int, 10)
473+
_ = append(s, s2...)
474+
c <- true
475+
}()
476+
s[0] = new(int)
477+
<-c
478+
}
479+
480+
func TestRacePointerSliceAppendSlice2(t *testing.T) {
481+
c := make(chan bool, 1)
482+
s := make([]*int, 10)
483+
s2foobar := make([]*int, 10)
484+
go func() {
485+
_ = append(s, s2foobar...)
486+
c <- true
487+
}()
488+
println("WRITE:", &s2foobar[5])
489+
s2foobar[5] = nil
490+
<-c
491+
}
492+
398493
func TestNoRaceSliceIndexAccess(t *testing.T) {
399494
c := make(chan bool, 1)
400495
s := make([]int, 10)

0 commit comments

Comments
 (0)