twizzler_abi/syscall/time/
clock.rs

1use bitflags::bitflags;
2
3use super::{ClockSource, FemtoSeconds, ReadClockFlags, ReadClockListFlags, TimeSpan};
4
5bitflags! {
6    /// Flags about a given clock or clock read.
7    #[derive(Debug, Clone, Copy)]
8    pub struct ClockFlags: u32 {
9        const MONOTONIC = 1;
10    }
11}
12
13#[derive(Clone, Copy, Debug)]
14#[repr(C)]
15/// Information about a given clock source, including precision and current clock value.
16pub struct ClockInfo {
17    current: TimeSpan,
18    precision: FemtoSeconds,
19    resolution: FemtoSeconds,
20    flags: ClockFlags,
21}
22
23impl ClockInfo {
24    pub const ZERO: ClockInfo = ClockInfo::new(
25        TimeSpan::ZERO,
26        FemtoSeconds(0),
27        FemtoSeconds(0),
28        ClockFlags::MONOTONIC,
29    );
30
31    /// Construct a new ClockInfo. You probably want to be getting these from
32    /// [super::sys_read_clock_info], though.
33    pub const fn new(
34        current: TimeSpan,
35        precision: FemtoSeconds,
36        resolution: FemtoSeconds,
37        flags: ClockFlags,
38    ) -> Self {
39        Self {
40            current,
41            precision,
42            resolution,
43            flags,
44        }
45    }
46
47    /// Get the precision of a clock source.
48    pub fn precision(&self) -> FemtoSeconds {
49        self.precision
50    }
51
52    /// Get the resolution of a clock source.
53    pub fn resolution(&self) -> FemtoSeconds {
54        self.resolution
55    }
56
57    /// Get the current value of a clock source.
58    pub fn current_value(&self) -> TimeSpan {
59        self.current
60    }
61
62    /// Is the clock source monotonic?
63    pub fn is_monotonic(&self) -> bool {
64        self.flags.contains(ClockFlags::MONOTONIC)
65    }
66}
67
68/// Different kinds of clocks exposed by the kernel.
69#[derive(Clone, Copy, Debug)]
70#[repr(C)]
71pub enum ClockKind {
72    Unknown,
73    Monotonic,
74    RealTime,
75}
76
77impl From<ClockKind> for u64 {
78    fn from(clock: ClockKind) -> Self {
79        match clock {
80            ClockKind::Monotonic => 0,
81            ClockKind::RealTime => 1,
82            ClockKind::Unknown => 2,
83        }
84    }
85}
86
87impl From<u64> for ClockKind {
88    fn from(x: u64) -> Self {
89        match x {
90            0 => ClockKind::Monotonic,
91            1 => ClockKind::RealTime,
92            _ => ClockKind::Unknown,
93        }
94    }
95}
96
97/// ID used internally to read the appropriate clock source.
98#[derive(Clone, Copy, Debug)]
99#[repr(transparent)]
100pub struct ClockID(pub u64);
101
102#[allow(dead_code)]
103// abstract representation of a clock source to users
104#[derive(Clone, Copy, Debug)]
105pub struct Clock {
106    pub info: ClockInfo,
107    id: ClockID,
108    kind: ClockKind,
109}
110
111impl Clock {
112    pub const ZERO: Clock = Clock {
113        info: ClockInfo::ZERO,
114        id: ClockID(0),
115        kind: ClockKind::Unknown,
116    };
117
118    pub fn new(info: ClockInfo, id: ClockID, kind: ClockKind) -> Clock {
119        Self { info, id, kind }
120    }
121
122    pub fn read(&self) -> TimeSpan {
123        match super::sys_read_clock_info(ClockSource::ID(self.id), ReadClockFlags::empty()) {
124            Ok(ci) => ci.current_value(),
125            _ => TimeSpan::ZERO,
126        }
127    }
128
129    pub fn info(&self) -> ClockInfo {
130        self.info
131    }
132
133    /// Returns a new instance of a Clock from the specified ClockKind
134    pub fn get(kind: ClockKind) -> Clock {
135        let mut clk = [Clock::ZERO];
136        if let Ok(filled) =
137            super::sys_read_clock_list(kind, &mut clk, 0, ReadClockListFlags::FIRST_KIND)
138        {
139            if filled > 0 {
140                return clk[0];
141            }
142        }
143        Clock::ZERO
144    }
145
146    pub fn set(&mut self, info: ClockInfo, id: ClockID, kind: ClockKind) {
147        self.info = info;
148        self.id = id;
149        self.kind = kind;
150    }
151}