From: Jason A. Donenfeld Date: Tue, 23 Nov 2021 19:04:24 +0000 (+0100) Subject: runtime: support non-cooperative preemption on windows/arm X-Git-Tag: go1.18beta1~176 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=c58243aa8a510a0f467715da71a3053a04365038;p=gostls13.git runtime: support non-cooperative preemption on windows/arm This adds support for injecting asynchronous preemption calls on windows/arm. This code follows sigctxt.pushCall for POSIX OSes on arm, except we subtract 1 from IP, just as in CL 273727. Updates #10958. Updates #24543. Updates #49759. Change-Id: Id0c2aed28662f50631b8c8cede3b4e6f088dafea Reviewed-on: https://go-review.googlesource.com/c/go/+/366734 Trust: Jason A. Donenfeld Reviewed-by: Austin Clements Reviewed-by: Patrik Nyblom Reviewed-by: Cherry Mui --- diff --git a/src/runtime/os_windows.go b/src/runtime/os_windows.go index 7ffb3a11b5..a85971c6a9 100644 --- a/src/runtime/os_windows.go +++ b/src/runtime/os_windows.go @@ -1306,7 +1306,7 @@ func setThreadCPUProfiler(hz int32) { atomic.Store((*uint32)(unsafe.Pointer(&getg().m.profilehz)), uint32(hz)) } -const preemptMSupported = GOARCH == "386" || GOARCH == "amd64" +const preemptMSupported = GOARCH != "arm64" // suspendLock protects simultaneous SuspendThread operations from // suspending each other. @@ -1399,8 +1399,20 @@ func preemptM(mp *m) { *(*uintptr)(unsafe.Pointer(sp)) = newpc c.set_sp(sp) c.set_ip(targetPC) - } + case "arm": + // Push LR. The injected call is responsible + // for restoring LR. gentraceback is aware of + // this extra slot. See sigctxt.pushCall in + // signal_arm.go, which is similar except we + // subtract 1 from IP here. + sp := c.sp() + sp -= goarch.PtrSize + c.set_sp(sp) + *(*uint32)(unsafe.Pointer(sp)) = uint32(c.lr()) + c.set_lr(newpc - 1) + c.set_ip(targetPC) + } stdcall2(_SetThreadContext, thread, uintptr(unsafe.Pointer(c))) } }