//go:nowritebarrier
func scanstack(gp *g) {
if gp.gcscanvalid {
- if gcphase == _GCmarktermination {
- gcRemoveStackBarriers(gp)
- }
return
}
} else {
sp = gp.sched.sp
}
+ gcLockStackBarriers(gp) // Not necessary during mark term, but harmless.
switch gcphase {
case _GCmark:
// Install stack barriers during stack scan.
nextBarrier = ^uintptr(0)
}
- if gp.stkbarPos != 0 || len(gp.stkbar) != 0 {
- // If this happens, it's probably because we
- // scanned a stack twice in the same phase.
- print("stkbarPos=", gp.stkbarPos, " len(stkbar)=", len(gp.stkbar), " goid=", gp.goid, " gcphase=", gcphase, "\n")
- throw("g already has stack barriers")
- }
-
- gcLockStackBarriers(gp)
+ // Remove any existing stack barriers before we
+ // install new ones.
+ gcRemoveStackBarriers(gp)
case _GCmarktermination:
+ if !work.markrootDone {
+ // This is a STW GC. There may be stale stack
+ // barriers from an earlier cycle since we
+ // never passed through mark phase.
+ gcRemoveStackBarriers(gp)
+ }
+
if int(gp.stkbarPos) == len(gp.stkbar) {
// gp hit all of the stack barriers (or there
// were none). Re-scan the whole stack.
}
}
- gcRemoveStackBarriers(gp)
-
default:
throw("scanstack in wrong phase")
}
if gcphase == _GCmarktermination {
gcw.dispose()
}
- if gcphase == _GCmark {
- gcUnlockStackBarriers(gp)
- }
+ gcUnlockStackBarriers(gp)
gp.gcscanvalid = true
}
}
// gcRemoveStackBarriers removes all stack barriers installed in gp's stack.
+//
+// gp's stack barriers must be locked.
+//
//go:nowritebarrier
func gcRemoveStackBarriers(gp *g) {
if debugStackBarrier && gp.stkbarPos != 0 {
print("hit ", gp.stkbarPos, " stack barriers, goid=", gp.goid, "\n")
}
- gcLockStackBarriers(gp)
-
// Remove stack barriers that we didn't hit.
for _, stkbar := range gp.stkbar[gp.stkbarPos:] {
gcRemoveStackBarrier(gp, stkbar)
// adjust them.
gp.stkbarPos = 0
gp.stkbar = gp.stkbar[:0]
-
- gcUnlockStackBarriers(gp)
}
// gcRemoveStackBarrier removes a single stack barrier. It is the