use std::io;
use std::ptr;
use std::time::Duration;
use crate::sync::AtomicU32;
#[allow(clippy::unnecessary_cast, clippy::unnecessary_fallible_conversions)]
pub(super) fn wait(word: &AtomicU32, expected: u32, timeout: Option<Duration>) {
let ts = timeout.map(|d| libc::timespec {
tv_sec: d.as_secs().try_into().unwrap_or(libc::time_t::MAX),
tv_nsec: d.subsec_nanos().try_into().unwrap_or(0),
});
let ts_ptr = ts.as_ref().map_or(ptr::null(), ptr::from_ref);
let r = unsafe {
libc::syscall(
libc::SYS_futex as libc::c_long,
word.as_ptr(),
libc::FUTEX_WAIT | libc::FUTEX_PRIVATE_FLAG,
expected,
ts_ptr,
)
};
if r < 0 {
let err = io::Error::last_os_error().raw_os_error();
debug_assert!(
matches!(err, Some(libc::EAGAIN | libc::EINTR | libc::ETIMEDOUT)),
"unexpected futex wait error: {err:?}"
);
}
}
#[allow(clippy::unnecessary_cast)]
pub(super) fn wake(word: &AtomicU32, all: bool) {
let count: libc::c_int = if all { libc::c_int::MAX } else { 1 };
unsafe {
libc::syscall(
libc::SYS_futex as libc::c_long,
word.as_ptr(),
libc::FUTEX_WAKE | libc::FUTEX_PRIVATE_FLAG,
count,
);
}
}