1use crate::{
2 Clock,
3 wrapping_u64::{U64Calibration, WrappingU64Instant, WrappingU64Time},
4};
5
6#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
11pub struct Tsc(());
12
13impl Clock for Tsc {
14 type Time = WrappingU64Time;
15 type Calibration = U64Calibration;
16
17 #[inline(always)]
18 fn now(&self) -> WrappingU64Instant {
19 WrappingU64Instant(unsafe { core::arch::x86_64::_rdtsc() })
20 }
21}
22
23#[derive(Debug)]
25#[non_exhaustive]
26pub struct TscUnavailable;
27
28impl core::fmt::Display for TscUnavailable {
29 fn fmt(&self, formatter: &mut core::fmt::Formatter) -> core::fmt::Result {
30 formatter.write_str("No stable TSC available")
31 }
32}
33
34#[cfg(feature = "std")]
35impl std::error::Error for TscUnavailable {}
36
37impl Tsc {
38 pub fn try_new_assume_stable() -> Result<Self, TscUnavailable> {
43 let edx = core::arch::x86_64::__cpuid(1).edx;
44 if (edx & (1 << 4)) != 0 {
45 Ok(Tsc(()))
46 } else {
47 Err(TscUnavailable)
48 }
49 }
50
51 #[cfg(all(target_os = "linux", feature = "std"))]
56 pub fn try_new_linux_sys() -> Result<Self, TscUnavailable> {
57 let stable_tsc_detected = std::fs::read_to_string(
58 "/sys/devices/system/clocksource/clocksource0/available_clocksource",
59 )
60 .is_ok_and(|x| x.contains("tsc"));
61 if stable_tsc_detected {
62 Ok(Tsc(()))
63 } else {
64 Err(TscUnavailable)
65 }
66 }
67}