Commit 9f263c14 authored by Austin Clements's avatar Austin Clements

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/20668Reviewed-by: default avatarRick Hudson <rlh@golang.org>
Run-TryBot: Austin Clements <austin@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
parent 269c969c
...@@ -1266,6 +1266,13 @@ func gcMarkTermination() { ...@@ -1266,6 +1266,13 @@ func gcMarkTermination() {
// Free stack spans. This must be done between GC cycles. // Free stack spans. This must be done between GC cycles.
systemstack(freeStackSpans) 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 // Print gctrace before dropping worldsema. As soon as we drop
// worldsema another cycle could start and smash the stats // worldsema another cycle could start and smash the stats
// we're trying to print. // we're trying to print.
......
...@@ -257,6 +257,31 @@ func gcRemoveStackBarrier(gp *g, stkbar stkbar) { ...@@ -257,6 +257,31 @@ func gcRemoveStackBarrier(gp *g, stkbar stkbar) {
*lrPtr = sys.Uintreg(stkbar.savedLRVal) *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 // gcPrintStkbars prints the stack barriers of gp for debugging. It
// places a "@@@" marker at gp.stkbarPos. If marker >= 0, it will also // places a "@@@" marker at gp.stkbarPos. If marker >= 0, it will also
// place a "==>" marker before the marker'th entry. // place a "==>" marker before the marker'th entry.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment