| 1 | use std::time::Instant; |
| 2 | |
| 3 | use crate::time::{fence, FineDuration, Timer, TimerKind}; |
| 4 | |
| 5 | mod tsc; |
| 6 | |
| 7 | pub(crate) use tsc::*; |
| 8 | |
| 9 | /// A measurement timestamp. |
| 10 | #[derive (Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] |
| 11 | pub(crate) enum Timestamp { |
| 12 | /// Time provided by the operating system. |
| 13 | Os(Instant), |
| 14 | |
| 15 | /// [CPU timestamp counter](https://en.wikipedia.org/wiki/Time_Stamp_Counter). |
| 16 | Tsc(TscTimestamp), |
| 17 | } |
| 18 | |
| 19 | impl Timestamp { |
| 20 | #[inline (always)] |
| 21 | pub fn start(timer_kind: TimerKind) -> Self { |
| 22 | fence::full_fence(); |
| 23 | let value: Timestamp = match timer_kind { |
| 24 | TimerKind::Os => Self::Os(Instant::now()), |
| 25 | TimerKind::Tsc => Self::Tsc(TscTimestamp::start()), |
| 26 | }; |
| 27 | fence::compiler_fence(); |
| 28 | value |
| 29 | } |
| 30 | |
| 31 | pub fn duration_since(self, earlier: Self, timer: Timer) -> FineDuration { |
| 32 | match (self, earlier, timer) { |
| 33 | (Self::Os(this: Instant), Self::Os(earlier: Instant), Timer::Os) => this.duration_since(earlier).into(), |
| 34 | (Self::Tsc(this: TscTimestamp), Self::Tsc(earlier: TscTimestamp), Timer::Tsc { frequency: NonZero }) => { |
| 35 | this.duration_since(earlier, frequency) |
| 36 | } |
| 37 | _ => unreachable!(), |
| 38 | } |
| 39 | } |
| 40 | } |
| 41 | |
| 42 | /// A [`Timestamp`] where the variant is determined by an external source of |
| 43 | /// truth. |
| 44 | /// |
| 45 | /// By making the variant tag external to this type, we produce more optimized |
| 46 | /// code by: |
| 47 | /// - Reusing the same condition variable |
| 48 | /// - Reducing the size of the timestamp variables |
| 49 | #[derive (Clone, Copy)] |
| 50 | pub(crate) union UntaggedTimestamp { |
| 51 | /// [`Timestamp::Os`]. |
| 52 | pub os: Instant, |
| 53 | |
| 54 | /// [`Timestamp::Tsc`]. |
| 55 | pub tsc: TscTimestamp, |
| 56 | } |
| 57 | |
| 58 | impl UntaggedTimestamp { |
| 59 | #[inline (always)] |
| 60 | pub fn start(timer_kind: TimerKind) -> Self { |
| 61 | fence::full_fence(); |
| 62 | let value = match timer_kind { |
| 63 | TimerKind::Os => Self { os: Instant::now() }, |
| 64 | TimerKind::Tsc => Self { tsc: TscTimestamp::start() }, |
| 65 | }; |
| 66 | fence::compiler_fence(); |
| 67 | value |
| 68 | } |
| 69 | |
| 70 | #[inline (always)] |
| 71 | pub fn end(timer_kind: TimerKind) -> Self { |
| 72 | fence::compiler_fence(); |
| 73 | let value = match timer_kind { |
| 74 | TimerKind::Os => Self { os: Instant::now() }, |
| 75 | TimerKind::Tsc => Self { tsc: TscTimestamp::end() }, |
| 76 | }; |
| 77 | fence::full_fence(); |
| 78 | value |
| 79 | } |
| 80 | |
| 81 | #[inline (always)] |
| 82 | pub unsafe fn into_timestamp(self, timer_kind: TimerKind) -> Timestamp { |
| 83 | match timer_kind { |
| 84 | TimerKind::Os => Timestamp::Os(self.os), |
| 85 | TimerKind::Tsc => Timestamp::Tsc(self.tsc), |
| 86 | } |
| 87 | } |
| 88 | } |
| 89 | |