use core::sync::atomic::{AtomicU64, Ordering};
use core::time::Duration;
use uefi::boot::stall;
#[inline(always)]
pub fn tick() -> u64 {
#[cfg(target_arch = "x86")]
unsafe { core::arch::x86::_rdtsc() }
#[cfg(target_arch = "x86_64")]
unsafe { core::arch::x86_64::_rdtsc() }
#[cfg(target_arch = "aarch64")]
unsafe {
let mut ticks: u64;
core::arch::asm!("mrs {}, cntvct_el0", out(reg) ticks);
ticks
}
}
#[deprecated(since = "0.2.4", note = "Use `FREQ.hz()` instead")]
pub fn calc_freq_blocking() -> u64 {
let start = tick();
stall(Duration::from_millis(100));
let end = tick();
let ticks_per_100ms = end - start;
ticks_per_100ms * 10
}
#[derive(Debug)]
pub struct ClockFreq { hz: AtomicU64, ms: AtomicU64, us: AtomicU64, ns: AtomicU64, ps: AtomicU64 }
impl ClockFreq {
#[inline(always)]
pub fn hz(&self) -> u64 { self.hz.load(Ordering::Relaxed) }
#[inline(always)]
pub fn ms(&self) -> u64 { self.ms.load(Ordering::Relaxed) }
#[inline(always)]
pub fn us(&self) -> u64 { self.us.load(Ordering::Relaxed) }
#[inline(always)]
pub fn ns(&self) -> u64 { self.ns.load(Ordering::Relaxed) }
#[inline(always)]
pub fn ps(&self) -> u64 { self.ps.load(Ordering::Relaxed) }
}
pub static FREQ: ClockFreq = ClockFreq {
hz: AtomicU64::new(0), ms: AtomicU64::new(0), us: AtomicU64::new(0),
ns: AtomicU64::new(0), ps: AtomicU64::new(0),
};
pub(crate) fn init_clock_freq() -> u64 {
let start = tick();
stall(Duration::from_millis(50)); let end = tick();
let ticks_per_50ms = end - start;
let hz = ticks_per_50ms * 20;
FREQ.hz.store(hz, Ordering::Relaxed);
FREQ.ms.store((hz / 1000).max(1), Ordering::Relaxed);
FREQ.us.store((hz / 100_0000).max(1), Ordering::Relaxed);
FREQ.ns.store((hz / 10_0000_0000).max(1), Ordering::Relaxed);
FREQ.ps.store(hz / 1_0000_0000_0000, Ordering::Relaxed);
hz
}