// mode is the concurrency mode of the current GC cycle.
mode gcMode
- // Snapshot of mheap.allspans for marker or sweeper created by
- // gcCopySpans. Unlike allspans, this does not change except
- // at controlled GC transition points.
- spans []*mspan
-
// totaltime is the CPU nanoseconds spent in GC since the
// program started if debug.gctrace > 0.
totaltime int64
systemstack(stopTheWorldWithSema)
// Finish sweep before we start concurrent scan.
systemstack(func() {
- finishsweep_m(true)
+ finishsweep_m()
})
// clearpools before we start the GC. If we wait they memory will not be
// reclaimed until the next GC cycle.
// possible.
setGCPhase(_GCmark)
- // markrootSpans uses work.spans, so make sure
- // it is up to date.
- gcCopySpans()
-
gcBgMarkPrepare() // Must happen before assist enable.
gcMarkRootPrepare()
// they have gcscanvalid==true and gcworkdone==true.
// Reset these so that all stacks will be rescanned.
gcResetMarkState()
- finishsweep_m(true)
+ finishsweep_m()
// Still in STW but gcphase is _GCoff, reset to _GCmarktermination
// At this point all objects will be found during the gcMark which
}
work.tstart = start_time
- gcCopySpans() // TODO(rlh): should this be hoisted and done only once? Right now it is done for normal marking and also for checkmarking.
-
// Queue root marking jobs.
gcMarkRootPrepare()
if gcphase != _GCoff {
throw("gcSweep being done but phase is not GCoff")
}
- gcCopySpans()
lock(&mheap_.lock)
mheap_.sweepgen += 2
unlock(&sweep.lock)
}
-func gcCopySpans() {
- // Cache runtime.mheap_.allspans in work.spans to avoid conflicts with
- // resizing/freeing allspans.
- // New spans can be created while GC progresses, but they are not garbage for
- // this round:
- // - new stack spans can be created even while the world is stopped.
- // - new malloc spans can be created during the concurrent sweep
- // Even if this is stop-the-world, a concurrent exitsyscall can allocate a stack from heap.
- lock(&mheap_.lock)
- // Free the old cached mark array if necessary.
- if work.spans != nil && &work.spans[0] != &mheap_.allspans[0] {
- sysFree(unsafe.Pointer(&work.spans[0]), uintptr(len(work.spans))*unsafe.Sizeof(work.spans[0]), &memstats.other_sys)
- }
- // Cache the current array for sweeping.
- work.spans = mheap_.allspans
- unlock(&mheap_.lock)
-}
-
// gcResetMarkState resets global state prior to marking (concurrent
// or STW) and resets the stack scan state of all Gs.
//
//go:nowritebarrier
func initCheckmarks() {
useCheckmark = true
- for _, s := range work.spans {
+ for _, s := range mheap_.allspans {
if s.state == _MSpanInUse {
heapBitsForSpan(s.base()).initCheckmarkSpan(s.layout())
}
func clearCheckmarks() {
useCheckmark = false
- for _, s := range work.spans {
+ for _, s := range mheap_.allspans {
if s.state == _MSpanInUse {
heapBitsForSpan(s.base()).clearCheckmarkSpan(s.layout())
}
pacertracegen uint32
}
+// finishsweep_m ensures that all spans are swept.
+//
+// The world must be stopped. This ensures there are no sweeps in
+// progress.
+//
//go:nowritebarrier
-func finishsweep_m(stw bool) {
+func finishsweep_m() {
// Sweeping must be complete before marking commences, so
// sweep any unswept spans. If this is a concurrent GC, there
// shouldn't be any spans left to sweep, so this should finish
sweep.npausesweep++
}
- // There may be some other spans being swept concurrently that
- // we need to wait for. If finishsweep_m is done with the world stopped
- // this is not required because the STW must have waited for sweeps.
- //
- // TODO(austin): As of this writing, we always pass true for stw.
- // Consider removing this code.
- if !stw {
- sg := mheap_.sweepgen
- for _, s := range work.spans {
- if s.sweepgen != sg && s.state == _MSpanInUse {
- s.ensureSwept()
- }
- }
- }
nextMarkBitArenaEpoch()
}
}
oldAllspans := h.allspans
h.allspans = new
- // Don't free the old array if it's referenced by sweep.
- // See the comment in mgc.go.
- if len(oldAllspans) != 0 && &oldAllspans[0] != &work.spans[0] {
+ if len(oldAllspans) != 0 {
sysFree(unsafe.Pointer(&oldAllspans[0]), uintptr(cap(oldAllspans))*unsafe.Sizeof(oldAllspans[0]), &memstats.other_sys)
}
}