]> Cypherpunks repositories - gostls13.git/commitdiff
runtime: fix profile handling of labels for race detector
authorRuss Cox <rsc@golang.org>
Fri, 28 Apr 2017 16:45:46 +0000 (12:45 -0400)
committerRuss Cox <rsc@golang.org>
Fri, 28 Apr 2017 17:37:46 +0000 (17:37 +0000)
If g1 sets its labels and then they are copied into a profile buffer
and then g2 reads the profile buffer and inspects the labels,
the race detector must understand that g1's recording of the labels
happens before g2's use of the labels. Make that so.

Fixes race test failure in CL 39613.

Change-Id: Id7cda1c2aac6f8eef49213b5ca414f7154b4acfa
Reviewed-on: https://go-review.googlesource.com/42111
Run-TryBot: Russ Cox <rsc@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Michael Matloob <matloob@golang.org>
src/runtime/profbuf.go
src/runtime/proflabel.go

index 605d8d34a448d77a245063c76f1b3a012d88203b..2719238bc172fa7c6588696f534abc3a889b9b11 100644 (file)
@@ -544,5 +544,18 @@ Read:
        // Remember how much we returned, to commit read on next call.
        b.rNext = br.addCountsAndClearFlags(skip+di, ti)
 
+       if raceenabled {
+               // Match racewritepc in runtime_setProfLabel,
+               // so that the setting of the labels in runtime_setProfLabel
+               // is treated as happening before any use of the labels
+               // by our caller. The synchronization on labelSync itself is a fiction
+               // for the race detector. The actual synchronization is handled
+               // by the fact that the signal handler only reads from the current
+               // goroutine and uses atomics to write the updated queue indices,
+               // and then the read-out from the signal handler buffer uses
+               // atomics to read those queue indices.
+               raceacquire(unsafe.Pointer(&labelSync))
+       }
+
        return data[:di], tags[:ti], false
 }
index 9742afafd77dd73d9d3667a59cdf3f097ff09ce5..1b41a8a16e0f637a61487d0bee56985909b85932 100644 (file)
@@ -6,8 +6,16 @@ package runtime
 
 import "unsafe"
 
+var labelSync uintptr
+
 //go:linkname runtime_setProfLabel runtime/pprof.runtime_setProfLabel
 func runtime_setProfLabel(labels unsafe.Pointer) {
+       // Introduce race edge for read-back via profile.
+       // This would more properly use &getg().labels as the sync address,
+       // but we do the read in a signal handler and can't call the race runtime then.
+       if raceenabled {
+               racerelease(unsafe.Pointer(&labelSync))
+       }
        getg().labels = labels
 }