aboutsummaryrefslogtreecommitdiff
path: root/src/runtime/mgcmark.go
diff options
context:
space:
mode:
Diffstat (limited to 'src/runtime/mgcmark.go')
-rw-r--r--src/runtime/mgcmark.go11
1 files changed, 9 insertions, 2 deletions
diff --git a/src/runtime/mgcmark.go b/src/runtime/mgcmark.go
index 8340f39a4b..5aabc14b40 100644
--- a/src/runtime/mgcmark.go
+++ b/src/runtime/mgcmark.go
@@ -18,6 +18,7 @@ import (
const (
fixedRootFinalizers = iota
fixedRootFreeGStacks
+ fixedRootCleanups
fixedRootCount
// rootBlockBytes is the number of bytes to scan per data or
@@ -179,8 +180,6 @@ func markroot(gcw *gcWork, i uint32, flushBgCredit bool) int64 {
case i == fixedRootFinalizers:
for fb := allfin; fb != nil; fb = fb.alllink {
cnt := uintptr(atomic.Load(&fb.cnt))
- // Finalizers that contain cleanups only have fn set. None of the other
- // fields are necessary.
scanblock(uintptr(unsafe.Pointer(&fb.fin[0])), cnt*unsafe.Sizeof(fb.fin[0]), &finptrmask[0], gcw, nil)
}
@@ -189,6 +188,14 @@ func markroot(gcw *gcWork, i uint32, flushBgCredit bool) int64 {
// stackfree.
systemstack(markrootFreeGStacks)
+ case i == fixedRootCleanups:
+ for cb := (*cleanupBlock)(gcCleanups.all.Load()); cb != nil; cb = cb.alllink {
+ // N.B. This only needs to synchronize with cleanup execution, which only resets these blocks.
+ // All cleanup queueing happens during sweep.
+ n := uintptr(atomic.Load(&cb.n))
+ scanblock(uintptr(unsafe.Pointer(&cb.cleanups[0])), n*goarch.PtrSize, &cleanupBlockPtrMask[0], gcw, nil)
+ }
+
case work.baseSpans <= i && i < work.baseStacks:
// mark mspan.specials
markrootSpans(gcw, int(i-work.baseSpans))