// sched.stopwait to in order to request that all Gs permanently stop.
const freezeStopWait = 0x7fffffff
+// freezing is set to non-zero if the runtime is trying to freeze the
+// world.
+var freezing uint32
+
// Similar to stopTheWorld but best-effort and can be called several times.
// There is no reverse operation, used during crashing.
// This function must not lock any mutexes.
func freezetheworld() {
+ atomic.Store(&freezing, 1)
// stopwait and preemption requests can be lost
// due to races with concurrently executing threads,
// so try several times
preemptall()
}
}
+
+ // sanity checks
+ bad := ""
if sched.stopwait != 0 {
- throw("stopTheWorld: not stopped")
- }
- for i := 0; i < int(gomaxprocs); i++ {
- p := allp[i]
- if p.status != _Pgcstop {
- throw("stopTheWorld: not stopped")
+ bad = "stopTheWorld: not stopped (stopwait != 0)"
+ } else {
+ for i := 0; i < int(gomaxprocs); i++ {
+ p := allp[i]
+ if p.status != _Pgcstop {
+ bad = "stopTheWorld: not stopped (status != _Pgcstop)"
+ }
}
}
+ if atomic.Load(&freezing) != 0 {
+ // Some other thread is panicking. This can cause the
+ // sanity checks above to fail if the panic happens in
+ // the signal handler on a stopped thread. Either way,
+ // we should halt this thread.
+ lock(&deadlock)
+ lock(&deadlock)
+ }
+ if bad != "" {
+ throw(bad)
+ }
}
func mhelpgc() {