Commit 3bfc9df2 authored by Austin Clements's avatar Austin Clements

runtime: add GODEBUG for stack barriers at every frame

Currently enabling the debugging mode where stack barriers are
installed at every frame requires recompiling the runtime. However,
this is potentially useful for field debugging and for runtime tests,
so make this mode a GODEBUG.

Updates #12238.

Change-Id: I6fb128f598b19568ae723a612e099c0ed96917f5
Reviewed-on: https://go-review.googlesource.com/13947Reviewed-by: default avatarRuss Cox <rsc@golang.org>
parent e2bb03f1
...@@ -47,6 +47,9 @@ It is a comma-separated list of name=val pairs setting these named variables: ...@@ -47,6 +47,9 @@ It is a comma-separated list of name=val pairs setting these named variables:
that allow the garbage collector to avoid repeating a stack scan during the that allow the garbage collector to avoid repeating a stack scan during the
mark termination phase. mark termination phase.
gcstackbarrierall: setting gcstackbarrierall=1 installs stack barriers
in every stack frame, rather than in exponentially-spaced frames.
gcstoptheworld: setting gcstoptheworld=1 disables concurrent garbage collection, gcstoptheworld: setting gcstoptheworld=1 disables concurrent garbage collection,
making every garbage collection a stop-the-world event. Setting gcstoptheworld=2 making every garbage collection a stop-the-world event. Setting gcstoptheworld=2
also disables concurrent sweeping after the garbage collection finishes. also disables concurrent sweeping after the garbage collection finishes.
......
...@@ -133,18 +133,7 @@ const ( ...@@ -133,18 +133,7 @@ const (
_RootFlushCaches = 4 _RootFlushCaches = 4
_RootCount = 5 _RootCount = 5
// firstStackBarrierOffset is the approximate byte offset at debugStackBarrier = false
// which to place the first stack barrier from the current SP.
// This is a lower bound on how much stack will have to be
// re-scanned during mark termination. Subsequent barriers are
// placed at firstStackBarrierOffset * 2^n offsets.
//
// For debugging, this can be set to 0, which will install a
// stack barrier at every frame. If you do this, you may also
// have to raise _StackMin, since the stack barrier
// bookkeeping will use a large amount of each stack.
firstStackBarrierOffset = 1024
debugStackBarrier = false
// sweepMinHeapDistance is a lower bound on the heap distance // sweepMinHeapDistance is a lower bound on the heap distance
// (in bytes) reserved for concurrent sweeping between GC // (in bytes) reserved for concurrent sweeping between GC
...@@ -152,6 +141,18 @@ const ( ...@@ -152,6 +141,18 @@ const (
sweepMinHeapDistance = 1024 * 1024 sweepMinHeapDistance = 1024 * 1024
) )
// firstStackBarrierOffset is the approximate byte offset at
// which to place the first stack barrier from the current SP.
// This is a lower bound on how much stack will have to be
// re-scanned during mark termination. Subsequent barriers are
// placed at firstStackBarrierOffset * 2^n offsets.
//
// For debugging, this can be set to 0, which will install a
// stack barrier at every frame. If you do this, you may also
// have to raise _StackMin, since the stack barrier
// bookkeeping will use a large amount of each stack.
var firstStackBarrierOffset = 1024
// heapminimum is the minimum heap size at which to trigger GC. // heapminimum is the minimum heap size at which to trigger GC.
// For small heaps, this overrides the usual GOGC*live set rule. // For small heaps, this overrides the usual GOGC*live set rule.
// //
......
...@@ -341,7 +341,7 @@ func scanstack(gp *g) { ...@@ -341,7 +341,7 @@ func scanstack(gp *g) {
switch gcphase { switch gcphase {
case _GCscan: case _GCscan:
// Install stack barriers during stack scan. // Install stack barriers during stack scan.
barrierOffset = firstStackBarrierOffset barrierOffset = uintptr(firstStackBarrierOffset)
nextBarrier = sp + barrierOffset nextBarrier = sp + barrierOffset
if debug.gcstackbarrieroff > 0 { if debug.gcstackbarrieroff > 0 {
......
...@@ -310,6 +310,7 @@ var debug struct { ...@@ -310,6 +310,7 @@ var debug struct {
gcpacertrace int32 gcpacertrace int32
gcshrinkstackoff int32 gcshrinkstackoff int32
gcstackbarrieroff int32 gcstackbarrieroff int32
gcstackbarrierall int32
gcstoptheworld int32 gcstoptheworld int32
gctrace int32 gctrace int32
invalidptr int32 invalidptr int32
...@@ -327,6 +328,7 @@ var dbgvars = []dbgVar{ ...@@ -327,6 +328,7 @@ var dbgvars = []dbgVar{
{"gcpacertrace", &debug.gcpacertrace}, {"gcpacertrace", &debug.gcpacertrace},
{"gcshrinkstackoff", &debug.gcshrinkstackoff}, {"gcshrinkstackoff", &debug.gcshrinkstackoff},
{"gcstackbarrieroff", &debug.gcstackbarrieroff}, {"gcstackbarrieroff", &debug.gcstackbarrieroff},
{"gcstackbarrierall", &debug.gcstackbarrierall},
{"gcstoptheworld", &debug.gcstoptheworld}, {"gcstoptheworld", &debug.gcstoptheworld},
{"gctrace", &debug.gctrace}, {"gctrace", &debug.gctrace},
{"invalidptr", &debug.invalidptr}, {"invalidptr", &debug.invalidptr},
...@@ -382,6 +384,10 @@ func parsedebugvars() { ...@@ -382,6 +384,10 @@ func parsedebugvars() {
if islibrary || isarchive { if islibrary || isarchive {
traceback_cache |= 1 traceback_cache |= 1
} }
if debug.gcstackbarrierall > 0 {
firstStackBarrierOffset = 0
}
} }
// Poor mans 64-bit division. // Poor mans 64-bit division.
......
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