aboutsummaryrefslogtreecommitdiff
path: root/src/runtime/runtime2.go
diff options
context:
space:
mode:
authorMichael Pratt <mpratt@google.com>2022-03-01 15:06:37 -0500
committerGopher Robot <gobot@golang.org>2022-08-12 03:22:59 +0000
commit8cb350d69a1b0765c1c81301583d6fd99fb9d74b (patch)
tree7c59c7c967019db071a8bc869054bd61d136620d /src/runtime/runtime2.go
parent54cf1b107d24e135990314b56b02264dba8620fc (diff)
downloadgo-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.go9
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.