gcstackbarrierall: setting gcstackbarrierall=1 installs stack barriers
in every stack frame, rather than in exponentially-spaced frames.
+ gcrescanstacks: setting gcrescanstacks=1 enables stack
+ re-scanning during the STW mark termination phase. This is
+ helpful for debugging if objects are being prematurely
+ garbage collected.
+
gcstoptheworld: setting gcstoptheworld=1 disables concurrent garbage collection,
making every garbage collection a stop-the-world event. Setting gcstoptheworld=2
also disables concurrent sweeping after the garbage collection finishes.
work.ndone = 0
work.nproc = uint32(gcprocs())
- if work.full == 0 && work.nDataRoots+work.nBSSRoots+work.nSpanRoots+work.nStackRoots+work.nRescanRoots == 0 {
+ if debug.gcrescanstacks == 0 && work.full == 0 && work.nDataRoots+work.nBSSRoots+work.nSpanRoots+work.nStackRoots+work.nRescanRoots == 0 {
// There's no work on the work queue and no root jobs
// that can produce work, so don't bother entering the
// getfull() barrier.
lock(&allglock)
// Check that stacks have been scanned.
- if gcphase == _GCmarktermination {
+ if gcphase == _GCmarktermination && debug.gcrescanstacks > 0 {
for i := 0; i < len(allgs); i++ {
gp := allgs[i]
if !(gp.gcscandone && gp.gcscanvalid) && readgstatus(gp) != _Gdead {
// gp.gcscanvalid. The caller must own gp and ensure that gp isn't
// already on the rescan list.
func queueRescan(gp *g) {
+ if debug.gcrescanstacks == 0 {
+ // Clear gcscanvalid to keep assertions happy.
+ //
+ // TODO: Remove gcscanvalid entirely when we remove
+ // stack rescanning.
+ gp.gcscanvalid = false
+ return
+ }
+
if gcphase == _GCoff {
gp.gcscanvalid = false
return
// dequeueRescan removes gp from the stack rescan list, if gp is on
// the rescan list. The caller must own gp.
func dequeueRescan(gp *g) {
+ if debug.gcrescanstacks == 0 {
+ return
+ }
+
if gp.gcRescan == -1 {
return
}
gcshrinkstackoff int32
gcstackbarrieroff int32
gcstackbarrierall int32
+ gcrescanstacks int32
gcstoptheworld int32
gctrace int32
invalidptr int32
{"gcshrinkstackoff", &debug.gcshrinkstackoff},
{"gcstackbarrieroff", &debug.gcstackbarrieroff},
{"gcstackbarrierall", &debug.gcstackbarrierall},
+ {"gcrescanstacks", &debug.gcrescanstacks},
{"gcstoptheworld", &debug.gcstoptheworld},
{"gctrace", &debug.gctrace},
{"invalidptr", &debug.invalidptr},
setTraceback(gogetenv("GOTRACEBACK"))
traceback_env = traceback_cache
+ if debug.gcrescanstacks == 0 {
+ // Without rescanning, there's no need for stack
+ // barriers.
+ debug.gcstackbarrieroff = 1
+ debug.gcstackbarrierall = 0
+ }
+
if debug.gcstackbarrierall > 0 {
firstStackBarrierOffset = 0
}