diff options
| author | Andy Pan <panjf2000@gmail.com> | 2023-12-15 17:19:08 +0800 |
|---|---|---|
| committer | Michael Pratt <mpratt@google.com> | 2024-02-27 20:35:42 +0000 |
| commit | 24070cf747d8b3f4487f1ca7247dcdf0ac266e8c (patch) | |
| tree | d28878ec57e126ac5095dd59c64f791c7538b51b /src | |
| parent | 234390e741dd43b1ce54b0cfd91dc591c0b190f7 (diff) | |
| download | go-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.go | 21 |
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. |
