tract_libcli/
time.rs

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                // Leave off `nomem` because this should be a compiler fence.
55                options(nostack, preserves_flags),
56            );
57            timestamp
58        }
59    }
60}