Commit e5e52f4f authored by Austin Clements's avatar Austin Clements

runtime: factor checking if P run queue is empty

There are a variety of places where we check if a P's run queue is
empty. This test is about to get slightly more complicated, so factor
it out into a new function, runqempty. This function is inlinable, so
this has no effect on performance.

Change-Id: If4a0b01ffbd004937de90d8d686f6ded4aad2c6b
Reviewed-on: https://go-review.googlesource.com/9287Reviewed-by: default avatarRick Hudson <rlh@golang.org>
Reviewed-by: default avatarRuss Cox <rsc@golang.org>
parent 9406f68e
......@@ -1115,7 +1115,7 @@ func startm(_p_ *p, spinning bool) {
//go:nowritebarrier
func handoffp(_p_ *p) {
// if it has local work, start it straight away
if _p_.runqhead != _p_.runqtail || sched.runqsize != 0 {
if !runqempty(_p_) || sched.runqsize != 0 {
startm(_p_, false)
return
}
......@@ -1369,7 +1369,7 @@ stop:
// check all runqueues once again
for i := 0; i < int(gomaxprocs); i++ {
_p_ := allp[i]
if _p_ != nil && _p_.runqhead != _p_.runqtail {
if _p_ != nil && !runqempty(_p_) {
lock(&sched.lock)
_p_ = pidleget()
unlock(&sched.lock)
......@@ -2657,7 +2657,7 @@ func procresize(nprocs int32) *p {
continue
}
p.status = _Pidle
if p.runqhead == p.runqtail {
if runqempty(p) {
pidleput(p)
} else {
p.m.set(mget())
......@@ -2940,7 +2940,7 @@ func retake(now int64) uint32 {
// On the one hand we don't want to retake Ps if there is no other work to do,
// but on the other hand we want to retake them eventually
// because they can prevent the sysmon thread from deep sleep.
if _p_.runqhead == _p_.runqtail && atomicload(&sched.nmspinning)+atomicload(&sched.npidle) > 0 && pd.syscallwhen+10*1000*1000 > now {
if runqempty(_p_) && atomicload(&sched.nmspinning)+atomicload(&sched.npidle) > 0 && pd.syscallwhen+10*1000*1000 > now {
continue
}
// Need to decrement number of idle locked M's
......@@ -3220,6 +3220,12 @@ func pidleget() *p {
return _p_
}
// runqempty returns true if _p_ has no Gs on its local run queue.
// Note that this test is generally racy.
func runqempty(_p_ *p) bool {
return _p_.runqhead == _p_.runqtail
}
// Try to put g on local runnable queue.
// If it's full, put onto global queue.
// Executed only by the owner P.
......@@ -3479,7 +3485,7 @@ func sync_runtime_canSpin(i int) bool {
if i >= active_spin || ncpu <= 1 || gomaxprocs <= int32(sched.npidle+sched.nmspinning)+1 {
return false
}
if p := getg().m.p.ptr(); p.runqhead != p.runqtail {
if p := getg().m.p.ptr(); !runqempty(p) {
return false
}
return true
......
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