//go:build moxie.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()) // Spin on event loop until woken. Wake() pops from stack and // sets RunState to RunStateResuming as a signal. t := Current() t.RunState = RunStatePaused for t.RunState == RunStatePaused { eventLoopTick() } return true } // Wake a single waiter. func (f *Futex) Wake() { if t := f.waiters.Pop(); t != nil { t.RunState = RunStateResuming scheduleTask(t) } } // Wake all waiters. func (f *Futex) WakeAll() { for t := f.waiters.Pop(); t != nil; t = f.waiters.Pop() { t.RunState = RunStateResuming scheduleTask(t) } }