]> Cypherpunks repositories - gostls13.git/commitdiff
runtime: document subtlety around entering mark termination
authorAustin Clements <austin@google.com>
Thu, 19 Mar 2015 18:37:30 +0000 (14:37 -0400)
committerAustin Clements <austin@google.com>
Fri, 20 Mar 2015 14:05:05 +0000 (14:05 +0000)
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/7736
Reviewed-by: Rick Hudson <rlh@golang.org>
src/runtime/mgc.go
src/runtime/mgcmark.go

index b82569bb3e4f77ed5ee7ac1d9e505f56cc084c5b..8eba5a8bc2dfa8024906e1e405fb1323a5c6ffd0 100644 (file)
@@ -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()
index 197b6a808dae37a983cfae14cbfd212452c72b42..8e0a88f0a3642bfc4812d5dcec92c5d5b3203dac 100644 (file)
@@ -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()