mirror of
https://github.com/golang/go
synced 2024-11-18 09:14:43 -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:
parent
1da6b2ea19
commit
feb92a8e8c
@ -622,7 +622,7 @@ func (c *gcControllerState) findRunnableGCWorker(_p_ *p) *g {
|
|||||||
// else for a while, so kick everything out of its run
|
// else for a while, so kick everything out of its run
|
||||||
// queue.
|
// queue.
|
||||||
} else {
|
} 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
|
// No work to be done right now. This can
|
||||||
// happen at the end of the mark phase when
|
// happen at the end of the mark phase when
|
||||||
// there are still assists tapering off. Don't
|
// there are still assists tapering off. Don't
|
||||||
@ -795,10 +795,8 @@ func (s *bgMarkSignal) clear() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var work struct {
|
var work struct {
|
||||||
full uint64 // lock-free list of full blocks workbuf
|
full uint64 // lock-free list of full blocks workbuf
|
||||||
empty uint64 // lock-free list of empty 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
|
|
||||||
pad0 [_CacheLineSize]uint8 // prevents false-sharing between full/empty and nproc/nwait
|
pad0 [_CacheLineSize]uint8 // prevents false-sharing between full/empty and nproc/nwait
|
||||||
nproc uint32
|
nproc uint32
|
||||||
tstart int64
|
tstart int64
|
||||||
@ -1400,7 +1398,7 @@ func gcBgMarkWorker(p *p) {
|
|||||||
"work.nwait=", incnwait, "work.nproc=", work.nproc)
|
"work.nwait=", incnwait, "work.nproc=", work.nproc)
|
||||||
throw("work.nwait > 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
|
// If this worker reached a background mark completion
|
||||||
@ -1436,7 +1434,7 @@ func gcMarkWorkAvailable(p *p) bool {
|
|||||||
if !p.gcw.empty() {
|
if !p.gcw.empty() {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
if atomicload64(&work.full) != 0 || atomicload64(&work.partial) != 0 {
|
if atomicload64(&work.full) != 0 {
|
||||||
return true // global work available
|
return true // global work available
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
@ -1497,9 +1495,6 @@ func gcMark(start_time int64) {
|
|||||||
if work.full != 0 {
|
if work.full != 0 {
|
||||||
throw("work.full != 0")
|
throw("work.full != 0")
|
||||||
}
|
}
|
||||||
if work.partial != 0 {
|
|
||||||
throw("work.partial != 0")
|
|
||||||
}
|
|
||||||
|
|
||||||
if work.nproc > 1 {
|
if work.nproc > 1 {
|
||||||
notesleep(&work.alldone)
|
notesleep(&work.alldone)
|
||||||
|
@ -300,7 +300,7 @@ retry:
|
|||||||
throw("work.nwait > work.nproc")
|
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
|
// This has reached a background completion
|
||||||
// point.
|
// point.
|
||||||
if gcBlackenPromptly {
|
if gcBlackenPromptly {
|
||||||
|
@ -80,7 +80,7 @@ func (ww *gcWork) put(obj uintptr) {
|
|||||||
|
|
||||||
wbuf := w.wbuf.ptr()
|
wbuf := w.wbuf.ptr()
|
||||||
if wbuf == nil {
|
if wbuf == nil {
|
||||||
wbuf = getpartialorempty(42)
|
wbuf = getempty(42)
|
||||||
w.wbuf = wbufptrOf(wbuf)
|
w.wbuf = wbufptrOf(wbuf)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -204,7 +204,7 @@ func (w *gcWork) empty() bool {
|
|||||||
type workbufhdr struct {
|
type workbufhdr struct {
|
||||||
node lfnode // must be first
|
node lfnode // must be first
|
||||||
nobj int
|
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
|
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
|
// workbuf factory routines. These funcs are used to manage the
|
||||||
// workbufs.
|
// workbufs.
|
||||||
// If the GC asks for some work these are the only routines that
|
// 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
|
// 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.
|
// to record a brief history of changes to ownership of the workbuf.
|
||||||
// The convention is to use a unique line number but any encoding
|
// 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)
|
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.
|
// trygetfull tries to get a full or partially empty workbuffer.
|
||||||
// If one is not immediately available return nil
|
// If one is not immediately available return nil
|
||||||
//go:nowritebarrier
|
//go:nowritebarrier
|
||||||
func trygetfull(entry int) *workbuf {
|
func trygetfull(entry int) *workbuf {
|
||||||
b := (*workbuf)(lfstackpop(&work.full))
|
b := (*workbuf)(lfstackpop(&work.full))
|
||||||
if b == nil {
|
|
||||||
b = (*workbuf)(lfstackpop(&work.partial))
|
|
||||||
}
|
|
||||||
if b != nil {
|
if b != nil {
|
||||||
b.logget(entry)
|
b.logget(entry)
|
||||||
b.checknonempty()
|
b.checknonempty()
|
||||||
@ -370,10 +327,9 @@ func trygetfull(entry int) *workbuf {
|
|||||||
return b
|
return b
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get a full work buffer off the work.full or a partially
|
// Get a full work buffer off the work.full list.
|
||||||
// filled one off the work.partial list. If nothing is available
|
// If nothing is available wait until all the other gc helpers have
|
||||||
// wait until all the other gc helpers have finished and then
|
// finished and then return nil.
|
||||||
// return nil.
|
|
||||||
// getfull acts as a barrier for work.nproc helpers. As long as one
|
// getfull acts as a barrier for work.nproc helpers. As long as one
|
||||||
// gchelper is actively marking objects it
|
// gchelper is actively marking objects it
|
||||||
// may create a workbuffer that the other helpers can work on.
|
// may create a workbuffer that the other helpers can work on.
|
||||||
@ -390,11 +346,6 @@ func getfull(entry int) *workbuf {
|
|||||||
b.checknonempty()
|
b.checknonempty()
|
||||||
return b
|
return b
|
||||||
}
|
}
|
||||||
b = (*workbuf)(lfstackpop(&work.partial))
|
|
||||||
if b != nil {
|
|
||||||
b.logget(entry)
|
|
||||||
return b
|
|
||||||
}
|
|
||||||
|
|
||||||
incnwait := xadd(&work.nwait, +1)
|
incnwait := xadd(&work.nwait, +1)
|
||||||
if incnwait > work.nproc {
|
if incnwait > work.nproc {
|
||||||
@ -402,16 +353,13 @@ func getfull(entry int) *workbuf {
|
|||||||
throw("work.nwait > work.nproc")
|
throw("work.nwait > work.nproc")
|
||||||
}
|
}
|
||||||
for i := 0; ; i++ {
|
for i := 0; ; i++ {
|
||||||
if work.full != 0 || work.partial != 0 {
|
if work.full != 0 {
|
||||||
decnwait := xadd(&work.nwait, -1)
|
decnwait := xadd(&work.nwait, -1)
|
||||||
if decnwait == work.nproc {
|
if decnwait == work.nproc {
|
||||||
println("runtime: work.nwait=", decnwait, "work.nproc=", work.nproc)
|
println("runtime: work.nwait=", decnwait, "work.nproc=", work.nproc)
|
||||||
throw("work.nwait > work.nproc")
|
throw("work.nwait > work.nproc")
|
||||||
}
|
}
|
||||||
b = (*workbuf)(lfstackpop(&work.full))
|
b = (*workbuf)(lfstackpop(&work.full))
|
||||||
if b == nil {
|
|
||||||
b = (*workbuf)(lfstackpop(&work.partial))
|
|
||||||
}
|
|
||||||
if b != nil {
|
if b != nil {
|
||||||
b.logget(entry)
|
b.logget(entry)
|
||||||
b.checknonempty()
|
b.checknonempty()
|
||||||
|
Loading…
Reference in New Issue
Block a user