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