diff options
Diffstat (limited to 'src/runtime/proc.go')
| -rw-r--r-- | src/runtime/proc.go | 29 |
1 files changed, 27 insertions, 2 deletions
diff --git a/src/runtime/proc.go b/src/runtime/proc.go index ae2562a5b7..159c19caf3 100644 --- a/src/runtime/proc.go +++ b/src/runtime/proc.go @@ -1820,10 +1820,35 @@ found: // fn will run on every CPU executing Go code, but it acts as a global // memory barrier. GC uses this as a "ragged barrier." // -// The caller must hold worldsema. +// The caller must hold worldsema. fn must not refer to any +// part of the current goroutine's stack, since the GC may move it. +func forEachP(reason waitReason, fn func(*p)) { + systemstack(func() { + gp := getg().m.curg + // Mark the user stack as preemptible so that it may be scanned. + // Otherwise, our attempt to force all P's to a safepoint could + // result in a deadlock as we attempt to preempt a worker that's + // trying to preempt us (e.g. for a stack scan). + // + // N.B. The execution tracer is not aware of this status + // transition and handles it specially based on the + // wait reason. + casGToWaiting(gp, _Grunning, reason) + forEachPInternal(fn) + casgstatus(gp, _Gwaiting, _Grunning) + }) +} + +// forEachPInternal calls fn(p) for every P p when p reaches a GC safe point. +// It is the internal implementation of forEachP. +// +// The caller must hold worldsema and either must ensure that a GC is not +// running (otherwise this may deadlock with the GC trying to preempt this P) +// or it must leave its goroutine in a preemptible state before it switches +// to the systemstack. Due to these restrictions, prefer forEachP when possible. // //go:systemstack -func forEachP(fn func(*p)) { +func forEachPInternal(fn func(*p)) { mp := acquirem() pp := getg().m.p.ptr() |
