1 //go:build moxie.unicore
2 3 package task
4 5 // A futex is a way for userspace to wait with the pointer as the key, and for
6 // another thread to wake one or all waiting threads keyed on the same pointer.
7 //
8 // A futex does not change the underlying value, it only reads it before to prevent
9 // lost wake-ups.
10 type Futex struct {
11 Uint32
12 waiters Stack
13 }
14 15 // Atomically check for cmp to still be equal to the futex value and if so, go
16 // to sleep. Return true if we were definitely awoken by a call to Wake or
17 // WakeAll, and false if we can't be sure of that.
18 func (f *Futex) Wait(cmp uint32) (awoken bool) {
19 if f.Uint32.v != cmp {
20 return false
21 }
22 23 // Push the current goroutine onto the waiter stack.
24 f.waiters.Push(Current())
25 26 // Spin on event loop until woken. Wake() pops from stack and
27 // sets RunState to RunStateResuming as a signal.
28 t := Current()
29 t.RunState = RunStatePaused
30 for t.RunState == RunStatePaused {
31 eventLoopTick()
32 }
33 34 return true
35 }
36 37 // Wake a single waiter.
38 func (f *Futex) Wake() {
39 if t := f.waiters.Pop(); t != nil {
40 t.RunState = RunStateResuming
41 scheduleTask(t)
42 }
43 }
44 45 // Wake all waiters.
46 func (f *Futex) WakeAll() {
47 for t := f.waiters.Pop(); t != nil; t = f.waiters.Pop() {
48 t.RunState = RunStateResuming
49 scheduleTask(t)
50 }
51 }
52