Commit 88e945fd authored by Austin Clements's avatar Austin Clements

runtime: recheck GC trigger before actually starting GC

Currently allocation checks the GC trigger speculatively during
allocation and then triggers the GC without rechecking. As a result,
it's possible for G 1 and G 2 to detect the trigger simultaneously,
both enter startGC, G 1 actually starts GC while G 2 gets preempted
until after the whole GC cycle, then G 2 immediately starts another GC
cycle even though the heap is now well under the trigger.

Fix this by re-checking the GC trigger non-speculatively just before
actually kicking off a new GC cycle.

This contributes to #11911 because when this happens, we definitely
don't finish the background sweep before starting the next GC cycle,
which can significantly delay the start of concurrent scan.

Change-Id: I560ab79ba5684ba435084410a9765d28f5745976
Reviewed-on: https://go-review.googlesource.com/13025Reviewed-by: default avatarRuss Cox <rsc@golang.org>
Reviewed-by: default avatarRick Hudson <rlh@golang.org>
parent d5f5e658
......@@ -841,6 +841,14 @@ func startGC(mode int) {
// trigger concurrent GC
readied := false
lock(&bggc.lock)
// The trigger was originally checked speculatively, so
// recheck that this really should trigger GC. (For example,
// we may have gone through a whole GC cycle since the
// speculative check.)
if !shouldtriggergc() {
unlock(&bggc.lock)
return
}
if !bggc.started {
bggc.working = 1
bggc.started = true
......
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