runtime: update big mgc.go comment

The comment describing the overall GC algorithm at the top of mgc.go
has gotten woefully out-of-date (and was possibly never
correct/complete). Update it to reflect the current workings of the
GC and the set of phases that we now divide it into.

Change-Id: I02143c0ebefe9d4cd7753349dab8045f0973bf95
Reviewed-on: https://go-review.googlesource.com/34711
Reviewed-by: Rick Hudson <rlh@golang.org>
This commit is contained in:
Austin Clements 2016-12-22 17:30:23 -07:00
parent cb91dccd86
commit 618c291544

View file

@ -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.
//