]> Cypherpunks repositories - gostls13.git/commitdiff
runtime: remove stack barriers during sweep
authorAustin Clements <austin@google.com>
Wed, 2 Mar 2016 22:55:45 +0000 (17:55 -0500)
committerAustin Clements <austin@google.com>
Tue, 26 Apr 2016 23:40:04 +0000 (23:40 +0000)
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 <rlh@golang.org>
Run-TryBot: Austin Clements <austin@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>

src/runtime/mgc.go
src/runtime/mstkbar.go

index bc157cddbb397b72d40f0ae556bb5014e02f5a50..425ed3a1600219eeaca4b005abeb7016c3ea5191 100644 (file)
@@ -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.
index f320c351d0de688aea39daf172bc5cdb8ec9ed04..1bf9d573b70f59bca185b9db62e91feb488b8492 100644 (file)
@@ -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.