]> Cypherpunks repositories - gostls13.git/commitdiff
runtime: add race annotations to cbs.lock
authorMichael Pratt <mpratt@google.com>
Tue, 28 Jun 2022 20:32:50 +0000 (16:32 -0400)
committerMichael Pratt <mpratt@google.com>
Wed, 29 Jun 2022 20:12:49 +0000 (20:12 +0000)
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>

src/runtime/syscall_windows.go

index e42d71ad65e2852864f5f6d8424fb88e3ced1b91..76036ad098e372af3cdd660cdee6fdbc6427730f 100644 (file)
@@ -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)
 }