aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAndy Pan <panjf2000@gmail.com>2023-12-15 17:19:08 +0800
committerMichael Pratt <mpratt@google.com>2024-02-27 20:35:42 +0000
commit24070cf747d8b3f4487f1ca7247dcdf0ac266e8c (patch)
treed28878ec57e126ac5095dd59c64f791c7538b51b /src
parent234390e741dd43b1ce54b0cfd91dc591c0b190f7 (diff)
downloadgo-24070cf747d8b3f4487f1ca7247dcdf0ac266e8c.tar.xz
runtime: fix the potential race of idle P's during injectglist
Fixes #63555 Change-Id: I26e7baf58fcb78e66e0feed5725e371e25d657cc Reviewed-on: https://go-review.googlesource.com/c/go/+/550175 Reviewed-by: Michael Pratt <mpratt@google.com> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Reviewed-by: Carlos Amedee <carlos@golang.org>
Diffstat (limited to 'src')
-rw-r--r--src/runtime/proc.go21
1 files changed, 19 insertions, 2 deletions
diff --git a/src/runtime/proc.go b/src/runtime/proc.go
index d4919e56fd..cbd3022802 100644
--- a/src/runtime/proc.go
+++ b/src/runtime/proc.go
@@ -3816,8 +3816,10 @@ func injectglist(glist *gList) {
}
npidle := int(sched.npidle.Load())
- var globq gQueue
- var n int
+ var (
+ globq gQueue
+ n int
+ )
for n = 0; n < npidle && !q.empty(); n++ {
g := q.pop()
globq.pushBack(g)
@@ -3833,6 +3835,21 @@ func injectglist(glist *gList) {
if !q.empty() {
runqputbatch(pp, &q, qsize)
}
+
+ // Some P's might have become idle after we loaded `sched.npidle`
+ // but before any goroutines were added to the queue, which could
+ // lead to idle P's when there is work available in the global queue.
+ // That could potentially last until other goroutines become ready
+ // to run. That said, we need to find a way to hedge
+ //
+ // Calling wakep() here is the best bet, it will do nothing in the
+ // common case (no racing on `sched.npidle`), while it could wake one
+ // more P to execute G's, which might end up with >1 P's: the first one
+ // wakes another P and so forth until there is no more work, but this
+ // ought to be an extremely rare case.
+ //
+ // Also see "Worker thread parking/unparking" comment at the top of the file for details.
+ wakep()
}
// One round of scheduler: find a runnable goroutine and execute it.