use crate::private;
#[derive(Default)]
pub struct TDesc<const B: bool>();
#[derive(Default)]
pub struct Asm(());
impl private::ArchDesc for TDesc<true> {
type Value = arch::Value;
#[inline(always)]
fn get_timer() -> Self::Value {
arch::get_timer()
}
}
impl private::ArchDesc for TDesc<false> {
type Value = arch_std::Value;
#[inline(always)]
fn get_timer() -> Self::Value {
arch_std::get_timer()
}
}
mod arch_std {
#[derive(Debug, Clone, Copy)]
pub struct Value(std::time::Instant);
impl super::private::Value for Value {
fn since(self, last: Self) -> crate::Delta {
(self.0 - last.0).as_nanos().into()
}
fn since_and_update(&mut self, now: Self) -> crate::Delta {
let delta = (now.0 - self.0).as_nanos().into();
*self = now;
delta
}
}
impl std::default::Default for Value {
fn default() -> Self {
Self(std::time::Instant::now())
}
}
#[inline(always)]
pub fn get_timer() -> Value {
Value(std::time::Instant::now())
}
}
#[cfg(not(any(target_arch = "aarch64", target_arch = "x86_64",)))]
use arch_std as arch;
#[cfg(target_arch = "aarch64")]
mod arch {
use std::arch::asm;
pub type Value = u64;
#[inline(always)]
pub fn get_timer() -> u64 {
let timer: u64;
unsafe {
asm!(
"isb
mrs {timer}, cntvct_el0",
timer = out(reg) timer,
);
}
timer
}
}
#[cfg(target_arch = "x86_64")]
mod arch {
use std::arch::asm;
pub type Value = u64;
#[inline(always)]
pub fn get_timer() -> Value {
let lo: u64;
let hi: u64;
unsafe {
asm!(
"
rdtsc
",
lateout("eax") lo,
lateout("edx") hi,
options(nomem, nostack)
);
}
hi << 32 | lo
}
}