use moa_uapi::{
error::{ERR_FAULT, ERR_INVAL, ERR_TIMEOUT},
futex::FutexWaiter,
sysnr::{
SYSNR_FUTEX_REQUEUE, SYSNR_FUTEX_WAIT, SYSNR_FUTEX_WAITV, SYSNR_FUTEX_WAKE,
SYSNR_ROBUST_LIST_SET,
},
types::Timeout,
};
pub type Result<T> = core::result::Result<T, FutexError>;
define_syscall_error! {
pub enum FutexError {
Inval = ERR_INVAL,
Fault = ERR_FAULT,
Timeout = ERR_TIMEOUT,
}
}
#[allow(clippy::cast_possible_truncation)]
pub fn futex_wait(uaddr: *const u32, expected: u32, timeout: Timeout) -> Result<()> {
let ret = unsafe {
super::arch::syscall3(
SYSNR_FUTEX_WAIT,
uaddr as usize,
expected as usize,
timeout.raw() as usize,
)
};
if ret < 0 { Err(FutexError::from_raw(ret)) } else { Ok(()) }
}
#[allow(clippy::cast_sign_loss, clippy::cast_possible_truncation)]
pub fn futex_waitv(waiters: &[FutexWaiter], timeout: Timeout) -> Result<u32> {
let ret = unsafe {
super::arch::syscall3(
SYSNR_FUTEX_WAITV,
waiters.as_ptr() as usize,
waiters.len(),
timeout.raw() as usize,
)
};
if ret < 0 { Err(FutexError::from_raw(ret)) } else { Ok(ret as u32) }
}
#[allow(clippy::cast_sign_loss, clippy::cast_possible_truncation)]
pub fn futex_wake(uaddr: *const u32, nr_wake: u32) -> Result<u32> {
let ret = unsafe { super::arch::syscall2(SYSNR_FUTEX_WAKE, uaddr as usize, nr_wake as usize) };
if ret < 0 { Err(FutexError::from_raw(ret)) } else { Ok(ret as u32) }
}
#[allow(clippy::cast_sign_loss, clippy::cast_possible_truncation)]
pub fn futex_requeue(src: *const u32, dst: *const u32, nr_wake: u32, nr_move: u32) -> Result<u32> {
let ret = unsafe {
super::arch::syscall4(
SYSNR_FUTEX_REQUEUE,
src as usize,
dst as usize,
nr_wake as usize,
nr_move as usize,
)
};
if ret < 0 { Err(FutexError::from_raw(ret)) } else { Ok(ret as u32) }
}
pub fn robust_list_set(head: *const u8) -> Result<()> {
let ret = unsafe { super::arch::syscall1(SYSNR_ROBUST_LIST_SET, head as usize) };
if ret < 0 { Err(FutexError::from_raw(ret)) } else { Ok(()) }
}