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}