Commit d57f0373 authored by Austin Clements's avatar Austin Clements

runtime: don't recheck heap trigger for periodic GC

88e945fd introduced a non-speculative double check of the heap trigger
before actually starting a concurrent GC. This was necessary to fix a
race for heap-triggered GC, but broke sysmon-triggered periodic GC,
since the heap check will of course fail for periodically triggered
GC.

Fix this by telling startGC whether or not this GC was triggered by
heap size or a timer and only doing the heap size double check for GCs
triggered by heap size.

Fixes #12026.

Change-Id: I7c3f6ec364545c36d619f2b4b3bf3b758e3bcbd6
Reviewed-on: https://go-review.googlesource.com/13168Reviewed-by: 's avatarRuss Cox <rsc@golang.org>
parent 3dd3ab41
......@@ -702,7 +702,7 @@ func mallocgc(size uintptr, typ *_type, flags uint32) unsafe.Pointer {
}
if shouldhelpgc && shouldtriggergc() {
startGC(gcBackgroundMode)
startGC(gcBackgroundMode, false)
} else if gcBlackenEnabled != 0 {
// Assist garbage collector. We delay this until the
// epilogue so that it doesn't interfere with the
......
......@@ -811,7 +811,7 @@ var work struct {
// garbage collection is complete. It may also block the entire
// program.
func GC() {
startGC(gcForceBlockMode)
startGC(gcForceBlockMode, false)
}
const (
......@@ -820,7 +820,12 @@ const (
gcForceBlockMode // stop-the-world GC now and wait for sweep
)
func startGC(mode int) {
// startGC starts a GC cycle. If mode is gcBackgroundMode, this will
// start GC in the background and return. Otherwise, this will block
// until the new GC cycle is started and finishes. If forceTrigger is
// true, it indicates that GC should be started regardless of the
// current heap size.
func startGC(mode int, forceTrigger bool) {
// The gc is turned off (via enablegc) until the bootstrap has completed.
// Also, malloc gets called in the guts of a number of libraries that might be
// holding locks. To avoid deadlocks during stop-the-world, don't bother
......@@ -853,7 +858,7 @@ func startGC(mode int) {
// recheck that this really should trigger GC. (For example,
// we may have gone through a whole GC cycle since the
// speculative check.)
if !shouldtriggergc() {
if !(forceTrigger || shouldtriggergc()) {
unlock(&bggc.lock)
return
}
......
......@@ -836,7 +836,7 @@ func mHeap_Scavenge(k int32, now, limit uint64) {
//go:linkname runtime_debug_freeOSMemory runtime/debug.freeOSMemory
func runtime_debug_freeOSMemory() {
startGC(gcForceBlockMode)
startGC(gcForceBlockMode, false)
systemstack(func() { mHeap_Scavenge(-1, ^uint64(0), 0) })
}
......
......@@ -154,7 +154,7 @@ func forcegchelper() {
if debug.gctrace > 0 {
println("GC forced")
}
startGC(gcBackgroundMode)
startGC(gcBackgroundMode, 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