twizzler_abi/syscall/time/
mod.rs

1mod clock;
2mod timedefs;
3mod units;
4
5use core::mem::MaybeUninit;
6
7use bitflags::bitflags;
8pub use clock::*;
9pub use timedefs::*;
10use twizzler_rt_abi::Result;
11pub use units::*;
12
13use super::{convert_codes_to_result, twzerr, Syscall};
14use crate::arch::syscall::raw_syscall;
15
16bitflags! {
17    /// Flags to pass to [`sys_read_clock_info`].
18    #[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Ord, Eq)]
19    pub struct ReadClockFlags: u32 {
20
21    }
22
23    /// Flags to pass to [`sys_read_clock_list`].
24    #[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Ord, Eq)]
25    pub struct ReadClockListFlags: u32 {
26        /// Fill the buffer with all clocks from the clock list, for every `ClockKind`.
27        const ALL_CLOCKS = 1 << 0;
28        /// Fill the buffer with only clocks from a given `ClockKind` list.
29        const ONLY_KIND = 1 << 1;
30        /// Fill the buffer with the first clock in the `ClockKind` list.
31        const FIRST_KIND = 1 << 2;
32    }
33}
34
35/// Possible clock sources.
36#[derive(Clone, Copy, Debug)]
37#[repr(C)]
38pub enum ClockSource {
39    BestMonotonic,
40    BestRealTime,
41    ID(ClockID),
42}
43
44impl From<u64> for ClockSource {
45    fn from(value: u64) -> Self {
46        match value {
47            0 => Self::BestMonotonic,
48            1 => Self::BestRealTime,
49            _ => Self::ID(ClockID(value)),
50        }
51    }
52}
53
54impl From<ClockSource> for u64 {
55    fn from(source: ClockSource) -> Self {
56        match source {
57            ClockSource::BestMonotonic => 0,
58            ClockSource::BestRealTime => 1,
59            ClockSource::ID(clk) => clk.0,
60        }
61    }
62}
63
64/// Read information about a give clock, as specified by clock source.
65pub fn sys_read_clock_info(clock_source: ClockSource, flags: ReadClockFlags) -> Result<ClockInfo> {
66    let mut clock_info = MaybeUninit::uninit();
67    let (code, val) = unsafe {
68        raw_syscall(
69            Syscall::ReadClockInfo,
70            &[
71                clock_source.into(),
72                &mut clock_info as *mut MaybeUninit<ClockInfo> as usize as u64,
73                flags.bits() as u64,
74            ],
75        )
76    };
77    convert_codes_to_result(
78        code,
79        val,
80        |c, _| c != 0,
81        |_, _| unsafe { clock_info.assume_init() },
82        twzerr,
83    )
84}
85
86/// Discover a list of clock sources exposed by the kernel.
87///
88/// This returns a list of clocks stored in `clocks` and the number of
89/// entries filled. By default, one clock from every type of clock
90/// exposed ([`ClockKind`]), is returned. All information in [`ClockInfo`]
91/// except the current value is also returned. For each type of clock with more
92/// than one clock source, the first one is returned. Users can get a list of
93/// all clocks, and thus all clock sources, for a particular type by
94/// specifying the [`ClockKind`] and setting the appropriate flag.
95///
96/// Users are expected to provide a slice, `clocks`, to be filled by the kernel.
97/// `start` indicates what offset into the list of clocks the kernel should fill
98/// the `clocks` buffer from. When there are no more clocks to read from a given
99/// `start` offset, then the value 0 is returned.
100///
101/// # Examples
102///
103/// ```no_run
104/// let mut clocks = [Clock::ZERO; 4];
105/// let result = sys_read_clock_list(
106///     ClockKind::Monotonic,
107///     &mut clocks,
108///     0,
109///     ReadClockListFlags::FIRST_KIND,
110/// );
111/// if let Some(filled) = result {
112///     if filled > 0 {
113///         println!("time now: {}", clock[0].read().as_nanos());
114///     }
115/// }
116/// ```
117pub fn sys_read_clock_list(
118    clock: ClockKind,
119    clocks: &mut [Clock],
120    start: u64,
121    flags: ReadClockListFlags,
122) -> Result<usize> {
123    let (code, val) = unsafe {
124        raw_syscall(
125            Syscall::ReadClockList,
126            &[
127                clock.into(),
128                clocks.as_mut_ptr() as u64,
129                clocks.len() as u64,
130                start,
131                flags.bits() as u64,
132            ],
133        )
134    };
135    convert_codes_to_result(code, val, |c, _| c != 0, |_, v| v as usize, twzerr)
136}