1 | //! RDTSC instructions. |
2 | |
3 | #[cfg (test)] |
4 | use stdarch_test::assert_instr; |
5 | |
6 | /// Reads the current value of the processor’s time-stamp counter. |
7 | /// |
8 | /// The processor monotonically increments the time-stamp counter MSR |
9 | /// every clock cycle and resets it to 0 whenever the processor is |
10 | /// reset. |
11 | /// |
12 | /// The RDTSC instruction is not a serializing instruction. It does |
13 | /// not necessarily wait until all previous instructions have been |
14 | /// executed before reading the counter. Similarly, subsequent |
15 | /// instructions may begin execution before the read operation is |
16 | /// performed. |
17 | /// |
18 | /// On processors that support the Intel 64 architecture, the |
19 | /// high-order 32 bits of each of RAX and RDX are cleared. |
20 | /// |
21 | /// [Intel's documentation](https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_rdtsc) |
22 | #[inline ] |
23 | #[cfg_attr (test, assert_instr(rdtsc))] |
24 | #[stable (feature = "simd_x86" , since = "1.27.0" )] |
25 | pub unsafe fn _rdtsc() -> u64 { |
26 | rdtsc() |
27 | } |
28 | |
29 | /// Reads the current value of the processor’s time-stamp counter and |
30 | /// the `IA32_TSC_AUX MSR`. |
31 | /// |
32 | /// The processor monotonically increments the time-stamp counter MSR |
33 | /// every clock cycle and resets it to 0 whenever the processor is |
34 | /// reset. |
35 | /// |
36 | /// The RDTSCP instruction waits until all previous instructions have |
37 | /// been executed before reading the counter. However, subsequent |
38 | /// instructions may begin execution before the read operation is |
39 | /// performed. |
40 | /// |
41 | /// On processors that support the Intel 64 architecture, the |
42 | /// high-order 32 bits of each of RAX, RDX, and RCX are cleared. |
43 | /// |
44 | /// [Intel's documentation](https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=__rdtscp) |
45 | #[inline ] |
46 | #[cfg_attr (test, assert_instr(rdtscp))] |
47 | #[stable (feature = "simd_x86" , since = "1.27.0" )] |
48 | pub unsafe fn __rdtscp(aux: *mut u32) -> u64 { |
49 | rdtscp(aux as *mut _) |
50 | } |
51 | |
52 | #[allow (improper_ctypes)] |
53 | extern "C" { |
54 | #[link_name = "llvm.x86.rdtsc" ] |
55 | fn rdtsc() -> u64; |
56 | #[link_name = "llvm.x86.rdtscp" ] |
57 | fn rdtscp(aux: *mut u8) -> u64; |
58 | } |
59 | |
60 | #[cfg (test)] |
61 | mod tests { |
62 | use crate::core_arch::x86::*; |
63 | use stdarch_test::simd_test; |
64 | |
65 | #[simd_test(enable = "sse2" )] |
66 | unsafe fn _rdtsc() { |
67 | let r = rdtsc::_rdtsc(); |
68 | assert_ne!(r, 0); // The chances of this being 0 are infinitesimal |
69 | } |
70 | |
71 | #[simd_test(enable = "sse2" )] |
72 | unsafe fn _rdtscp() { |
73 | let mut aux = 0; |
74 | let r = rdtsc::__rdtscp(&mut aux); |
75 | assert_ne!(r, 0); // The chances of this being 0 are infinitesimal |
76 | } |
77 | } |
78 | |