moto_rt/
futex.rs

1use crate::RtVdsoVtable;
2use core::sync::atomic::{AtomicU32, Ordering};
3
4/// An atomic for use as a futex that is at least 8-bits but may be larger.
5pub type Futex = AtomicU32;
6/// An atomic for use as a futex that is at least 8-bits but may be larger.
7pub type SmallFutex = AtomicU32;
8/// Must be the underlying type of Futex.
9pub type SmallPrimitive = u32;
10/// Must be the underlying type of Futex.
11pub type Primitive = u32;
12
13/// Returns false on timeout.
14pub fn futex_wait(futex: &AtomicU32, expected: u32, timeout: Option<core::time::Duration>) -> bool {
15    let vdso_futex_wait: extern "C" fn(*const AtomicU32, u32, u64) -> u32 = unsafe {
16        core::mem::transmute(
17            RtVdsoVtable::get().futex_wait.load(Ordering::Relaxed) as usize as *const (),
18        )
19    };
20
21    let timo = if let Some(timo) = timeout {
22        let timo_128 = timo.as_nanos();
23        if timo_128 > u64::MAX as u128 {
24            u64::MAX
25        } else {
26            timo_128 as u64
27        }
28    } else {
29        u64::MAX
30    };
31
32    match vdso_futex_wait(futex, expected, timo) {
33        0 => false,
34        1 => true,
35        _ => panic!(),
36    }
37}
38
39pub fn futex_wake(futex: &AtomicU32) -> bool {
40    let vdso_futex_wake: extern "C" fn(*const AtomicU32) -> u32 = unsafe {
41        core::mem::transmute(
42            RtVdsoVtable::get().futex_wake.load(Ordering::Relaxed) as usize as *const (),
43        )
44    };
45
46    match vdso_futex_wake(futex) {
47        0 => false,
48        1 => true,
49        _ => panic!(),
50    }
51}
52
53pub fn futex_wake_all(futex: &AtomicU32) {
54    let vdso_futex_wake_all: extern "C" fn(*const AtomicU32) = unsafe {
55        core::mem::transmute(
56            RtVdsoVtable::get().futex_wake_all.load(Ordering::Relaxed) as usize as *const (),
57        )
58    };
59
60    vdso_futex_wake_all(futex)
61}