1#![allow(dead_code)]
2
3#[cfg(not(target_arch = "aarch64"))]
4pub use generic::*;
5
6#[cfg(target_arch = "aarch64")]
7pub use aarch64::*;
8
9mod generic {
10 pub fn now() -> std::time::Instant {
11 std::time::Instant::now()
12 }
13}
14
15#[cfg(target_arch = "aarch64")]
16mod aarch64 {
17 use std::arch::asm;
18 use std::time::Duration;
19
20 pub struct Timestamp(u64);
21
22 impl Timestamp {
23 pub fn elapsed(&self) -> Duration {
24 let diff = timestamp().saturating_sub(self.0) as f64;
25 let secs = diff / frequency() as f64;
26 std::time::Duration::from_secs_f64(secs)
27 }
28 }
29
30 pub fn now() -> Timestamp {
31 Timestamp(timestamp())
32 }
33
34 #[inline]
35 fn frequency() -> u64 {
36 unsafe {
37 let frequency: u64;
38 asm!(
39 "mrs {}, cntfrq_el0",
40 out(reg) frequency,
41 options(nomem, nostack, preserves_flags, pure),
42 );
43 frequency
44 }
45 }
46
47 #[inline(always)]
48 fn timestamp() -> u64 {
49 unsafe {
50 let timestamp: u64;
51 asm!(
52 "mrs {}, cntvct_el0",
53 out(reg) timestamp,
54 options(nostack, preserves_flags),
56 );
57 timestamp
58 }
59 }
60}