aboutsummaryrefslogtreecommitdiff
path: root/libgo/go/runtime/preempt.go
diff options
context:
space:
mode:
Diffstat (limited to 'libgo/go/runtime/preempt.go')
-rw-r--r--libgo/go/runtime/preempt.go22
1 files changed, 15 insertions, 7 deletions
diff --git a/libgo/go/runtime/preempt.go b/libgo/go/runtime/preempt.go
index 1a8f9ac..9a78bcf 100644
--- a/libgo/go/runtime/preempt.go
+++ b/libgo/go/runtime/preempt.go
@@ -56,6 +56,11 @@ import (
"runtime/internal/atomic"
)
+// Keep in sync with cmd/compile/internal/gc/plive.go:go115ReduceLiveness.
+const go115ReduceLiveness = true
+
+const go115RestartSeq = go115ReduceLiveness && true // enable restartable sequences
+
type suspendGState struct {
g *g
@@ -328,26 +333,30 @@ func wantAsyncPreempt(gp *g) bool {
// 3. It's generally safe to interact with the runtime, even if we're
// in a signal handler stopped here. For example, there are no runtime
// locks held, so acquiring a runtime lock won't self-deadlock.
-func isAsyncSafePoint(gp *g, pc uintptr) bool {
+//
+// In some cases the PC is safe for asynchronous preemption but it
+// also needs to adjust the resumption PC. The new PC is returned in
+// the second result.
+func isAsyncSafePoint(gp *g, pc uintptr) (bool, uintptr) {
mp := gp.m
// Only user Gs can have safe-points. We check this first
// because it's extremely common that we'll catch mp in the
// scheduler processing this G preemption.
if mp.curg != gp {
- return false
+ return false, 0
}
// Check M state.
if mp.p == 0 || !canPreemptM(mp) {
- return false
+ return false, 0
}
// Check if PC is an unsafe-point.
f := FuncForPC(pc)
if f == nil {
// Not Go code.
- return false
+ return false, 0
}
name := f.Name()
if hasPrefix(name, "runtime.") ||
@@ -363,8 +372,7 @@ func isAsyncSafePoint(gp *g, pc uintptr) bool {
//
// TODO(austin): We should improve this, or opt things
// in incrementally.
- return false
+ return false, 0
}
-
- return true
+ return true, pc
}