Skip to content

Commit f00e947

Browse files
ianlancetaylorgopherbot
authored andcommitted
runtime: add raceFiniLock to lock ranking
Also preserve the PC/SP in reentersyscall when doing lock ranking. The test is TestDestructorCallbackRace with the staticlockranking experiment enabled. For #59711 Change-Id: I87ac1d121ec0d399de369666834891ab9e7d11b0 Reviewed-on: https://go-review.googlesource.com/c/go/+/487955 Run-TryBot: Ian Lance Taylor <[email protected]> Reviewed-by: Michael Knyszek <[email protected]> TryBot-Result: Gopher Robot <[email protected]> Reviewed-by: Ian Lance Taylor <[email protected]> Auto-Submit: Ian Lance Taylor <[email protected]> Run-TryBot: Ian Lance Taylor <[email protected]>
1 parent 3f987ae commit f00e947

File tree

6 files changed

+23
-4
lines changed

6 files changed

+23
-4
lines changed

src/runtime/lockrank.go

Lines changed: 3 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/runtime/lockrank_off.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66

77
package runtime
88

9+
const staticLockRanking = false
10+
911
// // lockRankStruct is embedded in mutex, but is empty when staticklockranking is
1012
// disabled (the default)
1113
type lockRankStruct struct {

src/runtime/lockrank_on.go

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ import (
1111
"unsafe"
1212
)
1313

14+
const staticLockRanking = true
15+
1416
// worldIsStopped is accessed atomically to track world-stops. 1 == world
1517
// stopped.
1618
var worldIsStopped atomic.Uint32
@@ -49,7 +51,7 @@ func getLockRank(l *mutex) lockRank {
4951
// split on entry to lock2() would record stack split locks as taken after l,
5052
// even though l is not actually locked yet.
5153
func lockWithRank(l *mutex, rank lockRank) {
52-
if l == &debuglock || l == &paniclk {
54+
if l == &debuglock || l == &paniclk || l == &raceFiniLock {
5355
// debuglock is only used for println/printlock(). Don't do lock
5456
// rank recording for it, since print/println are used when
5557
// printing out a lock ordering problem below.
@@ -59,6 +61,10 @@ func lockWithRank(l *mutex, rank lockRank) {
5961
// lock ordering problem. Additionally, paniclk may be taken
6062
// after effectively any lock (anywhere we might panic), which
6163
// the partial order doesn't cover.
64+
//
65+
// raceFiniLock is held while exiting when running
66+
// the race detector. Don't do lock rank recording for it,
67+
// since we are exiting.
6268
lock2(l)
6369
return
6470
}
@@ -159,7 +165,7 @@ func checkRanks(gp *g, prevRank, rank lockRank) {
159165

160166
// See comment on lockWithRank regarding stack splitting.
161167
func unlockWithRank(l *mutex) {
162-
if l == &debuglock || l == &paniclk {
168+
if l == &debuglock || l == &paniclk || l == &raceFiniLock {
163169
// See comment at beginning of lockWithRank.
164170
unlock2(l)
165171
return

src/runtime/mklockrank.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,8 @@ NONE < panic;
179179
# deadlock is not acquired while holding panic, but it also needs to be
180180
# below all other locks.
181181
panic < deadlock;
182+
# raceFini is only held while exiting.
183+
panic < raceFini;
182184
`
183185

184186
// cyclicRanks lists lock ranks that allow multiple locks of the same

src/runtime/proc.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,7 @@ var (
115115
g0 g
116116
mcache0 *mcache
117117
raceprocctx0 uintptr
118+
raceFiniLock mutex
118119
)
119120

120121
// This slice records the initializing tasks that need to be
@@ -3773,6 +3774,11 @@ func reentersyscall(pc, sp uintptr) {
37733774
gp.syscallsp = sp
37743775
gp.syscallpc = pc
37753776
casgstatus(gp, _Grunning, _Gsyscall)
3777+
if staticLockRanking {
3778+
// When doing static lock ranking casgstatus can call
3779+
// systemstack which clobbers g.sched.
3780+
save(pc, sp)
3781+
}
37763782
if gp.syscallsp < gp.stack.lo || gp.stack.hi < gp.syscallsp {
37773783
systemstack(func() {
37783784
print("entersyscall inconsistent ", hex(gp.syscallsp), " [", hex(gp.stack.lo), ",", hex(gp.stack.hi), "]\n")

src/runtime/race.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -355,6 +355,8 @@ func isvalidaddr(addr unsafe.Pointer) bool {
355355

356356
//go:nosplit
357357
func raceinit() (gctx, pctx uintptr) {
358+
lockInit(&raceFiniLock, lockRankRaceFini)
359+
358360
// On most machines, cgo is required to initialize libc, which is used by race runtime.
359361
if !iscgo && GOOS != "darwin" {
360362
throw("raceinit: race build must use cgo")
@@ -397,8 +399,6 @@ func raceinit() (gctx, pctx uintptr) {
397399
return
398400
}
399401

400-
var raceFiniLock mutex
401-
402402
//go:nosplit
403403
func racefini() {
404404
// racefini() can only be called once to avoid races.

0 commit comments

Comments
 (0)