Skip to content

Commit ae2dfcc

Browse files
prattmicheschi
authored andcommitted
[release-branch.go1.17] 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 #53612. For #50249. Change-Id: Ie49227c9e9210ffbf0aee65f86f2b7b6a2f64638 Reviewed-on: https://go-review.googlesource.com/c/go/+/414518 TryBot-Result: Gopher Robot <[email protected]> Reviewed-by: Cherry Mui <[email protected]> Run-TryBot: Michael Pratt <[email protected]> (cherry picked from commit 20760cf) Reviewed-on: https://go-review.googlesource.com/c/go/+/415197
1 parent fc07039 commit ae2dfcc

File tree

1 file changed

+23
-5
lines changed

1 file changed

+23
-5
lines changed

src/runtime/syscall_windows.go

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,30 @@ import (
1212

1313
// cbs stores all registered Go callbacks.
1414
var cbs struct {
15-
lock mutex
15+
lock mutex // use cbsLock / cbsUnlock for race instrumentation.
1616
ctxt [cb_max]winCallback
1717
index map[winCallbackKey]int
1818
n int
1919
}
2020

21+
func cbsLock() {
22+
lock(&cbs.lock)
23+
// compileCallback is used by goenvs prior to completion of schedinit.
24+
// raceacquire involves a racecallback to get the proc, which is not
25+
// safe prior to scheduler initialization. Thus avoid instrumentation
26+
// until then.
27+
if raceenabled && mainStarted {
28+
raceacquire(unsafe.Pointer(&cbs.lock))
29+
}
30+
}
31+
32+
func cbsUnlock() {
33+
if raceenabled && mainStarted {
34+
racerelease(unsafe.Pointer(&cbs.lock))
35+
}
36+
unlock(&cbs.lock)
37+
}
38+
2139
// winCallback records information about a registered Go callback.
2240
type winCallback struct {
2341
fn *funcval // Go function
@@ -302,11 +320,11 @@ func compileCallback(fn eface, cdecl bool) (code uintptr) {
302320

303321
key := winCallbackKey{(*funcval)(fn.data), cdecl}
304322

305-
lock(&cbs.lock) // We don't unlock this in a defer because this is used from the system stack.
323+
cbsLock()
306324

307325
// Check if this callback is already registered.
308326
if n, ok := cbs.index[key]; ok {
309-
unlock(&cbs.lock)
327+
cbsUnlock()
310328
return callbackasmAddr(n)
311329
}
312330

@@ -316,15 +334,15 @@ func compileCallback(fn eface, cdecl bool) (code uintptr) {
316334
}
317335
n := cbs.n
318336
if n >= len(cbs.ctxt) {
319-
unlock(&cbs.lock)
337+
cbsUnlock()
320338
throw("too many callback functions")
321339
}
322340
c := winCallback{key.fn, retPop, abiMap}
323341
cbs.ctxt[n] = c
324342
cbs.index[key] = n
325343
cbs.n++
326344

327-
unlock(&cbs.lock)
345+
cbsUnlock()
328346
return callbackasmAddr(n)
329347
}
330348

0 commit comments

Comments
 (0)