aboutsummaryrefslogtreecommitdiff
path: root/src/runtime/proc.go
diff options
context:
space:
mode:
Diffstat (limited to 'src/runtime/proc.go')
-rw-r--r--src/runtime/proc.go20
1 files changed, 12 insertions, 8 deletions
diff --git a/src/runtime/proc.go b/src/runtime/proc.go
index 96d44efdddf..4aeb66c92d4 100644
--- a/src/runtime/proc.go
+++ b/src/runtime/proc.go
@@ -2629,9 +2629,8 @@ top:
// We have nothing to do.
//
// If we're in the GC mark phase, can safely scan and blacken objects,
- // and have work to do, run idle-time marking rather than give up the
- // P.
- if gcBlackenEnabled != 0 && gcMarkWorkAvailable(_p_) {
+ // and have work to do, run idle-time marking rather than give up the P.
+ if gcBlackenEnabled != 0 && gcMarkWorkAvailable(_p_) && gcController.addIdleMarkWorker() {
node := (*gcBgMarkWorkerNode)(gcBgMarkWorkerPool.pop())
if node != nil {
_p_.gcMarkWorkerMode = gcMarkWorkerIdleMode
@@ -2642,6 +2641,7 @@ top:
}
return gp, false
}
+ gcController.removeIdleMarkWorker()
}
// wasm only:
@@ -2959,8 +2959,12 @@ func checkTimersNoP(allpSnapshot []*p, timerpMaskSnapshot pMask, pollUntil int64
// returned. The returned P has not been wired yet.
func checkIdleGCNoP() (*p, *g) {
// N.B. Since we have no P, gcBlackenEnabled may change at any time; we
- // must check again after acquiring a P.
- if atomic.Load(&gcBlackenEnabled) == 0 {
+ // must check again after acquiring a P. As an optimization, we also check
+ // if an idle mark worker is needed at all. This is OK here, because if we
+ // observe that one isn't needed, at least one is currently running. Even if
+ // it stops running, its own journey into the scheduler should schedule it
+ // again, if need be (at which point, this check will pass, if relevant).
+ if atomic.Load(&gcBlackenEnabled) == 0 || !gcController.needIdleMarkWorker() {
return nil, nil
}
if !gcMarkWorkAvailable(nil) {
@@ -2991,9 +2995,8 @@ func checkIdleGCNoP() (*p, *g) {
return nil, nil
}
- // Now that we own a P, gcBlackenEnabled can't change (as it requires
- // STW).
- if gcBlackenEnabled == 0 {
+ // Now that we own a P, gcBlackenEnabled can't change (as it requires STW).
+ if gcBlackenEnabled == 0 || !gcController.addIdleMarkWorker() {
pidleput(pp)
unlock(&sched.lock)
return nil, nil
@@ -3003,6 +3006,7 @@ func checkIdleGCNoP() (*p, *g) {
if node == nil {
pidleput(pp)
unlock(&sched.lock)
+ gcController.removeIdleMarkWorker()
return nil, nil
}