use core::{mem};
use crate::{
kty::{clockid_t, c_int, TIMER_ABSTIME, TFD_NONBLOCK},
syscall::{
clock_gettime, clock_settime, clock_getres, clock_nanosleep, timerfd_create
},
time::{timer::{Timer}, Time, time_from_timespec, time_to_timespec},
util::retry::{retry},
result::{Result},
lmem,
fd::{FdContainer},
};
#[derive(Pod, Copy, Clone, PartialEq, Eq)]
pub struct Clock(pub clockid_t);
pub const REAL: Clock = Clock(0);
pub const REAL_COARSE: Clock = Clock(5);
pub const MONO: Clock = Clock(1);
pub const MONO_COARSE: Clock = Clock(6);
pub const MONO_RAW: Clock = Clock(4);
pub const PROCESS: Clock = Clock(2);
pub const THREAD: Clock = Clock(3);
pub const BOOT: Clock = Clock(7);
impl Clock {
pub fn get_time(self) -> Result<Time> {
let mut timespec = lmem::zeroed();
rv!(clock_gettime(self.0, &mut timespec))?;
Ok(time_from_timespec(timespec))
}
pub fn set_time(self, t: Time) -> Result {
let timespec = time_to_timespec(t);
rv!(clock_settime(self.0, ×pec))
}
pub fn resolution(self) -> Result<Time> {
let mut timespec = lmem::zeroed();
rv!(clock_getres(self.0, &mut timespec))?;
Ok(time_from_timespec(timespec))
}
pub fn sleep_to(self, t: Time) -> Result {
let time = time_to_timespec(t);
let mut rem = lmem::zeroed();
retry(|| clock_nanosleep(self.0, TIMER_ABSTIME, &time, &mut rem)).map(|_| ())
}
pub fn sleep_for(self, t: Time) -> Result {
let now = self.get_time()?;
self.sleep_to(now + t)
}
pub fn timer(self) -> Result<Timer> {
let timer = rv!(timerfd_create(self.0, 0), -> c_int)?;
Ok(Timer::from_owned(timer))
}
pub fn timer_non_blocking(self) -> Result<Timer> {
let timer = rv!(timerfd_create(self.0, TFD_NONBLOCK), -> c_int)?;
Ok(Timer::from_owned(timer))
}
}