1
0
mirror of https://github.com/golang/go synced 2024-11-19 04:44:41 -07:00

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/5881
Reviewed-by: Russ Cox <rsc@golang.org>
Reviewed-by: Rick Hudson <rlh@golang.org>
This commit is contained in:
Austin Clements 2015-02-24 22:20:38 -05:00
parent 37b8597178
commit b3d791c7bb
2 changed files with 21 additions and 20 deletions

View File

@ -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()

View File

@ -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")