use sc::syscall;
use crate::platform::{ClockId, TimeSpec};
use crate::Result;
#[inline]
#[must_use]
pub fn clock_get_real_time() -> TimeSpec {
let mut ts = core::mem::MaybeUninit::uninit();
unsafe {
syscall!(CLOCK_GETTIME, ClockId::CLOCK_REALTIME.0, ts.as_mut_ptr());
ts.assume_init()
}
}
#[inline]
#[must_use]
pub fn clock_get_monotonic_time() -> TimeSpec {
let mut ts = core::mem::MaybeUninit::uninit();
unsafe {
syscall!(CLOCK_GETTIME, ClockId::CLOCK_MONOTONIC.0, ts.as_mut_ptr());
ts.assume_init()
}
}
#[inline]
pub fn clock_get_time(clock_id: ClockId) -> Result<TimeSpec> {
let mut ts = core::mem::MaybeUninit::zeroed();
let res = unsafe { syscall!(CLOCK_GETTIME, clock_id.0, ts.as_mut_ptr()) };
bail_on_below_zero!(res, "`CLOCK_GETTIME` syscall failed");
Ok(unsafe { ts.assume_init() })
}
#[cfg(test)]
mod tests {
use crate::error::Errno;
use crate::platform::ClockId;
use crate::time::{clock_get_monotonic_time, clock_get_real_time, clock_get_time};
#[test]
fn get_monotonic() {
let t1 = clock_get_monotonic_time();
let t2 = clock_get_monotonic_time();
assert!(t1 < t2);
}
#[test]
fn get_real() {
let t1 = clock_get_real_time();
let t2 = clock_get_real_time();
assert!(t1 < t2);
}
#[test]
fn get_clock_specified() {
let t1_mono = clock_get_monotonic_time();
let t2_mono = clock_get_time(ClockId::CLOCK_MONOTONIC).unwrap();
assert!(t2_mono > t1_mono);
assert!(t2_mono.seconds() - t2_mono.seconds() <= 1);
let t1_real = clock_get_real_time();
let t2_real = clock_get_time(ClockId::CLOCK_REALTIME).unwrap();
assert!(t2_real > t1_real);
assert!(t2_real.seconds() - t2_real.seconds() <= 1);
expect_errno!(Errno::EINVAL, clock_get_time(ClockId::from(99999)));
}
}