#[cfg(feature = "tsc")]
pub mod counter {
#[cfg(target_arch = "x86_64")]
#[must_use]
pub fn read() -> u64 {
unsafe { core::arch::x86_64::_rdtsc() }
}
#[cfg(target_arch = "aarch64")]
#[must_use]
pub fn read() -> u64 {
let v: u64;
unsafe {
core::arch::asm!("mrs {}, cntvct_el0", out(reg) v, options(nomem, nostack));
}
v
}
#[cfg(target_arch = "x86_64")]
#[must_use]
pub fn invariant_counter_supported() -> bool {
let max_leaf = core::arch::x86_64::__cpuid_count(0x8000_0000, 0).eax;
if max_leaf < 0x8000_0007 {
return false;
}
let invariant = core::arch::x86_64::__cpuid_count(0x8000_0007, 0).edx;
invariant & (1 << 8) != 0
}
#[cfg(target_arch = "aarch64")]
#[must_use]
pub fn counter_frequency_hz() -> Option<u64> {
let v: u64;
unsafe {
core::arch::asm!("mrs {}, cntfrq_el0", out(reg) v, options(nomem, nostack));
}
if v == 0 {
None
} else {
Some(v)
}
}
}
#[cfg(all(feature = "libc", not(feature = "std")))]
pub(crate) fn clock_gettime_ns(clock: libc::clockid_t) -> Option<u64> {
let mut ts = libc::timespec {
tv_sec: 0,
tv_nsec: 0,
};
unsafe {
if libc::clock_gettime(clock, &raw mut ts) == 0 {
#[allow(clippy::unnecessary_cast)]
Some(
(ts.tv_sec as u64)
.saturating_mul(1_000_000_000)
.saturating_add(ts.tv_nsec as u64),
)
} else {
None
}
}
}
#[cfg(all(feature = "libc", target_os = "linux"))]
pub(crate) fn clock_gettime_ns_i64(clock: libc::clockid_t) -> Option<i64> {
let mut ts = libc::timespec {
tv_sec: 0,
tv_nsec: 0,
};
unsafe {
if libc::clock_gettime(clock, &raw mut ts) == 0 {
#[allow(clippy::unnecessary_cast)]
Some(
(ts.tv_sec as i64)
.saturating_mul(1_000_000_000)
.saturating_add(ts.tv_nsec as i64),
)
} else {
None
}
}
}