]> Cypherpunks repositories - gostls13.git/commit
[release-branch.go1.14] runtime: ensure startm new M is consistently visible to checkdead
authorMichael Pratt <mpratt@google.com>
Mon, 27 Jul 2020 19:04:17 +0000 (15:04 -0400)
committerDmitri Shuralyov <dmitshur@golang.org>
Sat, 22 Aug 2020 01:48:02 +0000 (01:48 +0000)
commit17fd967e3b99c370eb52541b3b6108880f450d5b
treecec473c904250adb6ed6b3555b042a27f2d5d771
parent060e0c868a6f856e41a198e78457672b97bbf76e
[release-branch.go1.14] runtime: ensure startm new M is consistently visible to checkdead

If no M is available, startm first grabs an idle P, then drops
sched.lock and calls newm to start a new M to run than P.

Unfortunately, that leaves a window in which a G (e.g., returning from a
syscall) may find no idle P, add to the global runq, and then in stopm
discover that there are no running M's, a condition that should be
impossible with runnable G's.

To avoid this condition, we pre-allocate the new M ID in startm before
dropping sched.lock. This ensures that checkdead will see the M as
running, and since that new M must eventually run the scheduler, it will
handle any pending work as necessary.

Outside of startm, most other calls to newm/allocm don't have a P at
all. The only exception is startTheWorldWithSema, which always has an M
if there is 1 P (i.e., the currently running M), and if there is >1 P
the findrunnable spinning dance ensures the problem never occurs.

This has been tested with strategically placed sleeps in the runtime to
help induce the correct race ordering, but the timing on this is too
narrow for a test that can be checked in.

For #40368
Fixes #40398

Change-Id: If5e0293a430cc85154b7ed55bc6dadf9b340abe2
Reviewed-on: https://go-review.googlesource.com/c/go/+/245018
Run-TryBot: Michael Pratt <mpratt@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Austin Clements <austin@google.com>
(cherry picked from commit 85afa2eb190d5d1a06584803bde4b4ee9b0e79b0)
Reviewed-on: https://go-review.googlesource.com/c/go/+/245297
src/runtime/proc.go