mirror of
https://github.com/tinygo-org/tinygo.git
synced 2026-08-13 15:33:40 +00:00
60f8a62978
This commit adds support for a scheduler that runs a scheduler on all available cores. It is meant to be used on baremetal systems with a fixed number of cores, such as the RP2040. The initial implementation adds support for multicore scheduling to the riscv-qemu target as a convenient testing target. This means that this new multicore scheduler is tested in CI, including a bunch of standard library tests (`make tinygo-test-baremetal`). This should ensure the new scheduler is reasonably well tested before trying to use it on harder-to-debug targets like the RP2040.
47 lines
1.1 KiB
Go
47 lines
1.1 KiB
Go
//go:build tinygo.unicore
|
|
|
|
package task
|
|
|
|
// A futex is a way for userspace to wait with the pointer as the key, and for
|
|
// another thread to wake one or all waiting threads keyed on the same pointer.
|
|
//
|
|
// A futex does not change the underlying value, it only reads it before to prevent
|
|
// lost wake-ups.
|
|
type Futex struct {
|
|
Uint32
|
|
waiters Stack
|
|
}
|
|
|
|
// Atomically check for cmp to still be equal to the futex value and if so, go
|
|
// to sleep. Return true if we were definitely awoken by a call to Wake or
|
|
// WakeAll, and false if we can't be sure of that.
|
|
func (f *Futex) Wait(cmp uint32) (awoken bool) {
|
|
if f.Uint32.v != cmp {
|
|
return false
|
|
}
|
|
|
|
// Push the current goroutine onto the waiter stack.
|
|
f.waiters.Push(Current())
|
|
|
|
// Pause until the waiters are awoken by Wake/WakeAll.
|
|
Pause()
|
|
|
|
// We were awoken by a call to Wake or WakeAll. There is no chance for
|
|
// spurious wakeups.
|
|
return true
|
|
}
|
|
|
|
// Wake a single waiter.
|
|
func (f *Futex) Wake() {
|
|
if t := f.waiters.Pop(); t != nil {
|
|
scheduleTask(t)
|
|
}
|
|
}
|
|
|
|
// Wake all waiters.
|
|
func (f *Futex) WakeAll() {
|
|
for t := f.waiters.Pop(); t != nil; t = f.waiters.Pop() {
|
|
scheduleTask(t)
|
|
}
|
|
}
|