1
0
mirror of https://github.com/golang/go synced 2024-11-16 20:14:48 -07:00

runtime: add race annotations to cbs.lock

cbs.lock protects a map. The map implementation is race instrumented
regardless of which package is it called from.

lock/unlock are not automatically race instrumented, so we can trigger
race false positives without manually annotating our lock acquire and
release.

compileCallback is used during initialization before the P is available,
at which point raceacquire will crash during a racecallback to get the
race proc. Thus we skip instrumentation until scheduler initialization
is complete.

Fixes #50249.

Change-Id: Ie49227c9e9210ffbf0aee65f86f2b7b6a2f64638
Reviewed-on: https://go-review.googlesource.com/c/go/+/414518
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Cherry Mui <cherryyz@google.com>
Run-TryBot: Michael Pratt <mpratt@google.com>
This commit is contained in:
Michael Pratt 2022-06-28 16:32:50 -04:00
parent e6c0546c54
commit 20760cff00

View File

@ -12,12 +12,30 @@ import (
// cbs stores all registered Go callbacks. // cbs stores all registered Go callbacks.
var cbs struct { var cbs struct {
lock mutex lock mutex // use cbsLock / cbsUnlock for race instrumentation.
ctxt [cb_max]winCallback ctxt [cb_max]winCallback
index map[winCallbackKey]int index map[winCallbackKey]int
n int n int
} }
func cbsLock() {
lock(&cbs.lock)
// compileCallback is used by goenvs prior to completion of schedinit.
// raceacquire involves a racecallback to get the proc, which is not
// safe prior to scheduler initialization. Thus avoid instrumentation
// until then.
if raceenabled && mainStarted {
raceacquire(unsafe.Pointer(&cbs.lock))
}
}
func cbsUnlock() {
if raceenabled && mainStarted {
racerelease(unsafe.Pointer(&cbs.lock))
}
unlock(&cbs.lock)
}
// winCallback records information about a registered Go callback. // winCallback records information about a registered Go callback.
type winCallback struct { type winCallback struct {
fn *funcval // Go function fn *funcval // Go function
@ -302,11 +320,11 @@ func compileCallback(fn eface, cdecl bool) (code uintptr) {
key := winCallbackKey{(*funcval)(fn.data), cdecl} key := winCallbackKey{(*funcval)(fn.data), cdecl}
lock(&cbs.lock) // We don't unlock this in a defer because this is used from the system stack. cbsLock()
// Check if this callback is already registered. // Check if this callback is already registered.
if n, ok := cbs.index[key]; ok { if n, ok := cbs.index[key]; ok {
unlock(&cbs.lock) cbsUnlock()
return callbackasmAddr(n) return callbackasmAddr(n)
} }
@ -316,7 +334,7 @@ func compileCallback(fn eface, cdecl bool) (code uintptr) {
} }
n := cbs.n n := cbs.n
if n >= len(cbs.ctxt) { if n >= len(cbs.ctxt) {
unlock(&cbs.lock) cbsUnlock()
throw("too many callback functions") throw("too many callback functions")
} }
c := winCallback{key.fn, retPop, abiMap} c := winCallback{key.fn, retPop, abiMap}
@ -324,7 +342,7 @@ func compileCallback(fn eface, cdecl bool) (code uintptr) {
cbs.index[key] = n cbs.index[key] = n
cbs.n++ cbs.n++
unlock(&cbs.lock) cbsUnlock()
return callbackasmAddr(n) return callbackasmAddr(n)
} }