From 88e945fd231b40a41955f2b8505f680a83520fbf Mon Sep 17 00:00:00 2001 From: Austin Clements Date: Fri, 31 Jul 2015 13:52:17 -0400 Subject: [PATCH] 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/13025 Reviewed-by: Russ Cox Reviewed-by: Rick Hudson --- src/runtime/mgc.go | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/runtime/mgc.go b/src/runtime/mgc.go index f0e05f61aa..de9f4f51fd 100644 --- a/src/runtime/mgc.go +++ b/src/runtime/mgc.go @@ -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 -- 2.48.1