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:
parent
e6c0546c54
commit
20760cff00
@ -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)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user