Commit b3d791c7 authored by Austin Clements's avatar Austin Clements

runtime: consolidate gcworkdone/gcscanvalid clearing loops

Previously, we had three loops in the garbage collector that all
cleared the per-G GC flags.  Consolidate these into one function.
This one function is designed to work in a concurrent setting.  As a
result, it's slightly more expensive than the loops it replaces during
STW phases, but these happen at most twice per GC.

Change-Id: Id1ec0074fd58865eb0112b8a0547b267802d0df1
Reviewed-on: https://go-review.googlesource.com/5881Reviewed-by: 's avatarRuss Cox <rsc@golang.org>
Reviewed-by: 's avatarRick Hudson <rlh@golang.org>
parent 37b85971
......@@ -339,13 +339,9 @@ func gc(mode int) {
})
} else {
// For non-concurrent GC (mode != gcBackgroundMode)
// The g stacks have not been scanned so set gcscanvalid
// The g stacks have not been scanned so clear g state
// such that mark termination scans all stacks.
// No races here since we are in a STW phase.
for _, gp := range allgs {
gp.gcworkdone = false // set to true in gcphasework
gp.gcscanvalid = false // stack has not been scanned
}
gcResetGState()
}
startTime := nanotime()
......@@ -384,11 +380,7 @@ func gc(mode int) {
// The g stacks have been scanned so
// they have gcscanvalid==true and gcworkdone==true.
// Reset these so that all stacks will be rescanned.
// No races here since we are in a STW phase.
for _, gp := range allgs {
gp.gcworkdone = false // set to true in gcphasework
gp.gcscanvalid = false // stack has not been scanned
}
gcResetGState()
finishsweep_m()
gcMark(startTime)
gcSweep(mode)
......@@ -606,6 +598,22 @@ func gcCopySpans() {
unlock(&mheap_.lock)
}
// gcResetGState resets the GC state of all G's and returns the length
// of allgs.
func gcResetGState() int {
// This may be called during a concurrent phase, so make sure
// allgs doesn't change.
lock(&allglock)
local_allglen := allglen
for i := uintptr(0); i < local_allglen; i++ {
gp := allgs[i]
gp.gcworkdone = false // set to true in gcphasework
gp.gcscanvalid = false // stack has not been scanned
}
unlock(&allglock)
return int(local_allglen)
}
// Hooks for other packages
var poolcleanup func()
......
......@@ -27,14 +27,7 @@ func gcscan_m() {
// At the bottom we will want to return this p back to the scheduler.
// Prepare flag indicating that the scan has not been completed.
lock(&allglock)
local_allglen := allglen
for i := uintptr(0); i < local_allglen; i++ {
gp := allgs[i]
gp.gcworkdone = false // set to true in gcphasework
gp.gcscanvalid = false // stack has not been scanned
}
unlock(&allglock)
local_allglen := gcResetGState()
work.nwait = 0
work.ndone = 0
......@@ -45,7 +38,7 @@ func gcscan_m() {
lock(&allglock)
// Check that gc work is done.
for i := uintptr(0); i < local_allglen; i++ {
for i := 0; i < local_allglen; i++ {
gp := allgs[i]
if !gp.gcworkdone {
throw("scan missed a g")
......
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