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}