gp.waitsince = work.tstart
}
- // Shrink a stack if not much of it is being used but not in the scan phase.
- if gcphase == _GCmarktermination {
- // Shrink during STW GCmarktermination phase thus avoiding
- // complications introduced by shrinking during
- // non-STW phases.
+ if gcphase == _GCmarktermination && status == _Gdead {
+ // Free gp's stack if necessary. Only do this
+ // during mark termination because otherwise
+ // _Gdead may be transient.
shrinkstack(gp)
}
throw("can't scan gchelper stack")
}
+ // Shrink the stack if not much of it is being used. During
+ // concurrent GC, we can do this during concurrent mark.
+ if !work.markrootDone {
+ shrinkstack(gp)
+ }
+
+ // Prepare for stack barrier insertion/removal.
var sp, barrierOffset, nextBarrier uintptr
if gp.syscallsp != 0 {
sp = gp.syscallsp
throw("scanstack in wrong phase")
}
+ // Scan the stack.
var cache pcvalueCache
gcw := &getg().m.p.ptr().gcw
n := 0
// Called at garbage collection time.
// gp must be stopped, but the world need not be.
func shrinkstack(gp *g) {
- if readgstatus(gp) == _Gdead {
+ gstatus := readgstatus(gp)
+ if gstatus&^_Gscan == _Gdead {
if gp.stack.lo != 0 {
// Free whole stack - it will get reallocated
// if G is used again.
if gp.stack.lo == 0 {
throw("missing stack in shrinkstack")
}
+ if gstatus&_Gscan == 0 {
+ throw("bad status in shrinkstack")
+ }
if debug.gcshrinkstackoff > 0 {
return
print("shrinking stack ", oldsize, "->", newsize, "\n")
}
- oldstatus := casgcopystack(gp)
copystack(gp, newsize, false)
- casgstatus(gp, _Gcopystack, oldstatus)
}
// freeStackSpans frees unused stack spans at the end of GC.