Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions builder/testdata/binary-size.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,5 @@ microbit examples/serial z 2985 439 8 2272
wioterminal examples/pininterrupt z 8314 1790 148 7512
cortex-m-qemu ./testdata/size-corpus z 9923 1301 80 4188
cortex-m-qemu ./testdata/size-corpus 2 17482 862 72 4188
riscv-qemu ./testdata/size-corpus z 17364 1028 88 16660
riscv-qemu ./testdata/size-corpus 2 24960 744 80 16652
riscv-qemu ./testdata/size-corpus z 17396 1028 88 16660
riscv-qemu ./testdata/size-corpus 2 24976 744 80 16652
4 changes: 2 additions & 2 deletions src/runtime/gc_stack_cores.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ 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 {
if secondaryCoresReady.Load() == 0 {
// Scan the stack(s) of the current core.
scanCurrentStack()
if !task.OnSystemStack() {
Expand Down Expand Up @@ -98,7 +98,7 @@ func scanstack(sp uintptr) {

// Resume the world after a call to gcMarkReachable.
func gcResumeWorld() {
if !secondaryCoresStarted {
if secondaryCoresReady.Load() == 0 {
// Nothing to do: the world wasn't stopped in gcMarkReachable.
return
}
Expand Down
4 changes: 4 additions & 0 deletions src/runtime/runtime_rp2.go
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,10 @@ func runCore1() {
// interrupts can still happen while the GC is running.
enableSIOFifoInterruptCore1()

// The stop-the-world interrupt must be enabled before the
// secondary core is allowed to enter the scheduler.
waitForSecondaryCoresReady()

// Now start running the scheduler on this core.
schedulerLock.Lock()
scheduler(false)
Expand Down
4 changes: 1 addition & 3 deletions src/runtime/runtime_rp2040_flashsafe_cores.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,7 @@ var rp2040FlashSafeState volatile.Register8
// With scheduler=cores it must not be called from an interrupt handler or with
// interrupts disabled; the GC stop-the-world path has the same constraint (see #5610).
func rp2040EnterFlashSafeSection() (interrupt.State, bool) {
// secondaryCoresStarted is set after startSecondaryCores() returns, so core 1
// may already run Go code in this window. The GC shares it (see #5610).
multicore := secondaryCoresStarted
multicore := secondaryCoresReady.Load() != 0
if !multicore {
return interrupt.Disable(), false
}
Expand Down
4 changes: 4 additions & 0 deletions src/runtime/runtime_tinygoriscv_qemu.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,10 @@ func main() {
// Also enable timer interrupts, for sleepTicksMulticore.
riscv.MIE.SetBits(riscv.MIE_MTIE)

// The stop-the-world interrupt must be enabled before the
// secondary core is allowed to enter the scheduler.
waitForSecondaryCoresReady()

// Now start running the scheduler on this core.
schedulerLock.Lock()
scheduler(false)
Expand Down
11 changes: 8 additions & 3 deletions src/runtime/scheduler_cores.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,13 @@ const hasParallelism = true

var mainExited atomic.Uint32

// True after the secondary cores have started.
var secondaryCoresStarted bool
// Non-zero when secondary cores may enter the scheduler.
var secondaryCoresReady atomic.Uint32

func waitForSecondaryCoresReady() {
for secondaryCoresReady.Load() == 0 {
}
}

// Which task is running on a given core (or nil if there is no task running on
// the core).
Expand Down Expand Up @@ -190,7 +195,7 @@ func run() {

// After package initializers have finished, start all the other cores.
startSecondaryCores()
secondaryCoresStarted = true
secondaryCoresReady.Store(1)

// Run main.main.
callMain()
Expand Down
5 changes: 5 additions & 0 deletions src/runtime/scheduler_notcores.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
//go:build !scheduler.cores

package runtime

func waitForSecondaryCoresReady() {}
Loading