diff --git a/src/runtime/mgc.go b/src/runtime/mgc.go index 0f0b0962e95..64a2f3abef8 100644 --- a/src/runtime/mgc.go +++ b/src/runtime/mgc.go @@ -2,9 +2,6 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// TODO(rsc): The code having to do with the heap bitmap needs very serious cleanup. -// It has gotten completely out of control. - // Garbage collector (GC). // // The GC runs concurrently with mutator threads, is type accurate (aka precise), allows multiple @@ -24,67 +21,73 @@ // Hudson, R., and Moss, J.E.B. Copying Garbage Collection without stopping the world. // Concurrency and Computation: Practice and Experience 15(3-5), 2003. // -// TODO(austin): The rest of this comment is woefully out of date and -// needs to be rewritten. There is no distinct scan phase any more and -// we allocate black during GC. +// 1. GC performs sweep termination. // -// 0. Set phase = GCscan from GCoff. -// 1. Wait for all P's to acknowledge phase change. -// At this point all goroutines have passed through a GC safepoint and -// know we are in the GCscan phase. -// 2. GC scans all goroutine stacks, mark and enqueues all encountered pointers -// (marking avoids most duplicate enqueuing but races may produce benign duplication). -// Preempted goroutines are scanned before P schedules next goroutine. -// 3. Set phase = GCmark. -// 4. Wait for all P's to acknowledge phase change. -// 5. Now write barrier marks and enqueues black, grey, or white to white pointers. -// Malloc still allocates white (non-marked) objects. -// 6. Meanwhile GC transitively walks the heap marking reachable objects. -// 7. When GC finishes marking heap, it preempts P's one-by-one and -// retakes partial wbufs (filled by write barrier or during a stack scan of the goroutine -// currently scheduled on the P). -// 8. Once the GC has exhausted all available marking work it sets phase = marktermination. -// 9. Wait for all P's to acknowledge phase change. -// 10. Malloc now allocates black objects, so number of unmarked reachable objects -// monotonically decreases. -// 11. GC preempts P's one-by-one taking partial wbufs and marks all unmarked yet -// reachable objects. -// 12. When GC completes a full cycle over P's and discovers no new grey -// objects, (which means all reachable objects are marked) set phase = GCoff. -// 13. Wait for all P's to acknowledge phase change. -// 14. Now malloc allocates white (but sweeps spans before use). -// Write barrier becomes nop. -// 15. GC does background sweeping, see description below. -// 16. When sufficient allocation has taken place replay the sequence starting at 0 above, -// see discussion of GC rate below. - -// Changing phases. -// Phases are changed by setting the gcphase to the next phase and possibly calling ackgcphase. -// All phase action must be benign in the presence of a change. -// Starting with GCoff -// GCoff to GCscan -// GSscan scans stacks and globals greying them and never marks an object black. -// Once all the P's are aware of the new phase they will scan gs on preemption. -// This means that the scanning of preempted gs can't start until all the Ps -// have acknowledged. -// When a stack is scanned, this phase also installs stack barriers to -// track how much of the stack has been active. -// This transition enables write barriers because stack barriers -// assume that writes to higher frames will be tracked by write -// barriers. Technically this only needs write barriers for writes -// to stack slots, but we enable write barriers in general. -// GCscan to GCmark -// In GCmark, work buffers are drained until there are no more -// pointers to scan. -// No scanning of objects (making them black) can happen until all -// Ps have enabled the write barrier, but that already happened in -// the transition to GCscan. -// GCmark to GCmarktermination -// The only change here is that we start allocating black so the Ps must acknowledge -// the change before we begin the termination algorithm -// GCmarktermination to GSsweep -// Object currently on the freelist must be marked black for this to work. -// Are things on the free lists black or white? How does the sweep phase work? +// a. Stop the world. This causes all Ps to reach a GC safe-point. +// +// b. Sweep any unswept spans. There will only be unswept spans if +// this GC cycle was forced before the expected time. +// +// 2. GC performs the "mark 1" sub-phase. In this sub-phase, Ps are +// allowed to locally cache parts of the work queue. +// +// a. Prepare for the mark phase by setting gcphase to _GCmark +// (from _GCoff), enabling the write barrier, enabling mutator +// assists, and enqueueing root mark jobs. No objects may be +// scanned until all Ps have enabled the write barrier, which is +// accomplished using STW. +// +// b. Start the world. From this point, GC work is done by mark +// workers started by the scheduler and by assists performed as +// part of allocation. The write barrier shades both the +// overwritten pointer and the new pointer value for any pointer +// writes (see mbarrier.go for details). Newly allocated objects +// are immediately marked black. +// +// c. GC performs root marking jobs. This includes scanning all +// stacks, shading all globals, and shading any heap pointers in +// off-heap runtime data structures. Scanning a stack stops a +// goroutine, shades any pointers found on its stack, and then +// resumes the goroutine. +// +// d. GC drains the work queue of grey objects, scanning each grey +// object to black and shading all pointers found in the object +// (which in turn may add those pointers to the work queue). +// +// 3. Once the global work queue is empty (but local work queue caches +// may still contain work), GC performs the "mark 2" sub-phase. +// +// a. GC stops all workers, disables local work queue caches, +// flushes each P's local work queue cache to the global work queue +// cache, and reenables workers. +// +// b. GC again drains the work queue, as in 2d above. +// +// 4. Once the work queue is empty, GC performs mark termination. +// +// a. Stop the world. +// +// b. Set gcphase to _GCmarktermination, and disable workers and +// assists. +// +// c. Drain any remaining work from the work queue (typically there +// will be none). +// +// d. Perform other housekeeping like flushing mcaches. +// +// 5. GC performs the sweep phase. +// +// a. Prepare for the sweep phase by setting gcphase to _GCoff, +// setting up sweep state and disabling the write barrier. +// +// b. Start the world. From this point on, newly allocated objects +// are white, and allocating sweeps spans before use if necessary. +// +// c. GC does concurrent sweeping in the background and in response +// to allocation. See description below. +// +// 6. When sufficient allocation has taken place, replay the sequence +// starting with 1 above. See discussion of GC rate below. // Concurrent sweep. //