Skip to content

Commit 156209c

Browse files
committed
go-patches: support non-cooperative preemption on arm and arm64
Signed-off-by: Jason A. Donenfeld <[email protected]>
1 parent a35907c commit 156209c

File tree

2 files changed

+124
-0
lines changed

2 files changed

+124
-0
lines changed
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
2+
From: "Jason A. Donenfeld" <[email protected]>
3+
Date: Tue, 23 Nov 2021 20:04:24 +0100
4+
Subject: [PATCH] [release-branch.go1.17] runtime: support non-cooperative
5+
preemption on windows/arm
6+
7+
This adds support for injecting asynchronous preemption calls on
8+
windows/arm. This code follows sigctxt.pushCall for POSIX OSes
9+
on arm, except we subtract 1 from IP, just as in CL 273727.
10+
11+
Updates #10958.
12+
Updates #24543.
13+
Updates #49759.
14+
15+
Change-Id: Id0c2aed28662f50631b8c8cede3b4e6f088dafea
16+
Reviewed-on: https://go-review.googlesource.com/c/go/+/366734
17+
Trust: Jason A. Donenfeld <[email protected]>
18+
Reviewed-by: Austin Clements <[email protected]>
19+
Reviewed-by: Patrik Nyblom <[email protected]>
20+
Reviewed-by: Cherry Mui <[email protected]>
21+
---
22+
src/runtime/os_windows.go | 16 ++++++++++++++--
23+
1 file changed, 14 insertions(+), 2 deletions(-)
24+
25+
diff --git a/src/runtime/os_windows.go b/src/runtime/os_windows.go
26+
index f0935264ac..faeb6ce552 100644
27+
--- a/src/runtime/os_windows.go
28+
+++ b/src/runtime/os_windows.go
29+
@@ -1303,7 +1303,7 @@ func setThreadCPUProfiler(hz int32) {
30+
atomic.Store((*uint32)(unsafe.Pointer(&getg().m.profilehz)), uint32(hz))
31+
}
32+
33+
-const preemptMSupported = GOARCH == "386" || GOARCH == "amd64"
34+
+const preemptMSupported = GOARCH != "arm64"
35+
36+
// suspendLock protects simultaneous SuspendThread operations from
37+
// suspending each other.
38+
@@ -1396,8 +1396,20 @@ func preemptM(mp *m) {
39+
*(*uintptr)(unsafe.Pointer(sp)) = newpc
40+
c.set_sp(sp)
41+
c.set_ip(targetPC)
42+
- }
43+
44+
+ case "arm":
45+
+ // Push LR. The injected call is responsible
46+
+ // for restoring LR. gentraceback is aware of
47+
+ // this extra slot. See sigctxt.pushCall in
48+
+ // signal_arm.go, which is similar except we
49+
+ // subtract 1 from IP here.
50+
+ sp := c.sp()
51+
+ sp -= sys.PtrSize
52+
+ c.set_sp(sp)
53+
+ *(*uint32)(unsafe.Pointer(sp)) = uint32(c.lr())
54+
+ c.set_lr(newpc - 1)
55+
+ c.set_ip(targetPC)
56+
+ }
57+
stdcall2(_SetThreadContext, thread, uintptr(unsafe.Pointer(c)))
58+
}
59+
}
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
2+
From: "Jason A. Donenfeld" <[email protected]>
3+
Date: Tue, 23 Nov 2021 20:57:24 +0100
4+
Subject: [PATCH] runtime: support non-cooperative preemption on windows/arm64
5+
6+
This adds support for injecting asynchronous preemption calls on
7+
windows/arm64. This code exactly follows sigctxt.pushCall for POSIX OSes
8+
on arm64.
9+
10+
Fixes #49759.
11+
12+
Change-Id: Id35ff6bc105c1db9d7ed2918d3ecab0e4e9a9431
13+
Reviewed-on: https://go-review.googlesource.com/c/go/+/366735
14+
Trust: Jason A. Donenfeld <[email protected]>
15+
Run-TryBot: Jason A. Donenfeld <[email protected]>
16+
TryBot-Result: Go Bot <[email protected]>
17+
Reviewed-by: Cherry Mui <[email protected]>
18+
Reviewed-by: Austin Clements <[email protected]>
19+
Reviewed-by: Patrik Nyblom <[email protected]>
20+
---
21+
src/runtime/os_windows.go | 18 ++++++++++++------
22+
1 file changed, 12 insertions(+), 6 deletions(-)
23+
24+
diff --git a/src/runtime/os_windows.go b/src/runtime/os_windows.go
25+
index faeb6ce552..7bf9a426d1 100644
26+
--- a/src/runtime/os_windows.go
27+
+++ b/src/runtime/os_windows.go
28+
@@ -1303,18 +1303,13 @@ func setThreadCPUProfiler(hz int32) {
29+
atomic.Store((*uint32)(unsafe.Pointer(&getg().m.profilehz)), uint32(hz))
30+
}
31+
32+
-const preemptMSupported = GOARCH != "arm64"
33+
+const preemptMSupported = true
34+
35+
// suspendLock protects simultaneous SuspendThread operations from
36+
// suspending each other.
37+
var suspendLock mutex
38+
39+
func preemptM(mp *m) {
40+
- if !preemptMSupported {
41+
- // TODO: Implement call injection
42+
- return
43+
- }
44+
-
45+
if mp == getg().m {
46+
throw("self-preempt")
47+
}
48+
@@ -1409,6 +1404,17 @@ func preemptM(mp *m) {
49+
*(*uint32)(unsafe.Pointer(sp)) = uint32(c.lr())
50+
c.set_lr(newpc - 1)
51+
c.set_ip(targetPC)
52+
+
53+
+ case "arm64":
54+
+ // Push LR. The injected call is responsible
55+
+ // for restoring LR. gentraceback is aware of
56+
+ // this extra slot. See sigctxt.pushCall in
57+
+ // signal_arm64.go.
58+
+ sp := c.sp() - 16 // SP needs 16-byte alignment
59+
+ c.set_sp(sp)
60+
+ *(*uint64)(unsafe.Pointer(sp)) = uint64(c.lr())
61+
+ c.set_lr(newpc)
62+
+ c.set_ip(targetPC)
63+
}
64+
stdcall2(_SetThreadContext, thread, uintptr(unsafe.Pointer(c)))
65+
}

0 commit comments

Comments
 (0)