aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAustin Clements <austin@google.com>2016-12-22 17:30:23 -0700
committerAustin Clements <austin@google.com>2017-01-06 18:22:35 +0000
commit618c291544d4e1152e7ba5ce5b1b2988d1a7b50f (patch)
tree3ff9b67f76756b4a56fc7b11eb20b706ba7d9832
parentcb91dccd86ec07ecdc6cd227f0789372e3c75153 (diff)
downloadgo-618c291544d4e1152e7ba5ce5b1b2988d1a7b50f.tar.gz
go-618c291544d4e1152e7ba5ce5b1b2988d1a7b50f.zip
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>
-rw-r--r--src/runtime/mgc.go129
1 files changed, 66 insertions, 63 deletions
diff --git a/src/runtime/mgc.go b/src/runtime/mgc.go
index 0f0b0962e9..64a2f3abef 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.
+//
+// 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.
//
-// 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?
+// 6. When sufficient allocation has taken place, replay the sequence
+// starting with 1 above. See discussion of GC rate below.
// Concurrent sweep.
//