From 9f263c14edccb564b675ed6c4f12260f333505d5 Mon Sep 17 00:00:00 2001 From: Austin Clements Date: Wed, 2 Mar 2016 17:55:45 -0500 Subject: [PATCH] runtime: remove stack barriers during sweep This adds a best-effort pass to remove stack barriers immediately after the end of mark termination. This isn't necessary for the Go runtime, but should help external tools that perform stack walks but aren't aware of Go's stack barriers such as GDB, perf, and VTune. (Though clearly they'll still have trouble unwinding stacks during mark.) Change-Id: I66600fae1f03ee36b5459d2b00dcc376269af18e Reviewed-on: https://go-review.googlesource.com/20668 Reviewed-by: Rick Hudson Run-TryBot: Austin Clements TryBot-Result: Gobot Gobot --- src/runtime/mgc.go | 7 +++++++ src/runtime/mstkbar.go | 25 +++++++++++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/src/runtime/mgc.go b/src/runtime/mgc.go index bc157cddbb..425ed3a160 100644 --- a/src/runtime/mgc.go +++ b/src/runtime/mgc.go @@ -1266,6 +1266,13 @@ func gcMarkTermination() { // Free stack spans. This must be done between GC cycles. systemstack(freeStackSpans) + // Best-effort remove stack barriers so they don't get in the + // way of things like GDB and perf. + lock(&allglock) + myallgs := allgs + unlock(&allglock) + gcTryRemoveAllStackBarriers(myallgs) + // Print gctrace before dropping worldsema. As soon as we drop // worldsema another cycle could start and smash the stats // we're trying to print. diff --git a/src/runtime/mstkbar.go b/src/runtime/mstkbar.go index f320c351d0..1bf9d573b7 100644 --- a/src/runtime/mstkbar.go +++ b/src/runtime/mstkbar.go @@ -257,6 +257,31 @@ func gcRemoveStackBarrier(gp *g, stkbar stkbar) { *lrPtr = sys.Uintreg(stkbar.savedLRVal) } +// gcTryRemoveAllStackBarriers tries to remove stack barriers from all +// Gs in gps. It is best-effort and efficient. If it can't remove +// barriers from a G immediately, it will simply skip it. +func gcTryRemoveAllStackBarriers(gps []*g) { + for _, gp := range gps { + retry: + for { + switch s := readgstatus(gp); s { + default: + break retry + + case _Grunnable, _Gsyscall, _Gwaiting: + if !castogscanstatus(gp, s, s|_Gscan) { + continue + } + gcLockStackBarriers(gp) + gcRemoveStackBarriers(gp) + gcUnlockStackBarriers(gp) + restartg(gp) + break retry + } + } + } +} + // gcPrintStkbars prints the stack barriers of gp for debugging. It // places a "@@@" marker at gp.stkbarPos. If marker >= 0, it will also // place a "==>" marker before the marker'th entry. -- 2.48.1