/rust/registry/src/index.crates.io-1949cf8c6b5b557f/x86-0.47.0/src/time.rs
Line | Count | Source |
1 | | //! Functions to read time stamp counters on x86. |
2 | | |
3 | | use crate::arch::{__rdtscp, _rdtsc}; |
4 | | |
5 | | /// Read the time stamp counter. |
6 | | /// |
7 | | /// The RDTSC instruction is not a serializing instruction. |
8 | | /// It does not necessarily wait until all previous instructions |
9 | | /// have been executed before reading the counter. Similarly, |
10 | | /// subsequent instructions may begin execution before the |
11 | | /// read operation is performed. If software requires RDTSC to be |
12 | | /// executed only after all previous instructions have completed locally, |
13 | | /// it can either use RDTSCP or execute the sequence LFENCE;RDTSC. |
14 | | /// |
15 | | /// # Safety |
16 | | /// * Causes a GP fault if the TSD flag in register CR4 is set and the CPL |
17 | | /// is greater than 0. |
18 | 0 | pub unsafe fn rdtsc() -> u64 { |
19 | 0 | _rdtsc() as u64 |
20 | 0 | } |
21 | | |
22 | | /// Read the time stamp counter. |
23 | | /// |
24 | | /// The RDTSCP instruction waits until all previous instructions |
25 | | /// have been executed before reading the counter. |
26 | | /// However, subsequent instructions may begin execution |
27 | | /// before the read operation is performed. |
28 | | /// |
29 | | /// Volatile is used here because the function may be used to act as |
30 | | /// an instruction barrier. |
31 | | /// |
32 | | /// # Safety |
33 | | /// * Causes a GP fault if the TSD flag in register CR4 is set and the |
34 | | /// CPL is greater than 0. |
35 | 0 | pub unsafe fn rdtscp() -> u64 { |
36 | 0 | let mut _aux = 0; |
37 | 0 | __rdtscp(&mut _aux) |
38 | 0 | } |
39 | | |
40 | | #[cfg(all(test, feature = "utest"))] |
41 | | mod test { |
42 | | use super::*; |
43 | | |
44 | | #[test] |
45 | | fn check_rdtsc() { |
46 | | let cpuid = crate::cpuid::CpuId::new(); |
47 | | let has_tsc = cpuid |
48 | | .get_feature_info() |
49 | | .map_or(false, |finfo| finfo.has_tsc()); |
50 | | |
51 | | if has_tsc { |
52 | | unsafe { |
53 | | assert!(rdtsc() > 0, "rdtsc returned 0, unlikely!"); |
54 | | } |
55 | | } |
56 | | } |
57 | | |
58 | | #[test] |
59 | | fn check_rdtscp() { |
60 | | let cpuid = crate::cpuid::CpuId::new(); |
61 | | let has_rdtscp = cpuid |
62 | | .get_extended_processor_and_feature_identifiers() |
63 | | .map_or(false, |einfo| einfo.has_rdtscp()); |
64 | | |
65 | | if has_rdtscp { |
66 | | unsafe { |
67 | | assert!(rdtscp() > 0, "rdtscp returned 0, unlikely!"); |
68 | | } |
69 | | } |
70 | | } |
71 | | } |