mirror of
https://github.com/tinygo-org/tinygo.git
synced 2026-08-06 12:03:41 +00:00
runtime: don't try to interrupt other cores before they are started
The GC shouldn't try to interrupt other cores before they are started. For example, it would be possible for the GC to run in a package initializer (which is currently run on a single core). That would suggest questionable program design, but it is something that should work. So this commit makes sure the GC only tries to scan the stack of other cores when those other cores have in fact started.
This commit is contained in:
committed by
Ron Evans
parent
e395c94e5f
commit
f7d8502572
@@ -14,6 +14,24 @@ var gcScanState atomic.Uint32
|
||||
// Start GC scan by pausing the world (all other cores) and scanning their
|
||||
// stacks. It doesn't resume the world.
|
||||
func gcMarkReachable() {
|
||||
// If the other cores haven't started yet (for example, when a GC cycle
|
||||
// happens during init()), we only need to scan the stack of the current
|
||||
// core.
|
||||
if !secondaryCoresStarted {
|
||||
// Scan the stack(s) of the current core.
|
||||
scanCurrentStack()
|
||||
if !task.OnSystemStack() {
|
||||
// Mark system stack.
|
||||
markRoots(task.SystemStack(), stackTop)
|
||||
}
|
||||
|
||||
// Scan globals.
|
||||
findGlobals(markRoots)
|
||||
|
||||
// Nothing more to do: the other cores haven't started yet.
|
||||
return
|
||||
}
|
||||
|
||||
core := currentCPU()
|
||||
|
||||
// Interrupt all other cores.
|
||||
@@ -81,6 +99,11 @@ func scanstack(sp uintptr) {
|
||||
|
||||
// Resume the world after a call to gcMarkReachable.
|
||||
func gcResumeWorld() {
|
||||
if !secondaryCoresStarted {
|
||||
// Nothing to do: the world wasn't stopped in gcMarkReachable.
|
||||
return
|
||||
}
|
||||
|
||||
// Signal each core that they can resume.
|
||||
hartID := currentCPU()
|
||||
for i := uint32(0); i < numCPU; i++ {
|
||||
|
||||
@@ -14,6 +14,9 @@ const hasParallelism = true
|
||||
|
||||
var mainExited atomic.Uint32
|
||||
|
||||
// True after the secondary cores have started.
|
||||
var secondaryCoresStarted bool
|
||||
|
||||
// Which task is running on a given core (or nil if there is no task running on
|
||||
// the core).
|
||||
var cpuTasks [numCPU]*task.Task
|
||||
@@ -141,6 +144,7 @@ func run() {
|
||||
|
||||
// After package initializers have finished, start all the other cores.
|
||||
startSecondaryCores()
|
||||
secondaryCoresStarted = true
|
||||
|
||||
// Run main.main.
|
||||
callMain()
|
||||
|
||||
Reference in New Issue
Block a user