Skip to content

Commit 3bfc9df

Browse files
committed
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/13947 Reviewed-by: Russ Cox <[email protected]>
1 parent e2bb03f commit 3bfc9df

File tree

4 files changed

+23
-13
lines changed

4 files changed

+23
-13
lines changed

src/runtime/extern.go

+3
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,9 @@ It is a comma-separated list of name=val pairs setting these named variables:
4747
that allow the garbage collector to avoid repeating a stack scan during the
4848
mark termination phase.
4949
50+
gcstackbarrierall: setting gcstackbarrierall=1 installs stack barriers
51+
in every stack frame, rather than in exponentially-spaced frames.
52+
5053
gcstoptheworld: setting gcstoptheworld=1 disables concurrent garbage collection,
5154
making every garbage collection a stop-the-world event. Setting gcstoptheworld=2
5255
also disables concurrent sweeping after the garbage collection finishes.

src/runtime/mgc.go

+13-12
Original file line numberDiff line numberDiff line change
@@ -133,25 +133,26 @@ const (
133133
_RootFlushCaches = 4
134134
_RootCount = 5
135135

136-
// firstStackBarrierOffset is the approximate byte offset at
137-
// which to place the first stack barrier from the current SP.
138-
// This is a lower bound on how much stack will have to be
139-
// re-scanned during mark termination. Subsequent barriers are
140-
// placed at firstStackBarrierOffset * 2^n offsets.
141-
//
142-
// For debugging, this can be set to 0, which will install a
143-
// stack barrier at every frame. If you do this, you may also
144-
// have to raise _StackMin, since the stack barrier
145-
// bookkeeping will use a large amount of each stack.
146-
firstStackBarrierOffset = 1024
147-
debugStackBarrier = false
136+
debugStackBarrier = false
148137

149138
// sweepMinHeapDistance is a lower bound on the heap distance
150139
// (in bytes) reserved for concurrent sweeping between GC
151140
// cycles. This will be scaled by gcpercent/100.
152141
sweepMinHeapDistance = 1024 * 1024
153142
)
154143

144+
// firstStackBarrierOffset is the approximate byte offset at
145+
// which to place the first stack barrier from the current SP.
146+
// This is a lower bound on how much stack will have to be
147+
// re-scanned during mark termination. Subsequent barriers are
148+
// placed at firstStackBarrierOffset * 2^n offsets.
149+
//
150+
// For debugging, this can be set to 0, which will install a
151+
// stack barrier at every frame. If you do this, you may also
152+
// have to raise _StackMin, since the stack barrier
153+
// bookkeeping will use a large amount of each stack.
154+
var firstStackBarrierOffset = 1024
155+
155156
// heapminimum is the minimum heap size at which to trigger GC.
156157
// For small heaps, this overrides the usual GOGC*live set rule.
157158
//

src/runtime/mgcmark.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -341,7 +341,7 @@ func scanstack(gp *g) {
341341
switch gcphase {
342342
case _GCscan:
343343
// Install stack barriers during stack scan.
344-
barrierOffset = firstStackBarrierOffset
344+
barrierOffset = uintptr(firstStackBarrierOffset)
345345
nextBarrier = sp + barrierOffset
346346

347347
if debug.gcstackbarrieroff > 0 {

src/runtime/runtime1.go

+6
Original file line numberDiff line numberDiff line change
@@ -310,6 +310,7 @@ var debug struct {
310310
gcpacertrace int32
311311
gcshrinkstackoff int32
312312
gcstackbarrieroff int32
313+
gcstackbarrierall int32
313314
gcstoptheworld int32
314315
gctrace int32
315316
invalidptr int32
@@ -327,6 +328,7 @@ var dbgvars = []dbgVar{
327328
{"gcpacertrace", &debug.gcpacertrace},
328329
{"gcshrinkstackoff", &debug.gcshrinkstackoff},
329330
{"gcstackbarrieroff", &debug.gcstackbarrieroff},
331+
{"gcstackbarrierall", &debug.gcstackbarrierall},
330332
{"gcstoptheworld", &debug.gcstoptheworld},
331333
{"gctrace", &debug.gctrace},
332334
{"invalidptr", &debug.invalidptr},
@@ -382,6 +384,10 @@ func parsedebugvars() {
382384
if islibrary || isarchive {
383385
traceback_cache |= 1
384386
}
387+
388+
if debug.gcstackbarrierall > 0 {
389+
firstStackBarrierOffset = 0
390+
}
385391
}
386392

387393
// Poor mans 64-bit division.

0 commit comments

Comments
 (0)