]> Cypherpunks repositories - gostls13.git/commitdiff
runtime: capture pause stack for late gcWork put debugging
authorAustin Clements <austin@google.com>
Mon, 17 Dec 2018 19:39:05 +0000 (14:39 -0500)
committerAustin Clements <austin@google.com>
Mon, 17 Dec 2018 21:24:19 +0000 (21:24 +0000)
This captures the stack trace where mark completion observed that each
P had no work, and then dumps this if that P later discovers more
work. Hopefully this will help bound where the work was created.

For #27993.

Change-Id: I4f29202880d22c433482dc1463fb50ab693b6de6
Reviewed-on: https://go-review.googlesource.com/c/154599
Run-TryBot: Austin Clements <austin@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Michael Knyszek <mknyszek@google.com>
src/runtime/mgc.go
src/runtime/mgcwork.go

index 622750ed2ea9e56179e6084b677fec3c30a06689..36d48d2561c4f1fbebe50d9ce3971e3d56ff4b01 100644 (file)
@@ -1453,6 +1453,11 @@ top:
                                // there's a paused gcWork, then
                                // that's a bug.
                                _p_.gcw.pauseGen = gcWorkPauseGen
+                               // Capture the G's stack.
+                               for i := range _p_.gcw.pauseStack {
+                                       _p_.gcw.pauseStack[i] = 0
+                               }
+                               callers(1, _p_.gcw.pauseStack[:])
                        }
                })
                casgstatus(gp, _Gwaiting, _Grunning)
index cdc94b8ffb11ee525001edc750bb7602a28021d6..0ed07134423e23bb0959cfc57ae0093e833cda19 100644 (file)
@@ -97,6 +97,10 @@ type gcWork struct {
        // pauseGen causes put operations to spin while pauseGen ==
        // gcWorkPauseGen if debugCachedWork is true.
        pauseGen uint32
+
+       // pauseStack is the stack at which this P was paused if
+       // debugCachedWork is true.
+       pauseStack [16]uintptr
 }
 
 // Most of the methods of gcWork are go:nowritebarrierrec because the
@@ -128,6 +132,23 @@ func (w *gcWork) checkPut(ptr uintptr, ptrs []uintptr) {
                        for _, ptr := range ptrs {
                                gcDumpObject("ptrs", ptr, ^uintptr(0))
                        }
+                       println("runtime: paused at")
+                       for _, pc := range w.pauseStack {
+                               if pc == 0 {
+                                       break
+                               }
+                               f := findfunc(pc)
+                               if f.valid() {
+                                       // Obviously this doesn't
+                                       // relate to ancestor
+                                       // tracebacks, but this
+                                       // function prints what we
+                                       // want.
+                                       printAncestorTracebackFuncInfo(f, pc)
+                               } else {
+                                       println("\tunknown PC ", hex(pc), "\n")
+                               }
+                       }
                        throw("throwOnGCWork")
                }
        }