mirror of
https://github.com/golang/go
synced 2024-11-19 04:24:39 -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:
parent
37b8597178
commit
b3d791c7bb
@ -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")
|
||||
|
Loading…
Reference in New Issue
Block a user