#[cfg(any(target_os = "linux", target_os = "macos"))]
use crate::time::unix::UnixClock;
pub struct Timestamp {
sec: u64,
nano: u64,
}
#[repr(C)]
pub(crate) struct Timespec(Timestamp);
pub trait Clock {
fn precise() -> Timestamp;
}
#[cfg(target_os = "linux")]
pub type SystemClock = UnixClock;
#[cfg(any(target_os = "linux", target_os = "macos"))]
mod unix {
use core::mem::MaybeUninit;
use crate::time::Timespec;
pub struct UnixClock;
impl super::Clock for UnixClock {
fn precise() -> super::Timestamp {
let mut spec = MaybeUninit::uninit();
unsafe { (TIME)(0, &mut spec as *mut _ as *mut _) };
let super::Timespec(stamp) = unsafe { spec.assume_init() };
stamp
}
}
type Syscall = unsafe fn(i32, *mut Timespec) -> i32;
#[cfg(any(target_os = "linux"))]
const TIME: Syscall = super::linux::clock_gettime;
#[cfg(any(target_os = "macos"))]
const TIME: Syscall = super::macos::clock_gettime;
}
#[cfg(any(target_os = "linux"))]
mod linux {
use core::arch::asm;
use crate::time::Timespec;
pub unsafe fn clock_gettime(clock_id: i32, tp: *mut Timespec) -> i32 {
let mut ret: i32;
asm!(
"syscall",
in("rax") 228, in("rdi") clock_id,
in("rsi") tp,
lateout("rax") ret,
out("rcx") _,
out("r11") _,
);
ret
}
}
#[cfg(target_os = "macos")]
mod macos {
use crate::time::Timespec;
pub unsafe fn clock_gettime(clock_id: i32, tp: *mut Timespec) -> i32 {
let mut ret: i32;
asm!(
"syscall",
in("rax") 0x2000074, in("rdi") clock_id,
in("rsi") tp,
lateout("rax") ret,
out("rcx") _,
out("r11") _,
);
ret
}
}