use crate::errno::Errno;
use crate::{syscall_1, syscall_2};
pub use irox_enums::{EnumIterItem, EnumName};
pub const SYSCALL_TIMES: u64 = 100;
pub const SYSCALL_CLOCK_GETTIME: u64 = 228;
pub const SYSCALL_CLOCK_GETRES: u64 = 229;
pub type ClockT = u64;
#[derive(Debug, Copy, Clone, Eq, PartialEq, EnumName, EnumIterItem)]
#[repr(u32)]
pub enum ClockType {
Realtime = 0,
Monotonic = 1,
ProcessCPUTime = 2,
ThreadCPUTime = 3,
MonotonicRaw = 4,
RealtimeCoarse = 5,
MonotonicCoarse = 6,
BootTime = 7,
RealTimeAlarm = 8,
BootTimeAlarm = 9,
TAI = 11,
}
#[repr(C)]
#[derive(Default, Debug, Copy, Clone, Eq, PartialEq)]
pub struct Timespec {
pub tv_sec: u64,
pub tv_nsec: u64,
}
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub struct ClockTimespec {
pub timespec: Timespec,
pub clock: ClockType,
}
#[repr(C)]
#[derive(Default, Debug, Copy, Clone, Eq, PartialEq)]
pub struct Times {
pub tms_utime: ClockT,
pub tms_stime: ClockT,
pub tms_cutime: ClockT,
pub tms_cstime: ClockT,
}
pub fn clock_gettime(clock_type: ClockType) -> Result<ClockTimespec, Errno> {
let mut ts: Timespec = Default::default();
let ret = unsafe {
let ptr = core::ptr::from_mut(&mut ts);
syscall_2!(SYSCALL_CLOCK_GETTIME, clock_type as u64, ptr)
};
if ret != 0 {
return Err(ret.into());
}
Ok(ClockTimespec {
clock: clock_type,
timespec: ts,
})
}
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub struct ClockResolution {
pub clock: ClockType,
pub resolution_ns: u64,
}
pub fn clock_getres(clock_type: ClockType) -> Result<ClockResolution, Errno> {
let mut ts: Timespec = Default::default();
let ret = unsafe {
let ptr = core::ptr::from_mut(&mut ts);
syscall_2!(SYSCALL_CLOCK_GETRES, clock_type as u64, ptr)
};
if ret != 0 {
return Err(ret.into());
}
Ok(ClockResolution {
clock: clock_type,
resolution_ns: ts.tv_nsec,
})
}
#[derive(Default, Debug, Copy, Clone, Eq, PartialEq)]
pub struct TimesTicks {
pub times: Times,
pub ticks: u64,
}
pub fn times() -> Result<TimesTicks, Errno> {
let mut ts: Times = Default::default();
let ret = unsafe {
let ptr = core::ptr::from_mut(&mut ts);
syscall_1!(SYSCALL_TIMES, ptr)
};
if ret < 0 {
return Err(ret.into());
}
Ok(TimesTicks {
times: ts,
ticks: ret as u64,
})
}
#[cfg(test)]
mod tests {
use crate::errno::Errno;
use crate::time::*;
#[test]
pub fn test_clock_gettime() -> Result<(), Errno> {
let out = clock_gettime(ClockType::Realtime)?;
println!("{out:#?}");
for clock in ClockType::iter_items() {
let out = clock_gettime(clock);
println!("{clock:?}: {out:#?}");
}
Ok(())
}
#[test]
pub fn test_clock_getres() -> Result<(), Errno> {
let out = clock_getres(ClockType::Realtime)?;
println!("{out:#?}");
for clock in ClockType::iter_items() {
let out = clock_getres(clock);
println!("{clock:?}: {out:#?}");
}
Ok(())
}
#[test]
pub fn test_times() -> Result<(), Errno> {
let out = times()?;
println!("{out:#?}");
Ok(())
}
}