aboutsummaryrefslogtreecommitdiff
path: root/src/runtime/mgc.go
diff options
context:
space:
mode:
authorMichael Anthony Knyszek <mknyszek@google.com>2021-07-08 21:42:01 +0000
committerMichael Knyszek <mknyszek@google.com>2021-10-29 17:12:47 +0000
commit3aecb3a8f7e1435c76003a20068c0208fd73649a (patch)
tree2862c933092a5dcf54f70bb397bfc0ebfd259ad9 /src/runtime/mgc.go
parentf2885263748364a2a7f4e0d47abd5095699cd39f (diff)
downloadgo-3aecb3a8f7e1435c76003a20068c0208fd73649a.tar.gz
go-3aecb3a8f7e1435c76003a20068c0208fd73649a.zip
runtime: fix sweep termination condition
Currently, there is a chance that the sweep termination condition could flap, causing e.g. runtime.GC to return before all sweep work has not only been drained, but also completed. CL 307915 and CL 307916 attempted to fix this problem, but it is still possible that mheap_.sweepDrained is marked before any outstanding sweepers are accounted for in mheap_.sweepers, leaving a window in which a thread could observe isSweepDone as true before it actually was (and after some time it would revert to false, then true again, depending on the number of outstanding sweepers at that point). This change fixes the sweep termination condition by merging mheap_.sweepers and mheap_.sweepDrained into a single atomic value. This value is updated such that a new potential sweeper will increment the oustanding sweeper count iff there are still outstanding spans to be swept without an outstanding sweeper to pick them up. This design simplifies the sweep termination condition into a single atomic load and comparison and ensures the condition never flaps. Updates #46500. Fixes #45315. Change-Id: I6d69aff156b8d48428c4cc8cfdbf28be346dbf04 Reviewed-on: https://go-review.googlesource.com/c/go/+/333389 Trust: Michael Knyszek <mknyszek@google.com> Run-TryBot: Michael Knyszek <mknyszek@google.com> TryBot-Result: Go Bot <gobot@golang.org> Reviewed-by: Austin Clements <austin@google.com>
Diffstat (limited to 'src/runtime/mgc.go')
-rw-r--r--src/runtime/mgc.go12
1 files changed, 7 insertions, 5 deletions
diff --git a/src/runtime/mgc.go b/src/runtime/mgc.go
index 429b907322..e7c023919c 100644
--- a/src/runtime/mgc.go
+++ b/src/runtime/mgc.go
@@ -154,7 +154,7 @@ func gcinit() {
throw("size of Workbuf is suboptimal")
}
// No sweep on the first cycle.
- mheap_.sweepDrained = 1
+ sweep.active.state.Store(sweepDrainedMask)
// Initialize GC pacer state.
// Use the environment variable GOGC for the initial gcPercent value.
@@ -1022,8 +1022,10 @@ func gcMarkTermination(nextTriggerRatio float64) {
// Those aren't tracked in any sweep lists, so we need to
// count them against sweep completion until we ensure all
// those spans have been forced out.
- sl := newSweepLocker()
- sl.blockCompletion()
+ sl := sweep.active.begin()
+ if !sl.valid {
+ throw("failed to set sweep barrier")
+ }
systemstack(func() { startTheWorldWithSema(true) })
@@ -1050,7 +1052,7 @@ func gcMarkTermination(nextTriggerRatio float64) {
})
// Now that we've swept stale spans in mcaches, they don't
// count against unswept spans.
- sl.dispose()
+ sweep.active.end(sl)
// Print gctrace before dropping worldsema. As soon as we drop
// worldsema another cycle could start and smash the stats
@@ -1457,7 +1459,7 @@ func gcSweep(mode gcMode) {
lock(&mheap_.lock)
mheap_.sweepgen += 2
- mheap_.sweepDrained = 0
+ sweep.active.reset()
mheap_.pagesSwept.Store(0)
mheap_.sweepArenas = mheap_.allArenas
mheap_.reclaimIndex.Store(0)