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