})
}
-//go:systemstack
+// nosplit to ensure it can be called in as many contexts as possible.
+//go:nosplit
func printHeldLocks(gp *g) {
if gp.m.locksHeldLen == 0 {
println("<none>")
//go:nosplit
func acquireLockRank(rank lockRank) {
gp := getg()
- // Log the new class.
+ // Log the new class. See comment on lockWithRank.
systemstack(func() {
i := gp.m.locksHeldLen
if i >= len(gp.m.locksHeld) {
})
}
-//go:systemstack
+// nosplit to ensure it can be called in as many contexts as possible.
+//go:nosplit
func checkLockHeld(gp *g, l *mutex) bool {
for i := gp.m.locksHeldLen - 1; i >= 0; i-- {
if gp.m.locksHeld[i].lockAddr == uintptr(unsafe.Pointer(l)) {
func assertLockHeld(l *mutex) {
gp := getg()
+ held := checkLockHeld(gp, l)
+ if held {
+ return
+ }
+
+ // Crash from system stack to avoid splits that may cause
+ // additional issues.
systemstack(func() {
- held := checkLockHeld(gp, l)
- if !held {
- printlock()
- print("caller requires lock ", l, " (rank ", l.rank.String(), "), holding:\n")
- printHeldLocks(gp)
- throw("not holding required lock!")
- }
+ printlock()
+ print("caller requires lock ", l, " (rank ", l.rank.String(), "), holding:\n")
+ printHeldLocks(gp)
+ throw("not holding required lock!")
})
}
func assertRankHeld(r lockRank) {
gp := getg()
- systemstack(func() {
- for i := gp.m.locksHeldLen - 1; i >= 0; i-- {
- if gp.m.locksHeld[i].rank == r {
- return
- }
+ for i := gp.m.locksHeldLen - 1; i >= 0; i-- {
+ if gp.m.locksHeld[i].rank == r {
+ return
}
+ }
+ // Crash from system stack to avoid splits that may cause
+ // additional issues.
+ systemstack(func() {
printlock()
print("caller requires lock with rank ", r.String(), "), holding:\n")
printHeldLocks(gp)
//go:nosplit
func worldStopped() {
if stopped := atomic.Xadd(&worldIsStopped, 1); stopped != 1 {
- print("world stop count=", stopped, "\n")
- throw("recursive world stop")
+ systemstack(func() {
+ print("world stop count=", stopped, "\n")
+ throw("recursive world stop")
+ })
}
}
//go:nosplit
func worldStarted() {
if stopped := atomic.Xadd(&worldIsStopped, -1); stopped != 0 {
- print("world stop count=", stopped, "\n")
- throw("released non-stopped world stop")
+ systemstack(func() {
+ print("world stop count=", stopped, "\n")
+ throw("released non-stopped world stop")
+ })
}
}
func checkWorldStopped() bool {
stopped := atomic.Load(&worldIsStopped)
if stopped > 1 {
- print("inconsistent world stop count=", stopped, "\n")
- throw("inconsistent world stop count")
+ systemstack(func() {
+ print("inconsistent world stop count=", stopped, "\n")
+ throw("inconsistent world stop count")
+ })
}
return stopped == 1
}
gp := getg()
+ held := checkLockHeld(gp, l)
+ if held {
+ return
+ }
+
+ // Crash from system stack to avoid splits that may cause
+ // additional issues.
systemstack(func() {
- held := checkLockHeld(gp, l)
- if !held {
- printlock()
- print("caller requires world stop or lock ", l, " (rank ", l.rank.String(), "), holding:\n")
- println("<no world stop>")
- printHeldLocks(gp)
- throw("no world stop or required lock!")
- }
+ printlock()
+ print("caller requires world stop or lock ", l, " (rank ", l.rank.String(), "), holding:\n")
+ println("<no world stop>")
+ printHeldLocks(gp)
+ throw("no world stop or required lock!")
})
}