diff options
author | Cherry Zhang <cherryyz@google.com> | 2019-11-20 17:10:34 -0500 |
---|---|---|
committer | Cherry Zhang <cherryyz@google.com> | 2020-05-06 15:41:12 +0000 |
commit | ee330385ca684f7c166913e10998f791d1be06e7 (patch) | |
tree | 63f9b19a0811656bb78fc35df4ad2c7ced36a49d /src/runtime/signal_unix.go | |
parent | 4daf8719e7f4c71a620f650d73caab2a9d7ea499 (diff) | |
download | go-ee330385ca684f7c166913e10998f791d1be06e7.tar.gz go-ee330385ca684f7c166913e10998f791d1be06e7.zip |
cmd/internal/obj, runtime: preempt & restart some instruction sequences
On some architectures, for async preemption the injected call
needs to clobber a register (usually REGTMP) in order to return
to the preempted function. As a consequence, the PC ranges where
REGTMP is live are not preemptible.
The uses of REGTMP are usually generated by the assembler, where
it needs to load or materialize a large constant or offset that
doesn't fit into the instruction. In those cases, REGTMP is not
live at the start of the instruction sequence. Instead of giving
up preemption in those cases, we could preempt it and restart the
sequence when resuming the execution. Basically, this is like
reissuing an interrupted instruction, except that here the
"instruction" is a Prog that consists of multiple machine
instructions. For this to work, we need to generate PC data to
mark the start of the Prog.
Currently this is only done for ARM64.
TODO: the split-stack function prologue is currently not async
preemptible. We could use this mechanism, preempt it and restart
at the function entry.
Change-Id: I37cb282f8e606e7ab6f67b3edfdc6063097b4bd1
Reviewed-on: https://go-review.googlesource.com/c/go/+/208126
Run-TryBot: Cherry Zhang <cherryyz@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Austin Clements <austin@google.com>
Diffstat (limited to 'src/runtime/signal_unix.go')
-rw-r--r-- | src/runtime/signal_unix.go | 8 |
1 files changed, 5 insertions, 3 deletions
diff --git a/src/runtime/signal_unix.go b/src/runtime/signal_unix.go index f5d79e561c..5aedbf7778 100644 --- a/src/runtime/signal_unix.go +++ b/src/runtime/signal_unix.go @@ -326,9 +326,11 @@ func sigpipe() { func doSigPreempt(gp *g, ctxt *sigctxt) { // Check if this G wants to be preempted and is safe to // preempt. - if wantAsyncPreempt(gp) && isAsyncSafePoint(gp, ctxt.sigpc(), ctxt.sigsp(), ctxt.siglr()) { - // Inject a call to asyncPreempt. - ctxt.pushCall(funcPC(asyncPreempt)) + if wantAsyncPreempt(gp) { + if ok, newpc := isAsyncSafePoint(gp, ctxt.sigpc(), ctxt.sigsp(), ctxt.siglr()); ok { + // Adjust the PC and inject a call to asyncPreempt. + ctxt.pushCall(funcPC(asyncPreempt), newpc) + } } // Acknowledge the preemption. |