Commit 578667f4 authored by Michael Anthony Knyszek's avatar Michael Anthony Knyszek Committed by Michael Knyszek

runtime: enable preemption of mark termination goroutine

A mark worker goroutine may attempt to preempt the mark termination
goroutine to scan its stack while the mark termination goroutine is
trying to preempt that worker to flush its work buffer, in rare
cases.

This change makes it so that, like a worker goroutine, the mark
termination goroutine stack is preemptible while it is on the
system stack, attempting to preempt others.

Fixes #28695.

Change-Id: I23bbb191f4fdad293e8a70befd51c9175f8a1171
Reviewed-on: https://go-review.googlesource.com/c/153077Reviewed-by: 's avatarRick Hudson <rlh@golang.org>
Reviewed-by: 's avatarAustin Clements <austin@google.com>
parent f604b6ce
......@@ -1417,6 +1417,12 @@ top:
// Flush all local buffers and collect flushedWork flags.
gcMarkDoneFlushed = 0
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).
casgstatus(gp, _Grunning, _Gwaiting)
forEachP(func(_p_ *p) {
// Flush the write barrier buffer, since this may add
// work to the gcWork.
......@@ -1449,6 +1455,7 @@ top:
_p_.gcw.pauseGen = gcWorkPauseGen
}
})
casgstatus(gp, _Gwaiting, _Grunning)
})
if gcMarkDoneFlushed != 0 {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment