Skip to content

Commit

Permalink
Add ARM support. (#91)
Browse files Browse the repository at this point in the history
  • Loading branch information
tobz committed Sep 25, 2023
1 parent ff7abb9 commit 8ba2515
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 29 deletions.
25 changes: 19 additions & 6 deletions src/clocks/counter.rs
Original file line number Diff line number Diff line change
@@ -1,19 +1,32 @@
#[cfg(all(target_arch = "x86_64", target_feature = "sse2"))]
use core::arch::x86_64::_rdtsc;

#[derive(Clone, Debug, Default)]
pub struct Counter;

#[cfg(all(target_arch = "x86_64", target_feature = "sse2"))]
impl Counter {
pub fn now(&self) -> u64 {
unsafe { _rdtsc() }
unsafe { ::core::arch::x86_64::_rdtsc() }
}
}

#[cfg(target_arch = "aarch64")]
impl Counter {
pub fn now(&self) -> u64 {
let count: u64;

unsafe {
::core::arch::asm!("mrs {}, cntvct_el0", out(reg) count);
}

count
}
}

#[cfg(not(all(target_arch = "x86_64", target_feature = "sse2")))]
#[cfg(not(any(
all(target_arch = "x86_64", target_feature = "sse2"),
target_arch = "aarch64",
)))]
impl Counter {
pub fn now(&self) -> u64 {
panic!("can't use counter without TSC support");
panic!("can't use counter without TSC (x86_64) or system counter (ARM) support");
}
}
28 changes: 28 additions & 0 deletions src/detection.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#[allow(dead_code)]
#[cfg(all(target_arch = "x86_64", target_feature = "sse2"))]
pub fn has_counter_support() -> bool {
let cpuid = raw_cpuid::CpuId::new();
let has_invariant_tsc = cpuid
.get_advanced_power_mgmt_info()
.map_or(false, |apm| apm.has_invariant_tsc());
let has_rdtscp = cpuid
.get_extended_processor_and_feature_identifiers()
.map_or(false, |epf| epf.has_rdtscp());

has_invariant_tsc && has_rdtscp
}

#[cfg(target_arch = "aarch64")]
pub fn has_counter_support() -> bool {
// AArch64 implies ARMv8 or above, where the system counter is always present.
true
}

#[allow(dead_code)]
#[cfg(not(any(
all(target_arch = "x86_64", target_feature = "sse2"),
target_arch = "aarch64",
)))]
pub fn has_counter_support() -> bool {
false
}
27 changes: 4 additions & 23 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,7 @@ use once_cell::sync::OnceCell;

mod clocks;
use self::clocks::{Counter, Monotonic};
mod detection;
mod mock;
pub use self::mock::{IntoNanoseconds, Mock};
mod instant;
Expand Down Expand Up @@ -201,7 +202,7 @@ impl Calibration {
ref_time: 0,
src_time: 0,
scale_factor: 1,
scale_shift: 1,
scale_shift: 0,
}
}

Expand Down Expand Up @@ -314,8 +315,8 @@ impl Clock {
/// Support for TSC, etc, are checked at the time of creation, not compile-time.
pub fn new() -> Clock {
let reference = Monotonic::default();
let inner = if has_tsc_support() {
let source = Counter::default();
let inner = if detection::has_counter_support() {
let source = Counter;
let calibration = GLOBAL_CALIBRATION.get_or_init(|| {
let mut calibration = Calibration::new();
calibration.calibrate(reference, &source);
Expand Down Expand Up @@ -540,26 +541,6 @@ fn mul_div_po2_u64(value: u64, numer: u64, denom: u32) -> u64 {
v as u64
}

#[allow(dead_code)]
#[cfg(all(target_arch = "x86_64", target_feature = "sse2"))]
fn has_tsc_support() -> bool {
let cpuid = raw_cpuid::CpuId::new();
let has_invariant_tsc = cpuid
.get_advanced_power_mgmt_info()
.map_or(false, |apm| apm.has_invariant_tsc());
let has_rdtscp = cpuid
.get_extended_processor_and_feature_identifiers()
.map_or(false, |epf| epf.has_rdtscp());

has_invariant_tsc && has_rdtscp
}

#[allow(dead_code)]
#[cfg(not(all(target_arch = "x86_64", target_feature = "sse2")))]
fn has_tsc_support() -> bool {
false
}

#[cfg(test)]
pub mod tests {
use super::{Clock, Counter, Monotonic};
Expand Down

0 comments on commit 8ba2515

Please sign in to comment.