rustix/backend/libc/time/
types.rs

1#[cfg(any(
2    linux_kernel,
3    target_os = "freebsd",
4    target_os = "fuchsia",
5    target_os = "illumos",
6    target_os = "netbsd"
7))]
8use crate::backend::c;
9#[cfg(any(
10    linux_kernel,
11    target_os = "freebsd",
12    target_os = "fuchsia",
13    target_os = "illumos",
14    target_os = "netbsd"
15))]
16use crate::time::Itimerspec;
17#[cfg(any(
18    linux_kernel,
19    target_os = "freebsd",
20    target_os = "fuchsia",
21    target_os = "illumos",
22    target_os = "netbsd"
23))]
24#[cfg(fix_y2038)]
25use crate::timespec::LibcTimespec;
26#[cfg(any(
27    linux_kernel,
28    target_os = "freebsd",
29    target_os = "fuchsia",
30    target_os = "illumos",
31    target_os = "netbsd"
32))]
33use bitflags::bitflags;
34
35/// On most platforms, `LibcItimerspec` is just `Itimerspec`.
36#[cfg(any(
37    linux_kernel,
38    target_os = "freebsd",
39    target_os = "fuchsia",
40    target_os = "illumos",
41    target_os = "netbsd"
42))]
43#[cfg(not(fix_y2038))]
44pub(crate) type LibcItimerspec = Itimerspec;
45
46/// On 32-bit glibc platforms, `LibcTimespec` differs from `Timespec`, so we
47/// define our own struct, with bidirectional `From` impls.
48#[cfg(any(
49    linux_kernel,
50    target_os = "freebsd",
51    target_os = "fuchsia",
52    target_os = "illumos",
53    target_os = "netbsd"
54))]
55#[cfg(fix_y2038)]
56#[repr(C)]
57#[derive(Debug, Clone)]
58pub(crate) struct LibcItimerspec {
59    pub it_interval: LibcTimespec,
60    pub it_value: LibcTimespec,
61}
62
63#[cfg(any(
64    linux_kernel,
65    target_os = "freebsd",
66    target_os = "fuchsia",
67    target_os = "illumos",
68    target_os = "netbsd"
69))]
70#[cfg(fix_y2038)]
71impl From<LibcItimerspec> for Itimerspec {
72    #[inline]
73    fn from(t: LibcItimerspec) -> Self {
74        Self {
75            it_interval: t.it_interval.into(),
76            it_value: t.it_value.into(),
77        }
78    }
79}
80
81#[cfg(any(
82    linux_kernel,
83    target_os = "freebsd",
84    target_os = "fuchsia",
85    target_os = "illumos",
86    target_os = "netbsd"
87))]
88#[cfg(fix_y2038)]
89impl From<Itimerspec> for LibcItimerspec {
90    #[inline]
91    fn from(t: Itimerspec) -> Self {
92        Self {
93            it_interval: t.it_interval.into(),
94            it_value: t.it_value.into(),
95        }
96    }
97}
98
99#[cfg(any(
100    linux_kernel,
101    target_os = "freebsd",
102    target_os = "fuchsia",
103    target_os = "illumos",
104    target_os = "netbsd"
105))]
106#[cfg(not(fix_y2038))]
107pub(crate) fn as_libc_itimerspec_ptr(itimerspec: &Itimerspec) -> *const c::itimerspec {
108    #[cfg(test)]
109    {
110        assert_eq_size!(Itimerspec, c::itimerspec);
111    }
112    crate::utils::as_ptr(itimerspec).cast::<c::itimerspec>()
113}
114
115#[cfg(any(
116    linux_kernel,
117    target_os = "freebsd",
118    target_os = "fuchsia",
119    target_os = "illumos",
120    target_os = "netbsd"
121))]
122#[cfg(not(fix_y2038))]
123pub(crate) fn as_libc_itimerspec_mut_ptr(
124    itimerspec: &mut core::mem::MaybeUninit<Itimerspec>,
125) -> *mut c::itimerspec {
126    #[cfg(test)]
127    {
128        assert_eq_size!(Itimerspec, c::itimerspec);
129    }
130    itimerspec.as_mut_ptr().cast::<c::itimerspec>()
131}
132
133#[cfg(any(
134    linux_kernel,
135    target_os = "freebsd",
136    target_os = "fuchsia",
137    target_os = "illumos",
138    target_os = "netbsd"
139))]
140bitflags! {
141    /// `TFD_*` flags for use with [`timerfd_create`].
142    ///
143    /// [`timerfd_create`]: crate::time::timerfd_create
144    #[repr(transparent)]
145    #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
146    pub struct TimerfdFlags: u32 {
147        /// `TFD_NONBLOCK`
148        #[doc(alias = "TFD_NONBLOCK")]
149        const NONBLOCK = bitcast!(c::TFD_NONBLOCK);
150
151        /// `TFD_CLOEXEC`
152        #[doc(alias = "TFD_CLOEXEC")]
153        const CLOEXEC = bitcast!(c::TFD_CLOEXEC);
154
155        /// <https://docs.rs/bitflags/*/bitflags/#externally-defined-flags>
156        const _ = !0;
157    }
158}
159
160#[cfg(any(
161    linux_kernel,
162    target_os = "freebsd",
163    target_os = "fuchsia",
164    target_os = "illumos",
165    target_os = "netbsd"
166))]
167bitflags! {
168    /// `TFD_TIMER_*` flags for use with [`timerfd_settime`].
169    ///
170    /// [`timerfd_settime`]: crate::time::timerfd_settime
171    #[repr(transparent)]
172    #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
173    pub struct TimerfdTimerFlags: u32 {
174        /// `TFD_TIMER_ABSTIME`
175        #[doc(alias = "TFD_TIMER_ABSTIME")]
176        const ABSTIME = bitcast!(c::TFD_TIMER_ABSTIME);
177
178        /// `TFD_TIMER_CANCEL_ON_SET`
179        #[cfg(not(target_os = "fuchsia"))]
180        #[doc(alias = "TFD_TIMER_CANCEL_ON_SET")]
181        const CANCEL_ON_SET = bitcast!(c::TFD_TIMER_CANCEL_ON_SET);
182
183        /// <https://docs.rs/bitflags/*/bitflags/#externally-defined-flags>
184        const _ = !0;
185    }
186}
187
188/// `CLOCK_*` constants for use with [`timerfd_create`].
189///
190/// [`timerfd_create`]: crate::time::timerfd_create
191#[cfg(any(
192    linux_kernel,
193    target_os = "freebsd",
194    target_os = "fuchsia",
195    target_os = "illumos",
196    target_os = "netbsd"
197))]
198#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
199#[repr(u32)]
200#[non_exhaustive]
201pub enum TimerfdClockId {
202    /// `CLOCK_REALTIME`—A clock that tells the “real” time.
203    ///
204    /// This is a clock that tells the amount of time elapsed since the Unix
205    /// epoch, 1970-01-01T00:00:00Z. The clock is externally settable, so it is
206    /// not monotonic. Successive reads may see decreasing times, so it isn't
207    /// reliable for measuring durations.
208    #[doc(alias = "CLOCK_REALTIME")]
209    Realtime = bitcast!(c::CLOCK_REALTIME),
210
211    /// `CLOCK_MONOTONIC`—A clock that tells an abstract time.
212    ///
213    /// Unlike `Realtime`, this clock is not based on a fixed known epoch, so
214    /// individual times aren't meaningful. However, since it isn't settable,
215    /// it is reliable for measuring durations.
216    ///
217    /// This clock does not advance while the system is suspended; see
218    /// `Boottime` for a clock that does.
219    #[doc(alias = "CLOCK_MONOTONIC")]
220    Monotonic = bitcast!(c::CLOCK_MONOTONIC),
221
222    /// `CLOCK_BOOTTIME`—Like `Monotonic`, but advances while suspended.
223    ///
224    /// This clock is similar to `Monotonic`, but does advance while the system
225    /// is suspended.
226    #[doc(alias = "CLOCK_BOOTTIME")]
227    #[cfg(any(linux_kernel, target_os = "fuchsia", target_os = "openbsd"))]
228    Boottime = bitcast!(c::CLOCK_BOOTTIME),
229
230    /// `CLOCK_REALTIME_ALARM`—Like `Realtime`, but wakes a suspended system.
231    ///
232    /// This clock is like `Realtime`, but can wake up a suspended system.
233    ///
234    /// Use of this clock requires the `CAP_WAKE_ALARM` Linux capability.
235    #[cfg(linux_kernel)]
236    #[doc(alias = "CLOCK_REALTIME_ALARM")]
237    RealtimeAlarm = bitcast!(c::CLOCK_REALTIME_ALARM),
238
239    /// `CLOCK_BOOTTIME_ALARM`—Like `Boottime`, but wakes a suspended system.
240    ///
241    /// This clock is like `Boottime`, but can wake up a suspended system.
242    ///
243    /// Use of this clock requires the `CAP_WAKE_ALARM` Linux capability.
244    #[cfg(any(linux_kernel, target_os = "cygwin", target_os = "fuchsia"))]
245    #[doc(alias = "CLOCK_BOOTTIME_ALARM")]
246    BoottimeAlarm = bitcast!(c::CLOCK_BOOTTIME_ALARM),
247}
248
249#[cfg(test)]
250mod tests {
251    #[allow(unused_imports)]
252    use super::*;
253
254    #[cfg(any(
255        linux_kernel,
256        target_os = "freebsd",
257        target_os = "fuchsia",
258        target_os = "illumos",
259        target_os = "netbsd"
260    ))]
261    #[test]
262    fn test_types() {
263        assert_eq_size!(TimerfdFlags, c::c_int);
264        assert_eq_size!(TimerfdTimerFlags, c::c_int);
265    }
266}