diff options
author | Michael Pratt <mpratt@google.com> | 2022-06-28 16:32:50 -0400 |
---|---|---|
committer | Michael Pratt <mpratt@google.com> | 2022-06-29 20:12:49 +0000 |
commit | 20760cff001e9acc05627dfeab42ea50b57920e6 (patch) | |
tree | 94c5c910e52855bd286c49ef3b6995780dedc5cc | |
parent | e6c0546c54f6f3fa7c6cb5002ecc839bc89d5d20 (diff) | |
download | go-20760cff001e9acc05627dfeab42ea50b57920e6.tar.gz go-20760cff001e9acc05627dfeab42ea50b57920e6.zip |
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>
-rw-r--r-- | src/runtime/syscall_windows.go | 28 |
1 files changed, 23 insertions, 5 deletions
diff --git a/src/runtime/syscall_windows.go b/src/runtime/syscall_windows.go index e42d71ad65..76036ad098 100644 --- a/src/runtime/syscall_windows.go +++ b/src/runtime/syscall_windows.go @@ -12,12 +12,30 @@ import ( // cbs stores all registered Go callbacks. var cbs struct { - lock mutex + lock mutex // use cbsLock / cbsUnlock for race instrumentation. ctxt [cb_max]winCallback index map[winCallbackKey]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. type winCallback struct { fn *funcval // Go function @@ -302,11 +320,11 @@ func compileCallback(fn eface, cdecl bool) (code uintptr) { 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. if n, ok := cbs.index[key]; ok { - unlock(&cbs.lock) + cbsUnlock() return callbackasmAddr(n) } @@ -316,7 +334,7 @@ func compileCallback(fn eface, cdecl bool) (code uintptr) { } n := cbs.n if n >= len(cbs.ctxt) { - unlock(&cbs.lock) + cbsUnlock() throw("too many callback functions") } c := winCallback{key.fn, retPop, abiMap} @@ -324,7 +342,7 @@ func compileCallback(fn eface, cdecl bool) (code uintptr) { cbs.index[key] = n cbs.n++ - unlock(&cbs.lock) + cbsUnlock() return callbackasmAddr(n) } |