}
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
// garbage collection is complete. It may also block the entire
// program.
func GC() {
- startGC(gcForceBlockMode)
+ startGC(gcForceBlockMode, false)
}
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
// 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
}
//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) })
}