Commit 06de3f52 authored by Austin Clements's avatar Austin Clements

runtime: document subtlety around entering mark termination

The barrier in gcDrain does not account for concurrent gcDrainNs
happening in gchelpwork, so it can actually return while there is
still work being done. It turns out this is okay, but for subtle
reasons involving gcDrainN always being run on the system
stack. Document these reasons.

Change-Id: Ib07b3753cc4e2b54533ab3081a359cbd1c3c08fb
Reviewed-on: https://go-review.googlesource.com/7736Reviewed-by: default avatarRick Hudson <rlh@golang.org>
parent 43dfb879
......@@ -333,6 +333,12 @@ func gc(mode int) {
var gcw gcWork
gcDrain(&gcw)
gcw.dispose()
// Despite the barrier in gcDrain, gcDrainNs may still
// be doing work at this point. This is okay because
// 1) the gcDrainNs happen on the system stack, so
// they will flush their work to the global queues
// before we can stop the world, and 2) it's fine if
// we go into mark termination with some work queued.
// Begin mark termination.
gctimer.cycle.markterm = nanotime()
......
......@@ -366,6 +366,9 @@ func gcDrain(gcw *gcWork) {
}
// gcDrainN scans n objects, blackening grey objects.
//
// This MUST be run on the system stack to prevent a stop-the-world
// while this locally holds GC work buffers.
//go:nowritebarrier
func gcDrainN(gcw *gcWork, n int) {
checknocurrentwbuf()
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment