fix(gc): pause all cores before scanning stack and globals.

In gcMarkReachable, busy-wait for other cores to enter the interrupt handler and pause before scanning the GC core's stack or globals. Prevents data race where a running core relocates heap references to globals during mark phase.
This commit is contained in:
Konstantin Sharlaimov
2026-07-14 20:31:48 +02:00
committed by Ron Evans
parent 213d10838f
commit 7a9c649268
+6 -7
View File
@@ -43,6 +43,12 @@ func gcMarkReachable() {
gcPauseCore(i)
}
// Busy-wait until all the other cores are ready.
for gcScanState.Load() != numCPU {
spinLoopWait()
}
gcScanState.Store(0)
// Scan the stack(s) of the current core.
scanCurrentStack()
if !task.OnSystemStack() {
@@ -53,13 +59,6 @@ func gcMarkReachable() {
// Scan globals.
findGlobals(markRoots)
// Busy-wait until all the other cores are ready. They certainly should be,
// after the scanning we did above.
for gcScanState.Load() != numCPU {
spinLoopWait()
}
gcScanState.Store(0)
// Signal each core in turn that they can scan the stack.
for i := uint32(0); i < numCPU; i++ {
if i == core {