mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
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/7736 Reviewed-by: Rick Hudson <rlh@golang.org>
This commit is contained in:
parent
43dfb879a3
commit
06de3f52a7
2 changed files with 9 additions and 0 deletions
|
|
@ -333,6 +333,12 @@ func gc(mode int) {
|
||||||
var gcw gcWork
|
var gcw gcWork
|
||||||
gcDrain(&gcw)
|
gcDrain(&gcw)
|
||||||
gcw.dispose()
|
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.
|
// Begin mark termination.
|
||||||
gctimer.cycle.markterm = nanotime()
|
gctimer.cycle.markterm = nanotime()
|
||||||
|
|
|
||||||
|
|
@ -366,6 +366,9 @@ func gcDrain(gcw *gcWork) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// gcDrainN scans n objects, blackening grey objects.
|
// 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
|
//go:nowritebarrier
|
||||||
func gcDrainN(gcw *gcWork, n int) {
|
func gcDrainN(gcw *gcWork, n int) {
|
||||||
checknocurrentwbuf()
|
checknocurrentwbuf()
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue