aboutsummaryrefslogtreecommitdiff
path: root/src/runtime/debug.go
diff options
context:
space:
mode:
Diffstat (limited to 'src/runtime/debug.go')
-rw-r--r--src/runtime/debug.go34
1 files changed, 34 insertions, 0 deletions
diff --git a/src/runtime/debug.go b/src/runtime/debug.go
index 82deefa200..c343f430cc 100644
--- a/src/runtime/debug.go
+++ b/src/runtime/debug.go
@@ -61,3 +61,37 @@ func NumGoroutine() int {
func debug_modinfo() string {
return modinfo
}
+
+// mayMoreStackPreempt is a maymorestack hook that forces a preemption
+// at every possible cooperative preemption point.
+//
+// This is valuable to apply to the runtime, which can be sensitive to
+// preemption points. To apply this to all preemption points in the
+// runtime and runtime-like code, use the following in bash or zsh:
+//
+// X=(-{gc,asm}flags={runtime/...,reflect,sync}=-d=maymorestack=runtime.mayMoreStackPreempt) GOFLAGS=${X[@]}
+//
+// This must be deeply nosplit because it is called from a function
+// prologue before the stack is set up and because the compiler will
+// call it from any splittable prologue (leading to infinite
+// recursion).
+//
+// Ideally it should also use very little stack because the linker
+// doesn't currently account for this in nosplit stack depth checking.
+//
+//go:nosplit
+//
+// Ensure mayMoreStackPreempt can be called for all ABIs.
+//
+//go:linkname mayMoreStackPreempt
+func mayMoreStackPreempt() {
+ // Don't do anything on the g0 or gsignal stack.
+ g := getg()
+ if g == g.m.g0 || g == g.m.gsignal {
+ return
+ }
+ // Force a preemption, unless the stack is already poisoned.
+ if g.stackguard0 < stackPoisonMin {
+ g.stackguard0 = stackPreempt
+ }
+}