1
0
mirror of https://github.com/golang/go synced 2024-11-18 06:54:49 -07:00

runtime: remove work.partial queue

This work queue is no longer used (there are many reads of
work.partial, but the only write is in putpartial, which is never
called).

Fixes #11922.

Change-Id: I08b76c0c02a0867a9cdcb94783e1f7629d44249a
Reviewed-on: https://go-review.googlesource.com/15892
Reviewed-by: Rick Hudson <rlh@golang.org>
This commit is contained in:
Austin Clements 2015-10-15 15:44:16 -04:00
parent 1da6b2ea19
commit feb92a8e8c
3 changed files with 13 additions and 70 deletions

View File

@ -622,7 +622,7 @@ func (c *gcControllerState) findRunnableGCWorker(_p_ *p) *g {
// else for a while, so kick everything out of its run
// queue.
} else {
if _p_.gcw.wbuf == 0 && work.full == 0 && work.partial == 0 {
if _p_.gcw.wbuf == 0 && work.full == 0 {
// No work to be done right now. This can
// happen at the end of the mark phase when
// there are still assists tapering off. Don't
@ -795,10 +795,8 @@ func (s *bgMarkSignal) clear() {
}
var work struct {
full uint64 // lock-free list of full blocks workbuf
empty uint64 // lock-free list of empty blocks workbuf
// TODO(rlh): partial no longer used, remove. (issue #11922)
partial uint64 // lock-free list of partially filled blocks workbuf
full uint64 // lock-free list of full blocks workbuf
empty uint64 // lock-free list of empty blocks workbuf
pad0 [_CacheLineSize]uint8 // prevents false-sharing between full/empty and nproc/nwait
nproc uint32
tstart int64
@ -1400,7 +1398,7 @@ func gcBgMarkWorker(p *p) {
"work.nwait=", incnwait, "work.nproc=", work.nproc)
throw("work.nwait > work.nproc")
}
done = incnwait == work.nproc && work.full == 0 && work.partial == 0
done = incnwait == work.nproc && work.full == 0
}
// If this worker reached a background mark completion
@ -1436,7 +1434,7 @@ func gcMarkWorkAvailable(p *p) bool {
if !p.gcw.empty() {
return true
}
if atomicload64(&work.full) != 0 || atomicload64(&work.partial) != 0 {
if atomicload64(&work.full) != 0 {
return true // global work available
}
return false
@ -1497,9 +1495,6 @@ func gcMark(start_time int64) {
if work.full != 0 {
throw("work.full != 0")
}
if work.partial != 0 {
throw("work.partial != 0")
}
if work.nproc > 1 {
notesleep(&work.alldone)

View File

@ -300,7 +300,7 @@ retry:
throw("work.nwait > work.nproc")
}
if incnwait == work.nproc && work.full == 0 && work.partial == 0 {
if incnwait == work.nproc && work.full == 0 {
// This has reached a background completion
// point.
if gcBlackenPromptly {

View File

@ -80,7 +80,7 @@ func (ww *gcWork) put(obj uintptr) {
wbuf := w.wbuf.ptr()
if wbuf == nil {
wbuf = getpartialorempty(42)
wbuf = getempty(42)
w.wbuf = wbufptrOf(wbuf)
}
@ -204,7 +204,7 @@ func (w *gcWork) empty() bool {
type workbufhdr struct {
node lfnode // must be first
nobj int
inuse bool // This workbuf is in use by some gorotuine and is not on the work.empty/partial/full queues.
inuse bool // This workbuf is in use by some gorotuine and is not on the work.empty/full queues.
log [4]int // line numbers forming a history of ownership changes to workbuf
}
@ -217,7 +217,7 @@ type workbuf struct {
// workbuf factory routines. These funcs are used to manage the
// workbufs.
// If the GC asks for some work these are the only routines that
// make partially full wbufs available to the GC.
// make wbufs available to the GC.
// Each of the gets and puts also take an distinct integer that is used
// to record a brief history of changes to ownership of the workbuf.
// The convention is to use a unique line number but any encoding
@ -314,54 +314,11 @@ func putfull(b *workbuf, entry int) {
lfstackpush(&work.full, &b.node)
}
// getpartialorempty tries to return a partially empty
// and if none are available returns an empty one.
// entry is used to provide a brief history of ownership
// using entry + xxx00000 to
// indicating that two line numbers in the call chain.
//go:nowritebarrier
func getpartialorempty(entry int) *workbuf {
b := (*workbuf)(lfstackpop(&work.partial))
if b != nil {
b.logget(entry)
return b
}
// Let getempty do the logget check but
// use the entry to encode that it passed
// through this routine.
b = getempty(entry + 80700000)
return b
}
// putpartial puts empty buffers on the work.empty queue,
// full buffers on the work.full queue and
// others on the work.partial queue.
// entry is used to provide a brief history of ownership
// using entry + xxx00000 to
// indicating that two call chain line numbers.
//go:nowritebarrier
func putpartial(b *workbuf, entry int) {
if b.nobj == 0 {
putempty(b, entry+81500000)
} else if b.nobj < len(b.obj) {
b.logput(entry)
lfstackpush(&work.partial, &b.node)
} else if b.nobj == len(b.obj) {
b.logput(entry)
lfstackpush(&work.full, &b.node)
} else {
throw("putpartial: bad Workbuf b.nobj")
}
}
// trygetfull tries to get a full or partially empty workbuffer.
// If one is not immediately available return nil
//go:nowritebarrier
func trygetfull(entry int) *workbuf {
b := (*workbuf)(lfstackpop(&work.full))
if b == nil {
b = (*workbuf)(lfstackpop(&work.partial))
}
if b != nil {
b.logget(entry)
b.checknonempty()
@ -370,10 +327,9 @@ func trygetfull(entry int) *workbuf {
return b
}
// Get a full work buffer off the work.full or a partially
// filled one off the work.partial list. If nothing is available
// wait until all the other gc helpers have finished and then
// return nil.
// Get a full work buffer off the work.full list.
// If nothing is available wait until all the other gc helpers have
// finished and then return nil.
// getfull acts as a barrier for work.nproc helpers. As long as one
// gchelper is actively marking objects it
// may create a workbuffer that the other helpers can work on.
@ -390,11 +346,6 @@ func getfull(entry int) *workbuf {
b.checknonempty()
return b
}
b = (*workbuf)(lfstackpop(&work.partial))
if b != nil {
b.logget(entry)
return b
}
incnwait := xadd(&work.nwait, +1)
if incnwait > work.nproc {
@ -402,16 +353,13 @@ func getfull(entry int) *workbuf {
throw("work.nwait > work.nproc")
}
for i := 0; ; i++ {
if work.full != 0 || work.partial != 0 {
if work.full != 0 {
decnwait := xadd(&work.nwait, -1)
if decnwait == work.nproc {
println("runtime: work.nwait=", decnwait, "work.nproc=", work.nproc)
throw("work.nwait > work.nproc")
}
b = (*workbuf)(lfstackpop(&work.full))
if b == nil {
b = (*workbuf)(lfstackpop(&work.partial))
}
if b != nil {
b.logget(entry)
b.checknonempty()