runtime: yield in goschedIfBusy if gp.preempt

runtime.bgsweep contains an infinite loop. With aggressive enough
inlining, it may not perform any CALLs on a typical iteration. If
the runtime trying to preempt this goroutine, the lack of CALLs may
prevent preemption for ever occurring.

bgsweep does happen to call goschedIfBusy. Add a preempt check there to
make sure we yield eventually.

For #55022.

Change-Id: If22eb86fd6a626094b3c56dc745c8e4243b0fb40
Reviewed-on: https://go-review.googlesource.com/c/go/+/447135
Run-TryBot: Michael Pratt <mpratt@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Michael Knyszek <mknyszek@google.com>
Reviewed-by: Cherry Mui <cherryyz@google.com>
This commit is contained in:
Michael Pratt 2022-11-01 17:27:41 -04:00
parent 82c6967ada
commit 50664c236f
1 changed files with 4 additions and 1 deletions

View File

@ -335,7 +335,10 @@ func goschedguarded() {
//
//go:nosplit
func goschedIfBusy() {
if sched.npidle.Load() > 0 {
gp := getg()
// Call gosched if gp.preempt is set; we may be in a tight loop that
// doesn't otherwise yield.
if !gp.preempt && sched.npidle.Load() > 0 {
return
}
mcall(gosched_m)