diff options
| author | Michael Pratt <mpratt@google.com> | 2022-03-01 15:06:37 -0500 |
|---|---|---|
| committer | Gopher Robot <gobot@golang.org> | 2022-08-12 03:22:59 +0000 |
| commit | 8cb350d69a1b0765c1c81301583d6fd99fb9d74b (patch) | |
| tree | 7c59c7c967019db071a8bc869054bd61d136620d /src/runtime/runtime2.go | |
| parent | 54cf1b107d24e135990314b56b02264dba8620fc (diff) | |
| download | go-8cb350d69a1b0765c1c81301583d6fd99fb9d74b.tar.xz | |
runtime: synchronize P wakeup and dropping Ps
CL 310850 dropped work re-checks on non-spinning Ms to fix #43997.
This introduced a new race condition: a non-spinning M may drop its P
and then park at the same time a spinning M attempts to wake a P to
handle some new work. The spinning M fails to find an idle P (because
the non-spinning M hasn't quite made its P idle yet), and does nothing
assuming that the system is fully loaded. This results in loss of work
conservation. In the worst case we could have a complete deadlock if
injectglist fails to wake anything just as all Ps are going idle.
sched.needspinning adds new synchronization to cover this case. If work
submission fails to find a P, it sets needspinning to indicate that a
spinning M is required. When non-spinning Ms prepare to drop their P,
they check needspinning and abort going idle to become a spinning M
instead. This addresses the race without extra spurious wakeups. In the
normal (non-racing case), an M will become spinning via the normal path
and clear the flag.
injectglist must change in addition to wakep because it is a similar
form of work submission, notably used following netpoll at a point when
we might not have a P that would guarantee the work runs.
Fixes #45867
Change-Id: Ieb623a6d4162fb8c2be7b4ff8acdebcc3a0d69a8
Reviewed-on: https://go-review.googlesource.com/c/go/+/389014
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Michael Knyszek <mknyszek@google.com>
Run-TryBot: Michael Pratt <mpratt@google.com>
Auto-Submit: Michael Pratt <mpratt@google.com>
Diffstat (limited to 'src/runtime/runtime2.go')
| -rw-r--r-- | src/runtime/runtime2.go | 9 |
1 files changed, 6 insertions, 3 deletions
diff --git a/src/runtime/runtime2.go b/src/runtime/runtime2.go index e706cf7354..884d6cc096 100644 --- a/src/runtime/runtime2.go +++ b/src/runtime/runtime2.go @@ -777,9 +777,10 @@ type schedt struct { ngsys atomic.Int32 // number of system goroutines - pidle puintptr // idle p's - npidle atomic.Int32 - nmspinning atomic.Int32 // See "Worker thread parking/unparking" comment in proc.go. + pidle puintptr // idle p's + npidle atomic.Int32 + nmspinning atomic.Int32 // See "Worker thread parking/unparking" comment in proc.go. + needspinning atomic.Uint32 // See "Delicate dance" comment in proc.go. Boolean. Must hold sched.lock to set to 1. // Global runnable queue. runq gQueue @@ -840,6 +841,8 @@ type schedt struct { // with the rest of the runtime. sysmonlock mutex + _ uint32 // ensure timeToRun has 8-byte alignment + // timeToRun is a distribution of scheduling latencies, defined // as the sum of time a G spends in the _Grunnable state before // it transitions to _Grunning. |
