runtime: use signals to preempt Gs for suspendG

This adds support for pausing a running G by sending a signal to its
M.

The main complication is that we want to target a G, but can only send
a signal to an M. Hence, the protocol we use is to simply mark the G
for preemption (which we already do) and send the M a "wake up and
look around" signal. The signal checks if it's running a G with a
preemption request and stops it if so in the same way that stack check
preemptions stop Gs. Since the preemption may fail (the G could be
moved or the signal could arrive at an unsafe point), we keep a count
of the number of received preemption signals. This lets stopG detect
if its request failed and should be retried without an explicit
channel back to suspendG.

For #10958, #24543.

Change-Id: I3e1538d5ea5200aeb434374abb5d5fdc56107e53
Reviewed-on: https://go-review.googlesource.com/c/go/+/201760
Run-TryBot: Austin Clements <austin@google.com>
Reviewed-by: Cherry Zhang <cherryyz@google.com>
This commit is contained in:
Austin Clements 2019-10-08 13:23:51 -04:00
parent d16ec13756
commit 62e53b7922
10 changed files with 294 additions and 8 deletions

View file

@ -1072,7 +1072,11 @@ func isShrinkStackSafe(gp *g) bool {
// The syscall might have pointers into the stack and
// often we don't have precise pointer maps for the innermost
// frames.
return gp.syscallsp == 0
//
// We also can't copy the stack if we're at an asynchronous
// safe-point because we don't have precise pointer maps for
// all frames.
return gp.syscallsp == 0 && !gp.asyncSafePoint
}
// Maybe shrink the stack being used by gp.