1b8a62b91Sopenharmony_ci//! libc syscalls supporting `rustix::time`.
2b8a62b91Sopenharmony_ci
3b8a62b91Sopenharmony_ciuse super::super::c;
4b8a62b91Sopenharmony_ciuse super::super::conv::ret;
5b8a62b91Sopenharmony_ci#[cfg(feature = "time")]
6b8a62b91Sopenharmony_ci#[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
7b8a62b91Sopenharmony_ciuse super::super::time::types::LibcItimerspec;
8b8a62b91Sopenharmony_ciuse super::super::time::types::LibcTimespec;
9b8a62b91Sopenharmony_ciuse super::types::Timespec;
10b8a62b91Sopenharmony_ci#[cfg(not(target_os = "wasi"))]
11b8a62b91Sopenharmony_ciuse super::types::{ClockId, DynamicClockId};
12b8a62b91Sopenharmony_ciuse crate::io;
13b8a62b91Sopenharmony_ciuse core::mem::MaybeUninit;
14b8a62b91Sopenharmony_ci#[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
15b8a62b91Sopenharmony_ci#[cfg(feature = "time")]
16b8a62b91Sopenharmony_ciuse {
17b8a62b91Sopenharmony_ci    super::super::conv::{borrowed_fd, ret_owned_fd},
18b8a62b91Sopenharmony_ci    crate::fd::{BorrowedFd, OwnedFd},
19b8a62b91Sopenharmony_ci    crate::time::{Itimerspec, TimerfdClockId, TimerfdFlags, TimerfdTimerFlags},
20b8a62b91Sopenharmony_ci};
21b8a62b91Sopenharmony_ci
22b8a62b91Sopenharmony_ci#[cfg(all(
23b8a62b91Sopenharmony_ci    any(target_arch = "arm", target_arch = "mips", target_arch = "x86"),
24b8a62b91Sopenharmony_ci    target_env = "gnu",
25b8a62b91Sopenharmony_ci))]
26b8a62b91Sopenharmony_ciweak!(fn __clock_gettime64(c::clockid_t, *mut LibcTimespec) -> c::c_int);
27b8a62b91Sopenharmony_ci#[cfg(all(
28b8a62b91Sopenharmony_ci    any(target_arch = "arm", target_arch = "mips", target_arch = "x86"),
29b8a62b91Sopenharmony_ci    target_env = "gnu",
30b8a62b91Sopenharmony_ci))]
31b8a62b91Sopenharmony_ciweak!(fn __clock_getres64(c::clockid_t, *mut LibcTimespec) -> c::c_int);
32b8a62b91Sopenharmony_ci#[cfg(all(
33b8a62b91Sopenharmony_ci    any(target_arch = "arm", target_arch = "mips", target_arch = "x86"),
34b8a62b91Sopenharmony_ci    target_env = "gnu",
35b8a62b91Sopenharmony_ci))]
36b8a62b91Sopenharmony_ci#[cfg(feature = "time")]
37b8a62b91Sopenharmony_ciweak!(fn __timerfd_gettime64(c::c_int, *mut LibcItimerspec) -> c::c_int);
38b8a62b91Sopenharmony_ci#[cfg(all(
39b8a62b91Sopenharmony_ci    any(target_arch = "arm", target_arch = "mips", target_arch = "x86"),
40b8a62b91Sopenharmony_ci    target_env = "gnu",
41b8a62b91Sopenharmony_ci))]
42b8a62b91Sopenharmony_ci#[cfg(feature = "time")]
43b8a62b91Sopenharmony_ciweak!(fn __timerfd_settime64(c::c_int, c::c_int, *const LibcItimerspec, *mut LibcItimerspec) -> c::c_int);
44b8a62b91Sopenharmony_ci
45b8a62b91Sopenharmony_ci#[cfg(not(any(target_os = "redox", target_os = "wasi")))]
46b8a62b91Sopenharmony_ci#[inline]
47b8a62b91Sopenharmony_ci#[must_use]
48b8a62b91Sopenharmony_cipub(crate) fn clock_getres(id: ClockId) -> Timespec {
49b8a62b91Sopenharmony_ci    let mut timespec = MaybeUninit::<LibcTimespec>::uninit();
50b8a62b91Sopenharmony_ci
51b8a62b91Sopenharmony_ci    // 32-bit gnu version: libc has `clock_getres` but it is not y2038 safe by
52b8a62b91Sopenharmony_ci    // default.
53b8a62b91Sopenharmony_ci    #[cfg(all(
54b8a62b91Sopenharmony_ci        any(target_arch = "arm", target_arch = "mips", target_arch = "x86"),
55b8a62b91Sopenharmony_ci        target_env = "gnu",
56b8a62b91Sopenharmony_ci    ))]
57b8a62b91Sopenharmony_ci    unsafe {
58b8a62b91Sopenharmony_ci        if let Some(libc_clock_getres) = __clock_getres64.get() {
59b8a62b91Sopenharmony_ci            ret(libc_clock_getres(id as c::clockid_t, timespec.as_mut_ptr())).unwrap();
60b8a62b91Sopenharmony_ci            timespec.assume_init().into()
61b8a62b91Sopenharmony_ci        } else {
62b8a62b91Sopenharmony_ci            clock_getres_old(id)
63b8a62b91Sopenharmony_ci        }
64b8a62b91Sopenharmony_ci    }
65b8a62b91Sopenharmony_ci
66b8a62b91Sopenharmony_ci    // Main version: libc is y2038 safe and has `clock_getres`.
67b8a62b91Sopenharmony_ci    #[cfg(not(all(
68b8a62b91Sopenharmony_ci        any(target_arch = "arm", target_arch = "mips", target_arch = "x86"),
69b8a62b91Sopenharmony_ci        target_env = "gnu",
70b8a62b91Sopenharmony_ci    )))]
71b8a62b91Sopenharmony_ci    unsafe {
72b8a62b91Sopenharmony_ci        let _ = c::clock_getres(id as c::clockid_t, timespec.as_mut_ptr());
73b8a62b91Sopenharmony_ci        timespec.assume_init()
74b8a62b91Sopenharmony_ci    }
75b8a62b91Sopenharmony_ci}
76b8a62b91Sopenharmony_ci
77b8a62b91Sopenharmony_ci#[cfg(all(
78b8a62b91Sopenharmony_ci    any(target_arch = "arm", target_arch = "mips", target_arch = "x86"),
79b8a62b91Sopenharmony_ci    target_env = "gnu",
80b8a62b91Sopenharmony_ci))]
81b8a62b91Sopenharmony_ci#[must_use]
82b8a62b91Sopenharmony_ciunsafe fn clock_getres_old(id: ClockId) -> Timespec {
83b8a62b91Sopenharmony_ci    let mut old_timespec = MaybeUninit::<c::timespec>::uninit();
84b8a62b91Sopenharmony_ci    ret(c::clock_getres(
85b8a62b91Sopenharmony_ci        id as c::clockid_t,
86b8a62b91Sopenharmony_ci        old_timespec.as_mut_ptr(),
87b8a62b91Sopenharmony_ci    ))
88b8a62b91Sopenharmony_ci    .unwrap();
89b8a62b91Sopenharmony_ci    let old_timespec = old_timespec.assume_init();
90b8a62b91Sopenharmony_ci    Timespec {
91b8a62b91Sopenharmony_ci        tv_sec: old_timespec.tv_sec.into(),
92b8a62b91Sopenharmony_ci        tv_nsec: old_timespec.tv_nsec.into(),
93b8a62b91Sopenharmony_ci    }
94b8a62b91Sopenharmony_ci}
95b8a62b91Sopenharmony_ci
96b8a62b91Sopenharmony_ci#[cfg(not(target_os = "wasi"))]
97b8a62b91Sopenharmony_ci#[inline]
98b8a62b91Sopenharmony_ci#[must_use]
99b8a62b91Sopenharmony_cipub(crate) fn clock_gettime(id: ClockId) -> Timespec {
100b8a62b91Sopenharmony_ci    let mut timespec = MaybeUninit::<LibcTimespec>::uninit();
101b8a62b91Sopenharmony_ci
102b8a62b91Sopenharmony_ci    #[cfg(all(
103b8a62b91Sopenharmony_ci        any(target_arch = "arm", target_arch = "mips", target_arch = "x86"),
104b8a62b91Sopenharmony_ci        target_env = "gnu",
105b8a62b91Sopenharmony_ci    ))]
106b8a62b91Sopenharmony_ci    unsafe {
107b8a62b91Sopenharmony_ci        if let Some(libc_clock_gettime) = __clock_gettime64.get() {
108b8a62b91Sopenharmony_ci            ret(libc_clock_gettime(
109b8a62b91Sopenharmony_ci                id as c::clockid_t,
110b8a62b91Sopenharmony_ci                timespec.as_mut_ptr(),
111b8a62b91Sopenharmony_ci            ))
112b8a62b91Sopenharmony_ci            .unwrap();
113b8a62b91Sopenharmony_ci            timespec.assume_init().into()
114b8a62b91Sopenharmony_ci        } else {
115b8a62b91Sopenharmony_ci            clock_gettime_old(id)
116b8a62b91Sopenharmony_ci        }
117b8a62b91Sopenharmony_ci    }
118b8a62b91Sopenharmony_ci
119b8a62b91Sopenharmony_ci    // Use `unwrap()` here because `clock_getres` can fail if the clock itself
120b8a62b91Sopenharmony_ci    // overflows a number of seconds, but if that happens, the monotonic clocks
121b8a62b91Sopenharmony_ci    // can't maintain their invariants, or the realtime clocks aren't properly
122b8a62b91Sopenharmony_ci    // configured.
123b8a62b91Sopenharmony_ci    #[cfg(not(all(
124b8a62b91Sopenharmony_ci        any(target_arch = "arm", target_arch = "mips", target_arch = "x86"),
125b8a62b91Sopenharmony_ci        target_env = "gnu",
126b8a62b91Sopenharmony_ci    )))]
127b8a62b91Sopenharmony_ci    unsafe {
128b8a62b91Sopenharmony_ci        ret(c::clock_gettime(id as c::clockid_t, timespec.as_mut_ptr())).unwrap();
129b8a62b91Sopenharmony_ci        timespec.assume_init()
130b8a62b91Sopenharmony_ci    }
131b8a62b91Sopenharmony_ci}
132b8a62b91Sopenharmony_ci
133b8a62b91Sopenharmony_ci#[cfg(all(
134b8a62b91Sopenharmony_ci    any(target_arch = "arm", target_arch = "mips", target_arch = "x86"),
135b8a62b91Sopenharmony_ci    target_env = "gnu",
136b8a62b91Sopenharmony_ci))]
137b8a62b91Sopenharmony_ci#[must_use]
138b8a62b91Sopenharmony_ciunsafe fn clock_gettime_old(id: ClockId) -> Timespec {
139b8a62b91Sopenharmony_ci    let mut old_timespec = MaybeUninit::<c::timespec>::uninit();
140b8a62b91Sopenharmony_ci    ret(c::clock_gettime(
141b8a62b91Sopenharmony_ci        id as c::clockid_t,
142b8a62b91Sopenharmony_ci        old_timespec.as_mut_ptr(),
143b8a62b91Sopenharmony_ci    ))
144b8a62b91Sopenharmony_ci    .unwrap();
145b8a62b91Sopenharmony_ci    let old_timespec = old_timespec.assume_init();
146b8a62b91Sopenharmony_ci    Timespec {
147b8a62b91Sopenharmony_ci        tv_sec: old_timespec.tv_sec.into(),
148b8a62b91Sopenharmony_ci        tv_nsec: old_timespec.tv_nsec.into(),
149b8a62b91Sopenharmony_ci    }
150b8a62b91Sopenharmony_ci}
151b8a62b91Sopenharmony_ci
152b8a62b91Sopenharmony_ci#[cfg(not(target_os = "wasi"))]
153b8a62b91Sopenharmony_ci#[inline]
154b8a62b91Sopenharmony_cipub(crate) fn clock_gettime_dynamic(id: DynamicClockId<'_>) -> io::Result<Timespec> {
155b8a62b91Sopenharmony_ci    let mut timespec = MaybeUninit::<LibcTimespec>::uninit();
156b8a62b91Sopenharmony_ci    unsafe {
157b8a62b91Sopenharmony_ci        let id: c::clockid_t = match id {
158b8a62b91Sopenharmony_ci            DynamicClockId::Known(id) => id as c::clockid_t,
159b8a62b91Sopenharmony_ci
160b8a62b91Sopenharmony_ci            #[cfg(any(target_os = "android", target_os = "linux"))]
161b8a62b91Sopenharmony_ci            DynamicClockId::Dynamic(fd) => {
162b8a62b91Sopenharmony_ci                use crate::fd::AsRawFd;
163b8a62b91Sopenharmony_ci                const CLOCKFD: i32 = 3;
164b8a62b91Sopenharmony_ci                (!fd.as_raw_fd() << 3) | CLOCKFD
165b8a62b91Sopenharmony_ci            }
166b8a62b91Sopenharmony_ci
167b8a62b91Sopenharmony_ci            #[cfg(not(any(target_os = "android", target_os = "linux")))]
168b8a62b91Sopenharmony_ci            DynamicClockId::Dynamic(_fd) => {
169b8a62b91Sopenharmony_ci                // Dynamic clocks are not supported on this platform.
170b8a62b91Sopenharmony_ci                return Err(io::Errno::INVAL);
171b8a62b91Sopenharmony_ci            }
172b8a62b91Sopenharmony_ci
173b8a62b91Sopenharmony_ci            #[cfg(any(target_os = "android", target_os = "linux"))]
174b8a62b91Sopenharmony_ci            DynamicClockId::RealtimeAlarm => c::CLOCK_REALTIME_ALARM,
175b8a62b91Sopenharmony_ci
176b8a62b91Sopenharmony_ci            #[cfg(any(target_os = "android", target_os = "linux"))]
177b8a62b91Sopenharmony_ci            DynamicClockId::Tai => c::CLOCK_TAI,
178b8a62b91Sopenharmony_ci
179b8a62b91Sopenharmony_ci            #[cfg(any(target_os = "android", target_os = "linux"))]
180b8a62b91Sopenharmony_ci            DynamicClockId::Boottime => c::CLOCK_BOOTTIME,
181b8a62b91Sopenharmony_ci
182b8a62b91Sopenharmony_ci            #[cfg(any(target_os = "android", target_os = "linux"))]
183b8a62b91Sopenharmony_ci            DynamicClockId::BoottimeAlarm => c::CLOCK_BOOTTIME_ALARM,
184b8a62b91Sopenharmony_ci        };
185b8a62b91Sopenharmony_ci
186b8a62b91Sopenharmony_ci        #[cfg(all(
187b8a62b91Sopenharmony_ci            any(target_arch = "arm", target_arch = "mips", target_arch = "x86"),
188b8a62b91Sopenharmony_ci            target_env = "gnu",
189b8a62b91Sopenharmony_ci        ))]
190b8a62b91Sopenharmony_ci        {
191b8a62b91Sopenharmony_ci            if let Some(libc_clock_gettime) = __clock_gettime64.get() {
192b8a62b91Sopenharmony_ci                ret(libc_clock_gettime(
193b8a62b91Sopenharmony_ci                    id as c::clockid_t,
194b8a62b91Sopenharmony_ci                    timespec.as_mut_ptr(),
195b8a62b91Sopenharmony_ci                ))?;
196b8a62b91Sopenharmony_ci
197b8a62b91Sopenharmony_ci                Ok(timespec.assume_init().into())
198b8a62b91Sopenharmony_ci            } else {
199b8a62b91Sopenharmony_ci                clock_gettime_dynamic_old(id)
200b8a62b91Sopenharmony_ci            }
201b8a62b91Sopenharmony_ci        }
202b8a62b91Sopenharmony_ci
203b8a62b91Sopenharmony_ci        #[cfg(not(all(
204b8a62b91Sopenharmony_ci            any(target_arch = "arm", target_arch = "mips", target_arch = "x86"),
205b8a62b91Sopenharmony_ci            target_env = "gnu",
206b8a62b91Sopenharmony_ci        )))]
207b8a62b91Sopenharmony_ci        {
208b8a62b91Sopenharmony_ci            ret(c::clock_gettime(id as c::clockid_t, timespec.as_mut_ptr()))?;
209b8a62b91Sopenharmony_ci
210b8a62b91Sopenharmony_ci            Ok(timespec.assume_init())
211b8a62b91Sopenharmony_ci        }
212b8a62b91Sopenharmony_ci    }
213b8a62b91Sopenharmony_ci}
214b8a62b91Sopenharmony_ci
215b8a62b91Sopenharmony_ci#[cfg(all(
216b8a62b91Sopenharmony_ci    any(target_arch = "arm", target_arch = "mips", target_arch = "x86"),
217b8a62b91Sopenharmony_ci    target_env = "gnu",
218b8a62b91Sopenharmony_ci))]
219b8a62b91Sopenharmony_ci#[inline]
220b8a62b91Sopenharmony_ciunsafe fn clock_gettime_dynamic_old(id: c::clockid_t) -> io::Result<Timespec> {
221b8a62b91Sopenharmony_ci    let mut old_timespec = MaybeUninit::<c::timespec>::uninit();
222b8a62b91Sopenharmony_ci
223b8a62b91Sopenharmony_ci    ret(c::clock_gettime(
224b8a62b91Sopenharmony_ci        id as c::clockid_t,
225b8a62b91Sopenharmony_ci        old_timespec.as_mut_ptr(),
226b8a62b91Sopenharmony_ci    ))?;
227b8a62b91Sopenharmony_ci
228b8a62b91Sopenharmony_ci    let old_timespec = old_timespec.assume_init();
229b8a62b91Sopenharmony_ci    Ok(Timespec {
230b8a62b91Sopenharmony_ci        tv_sec: old_timespec.tv_sec.into(),
231b8a62b91Sopenharmony_ci        tv_nsec: old_timespec.tv_nsec.into(),
232b8a62b91Sopenharmony_ci    })
233b8a62b91Sopenharmony_ci}
234b8a62b91Sopenharmony_ci
235b8a62b91Sopenharmony_ci#[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
236b8a62b91Sopenharmony_ci#[cfg(feature = "time")]
237b8a62b91Sopenharmony_cipub(crate) fn timerfd_create(id: TimerfdClockId, flags: TimerfdFlags) -> io::Result<OwnedFd> {
238b8a62b91Sopenharmony_ci    unsafe { ret_owned_fd(c::timerfd_create(id as c::clockid_t, flags.bits())) }
239b8a62b91Sopenharmony_ci}
240b8a62b91Sopenharmony_ci
241b8a62b91Sopenharmony_ci#[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
242b8a62b91Sopenharmony_ci#[cfg(feature = "time")]
243b8a62b91Sopenharmony_cipub(crate) fn timerfd_settime(
244b8a62b91Sopenharmony_ci    fd: BorrowedFd<'_>,
245b8a62b91Sopenharmony_ci    flags: TimerfdTimerFlags,
246b8a62b91Sopenharmony_ci    new_value: &Itimerspec,
247b8a62b91Sopenharmony_ci) -> io::Result<Itimerspec> {
248b8a62b91Sopenharmony_ci    let mut result = MaybeUninit::<LibcItimerspec>::uninit();
249b8a62b91Sopenharmony_ci
250b8a62b91Sopenharmony_ci    #[cfg(all(
251b8a62b91Sopenharmony_ci        any(target_arch = "arm", target_arch = "mips", target_arch = "x86"),
252b8a62b91Sopenharmony_ci        target_env = "gnu",
253b8a62b91Sopenharmony_ci    ))]
254b8a62b91Sopenharmony_ci    unsafe {
255b8a62b91Sopenharmony_ci        if let Some(libc_timerfd_settime) = __timerfd_settime64.get() {
256b8a62b91Sopenharmony_ci            ret(libc_timerfd_settime(
257b8a62b91Sopenharmony_ci                borrowed_fd(fd),
258b8a62b91Sopenharmony_ci                flags.bits(),
259b8a62b91Sopenharmony_ci                &new_value.clone().into(),
260b8a62b91Sopenharmony_ci                result.as_mut_ptr(),
261b8a62b91Sopenharmony_ci            ))?;
262b8a62b91Sopenharmony_ci            Ok(result.assume_init().into())
263b8a62b91Sopenharmony_ci        } else {
264b8a62b91Sopenharmony_ci            timerfd_settime_old(fd, flags, new_value)
265b8a62b91Sopenharmony_ci        }
266b8a62b91Sopenharmony_ci    }
267b8a62b91Sopenharmony_ci
268b8a62b91Sopenharmony_ci    #[cfg(not(all(
269b8a62b91Sopenharmony_ci        any(target_arch = "arm", target_arch = "mips", target_arch = "x86"),
270b8a62b91Sopenharmony_ci        target_env = "gnu",
271b8a62b91Sopenharmony_ci    )))]
272b8a62b91Sopenharmony_ci    unsafe {
273b8a62b91Sopenharmony_ci        ret(c::timerfd_settime(
274b8a62b91Sopenharmony_ci            borrowed_fd(fd),
275b8a62b91Sopenharmony_ci            flags.bits(),
276b8a62b91Sopenharmony_ci            new_value,
277b8a62b91Sopenharmony_ci            result.as_mut_ptr(),
278b8a62b91Sopenharmony_ci        ))?;
279b8a62b91Sopenharmony_ci        Ok(result.assume_init())
280b8a62b91Sopenharmony_ci    }
281b8a62b91Sopenharmony_ci}
282b8a62b91Sopenharmony_ci
283b8a62b91Sopenharmony_ci#[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
284b8a62b91Sopenharmony_ci#[cfg(all(
285b8a62b91Sopenharmony_ci    any(target_arch = "arm", target_arch = "mips", target_arch = "x86"),
286b8a62b91Sopenharmony_ci    target_env = "gnu",
287b8a62b91Sopenharmony_ci))]
288b8a62b91Sopenharmony_ci#[cfg(feature = "time")]
289b8a62b91Sopenharmony_ciunsafe fn timerfd_settime_old(
290b8a62b91Sopenharmony_ci    fd: BorrowedFd<'_>,
291b8a62b91Sopenharmony_ci    flags: TimerfdTimerFlags,
292b8a62b91Sopenharmony_ci    new_value: &Itimerspec,
293b8a62b91Sopenharmony_ci) -> io::Result<Itimerspec> {
294b8a62b91Sopenharmony_ci    use core::convert::TryInto;
295b8a62b91Sopenharmony_ci
296b8a62b91Sopenharmony_ci    let mut old_result = MaybeUninit::<c::itimerspec>::uninit();
297b8a62b91Sopenharmony_ci
298b8a62b91Sopenharmony_ci    // Convert `new_value` to the old `itimerspec` format.
299b8a62b91Sopenharmony_ci    let old_new_value = c::itimerspec {
300b8a62b91Sopenharmony_ci        it_interval: c::timespec {
301b8a62b91Sopenharmony_ci            tv_sec: new_value
302b8a62b91Sopenharmony_ci                .it_interval
303b8a62b91Sopenharmony_ci                .tv_sec
304b8a62b91Sopenharmony_ci                .try_into()
305b8a62b91Sopenharmony_ci                .map_err(|_| io::Errno::OVERFLOW)?,
306b8a62b91Sopenharmony_ci            tv_nsec: new_value
307b8a62b91Sopenharmony_ci                .it_interval
308b8a62b91Sopenharmony_ci                .tv_nsec
309b8a62b91Sopenharmony_ci                .try_into()
310b8a62b91Sopenharmony_ci                .map_err(|_| io::Errno::INVAL)?,
311b8a62b91Sopenharmony_ci        },
312b8a62b91Sopenharmony_ci        it_value: c::timespec {
313b8a62b91Sopenharmony_ci            tv_sec: new_value
314b8a62b91Sopenharmony_ci                .it_value
315b8a62b91Sopenharmony_ci                .tv_sec
316b8a62b91Sopenharmony_ci                .try_into()
317b8a62b91Sopenharmony_ci                .map_err(|_| io::Errno::OVERFLOW)?,
318b8a62b91Sopenharmony_ci            tv_nsec: new_value
319b8a62b91Sopenharmony_ci                .it_value
320b8a62b91Sopenharmony_ci                .tv_nsec
321b8a62b91Sopenharmony_ci                .try_into()
322b8a62b91Sopenharmony_ci                .map_err(|_| io::Errno::INVAL)?,
323b8a62b91Sopenharmony_ci        },
324b8a62b91Sopenharmony_ci    };
325b8a62b91Sopenharmony_ci
326b8a62b91Sopenharmony_ci    ret(c::timerfd_settime(
327b8a62b91Sopenharmony_ci        borrowed_fd(fd),
328b8a62b91Sopenharmony_ci        flags.bits(),
329b8a62b91Sopenharmony_ci        &old_new_value,
330b8a62b91Sopenharmony_ci        old_result.as_mut_ptr(),
331b8a62b91Sopenharmony_ci    ))?;
332b8a62b91Sopenharmony_ci
333b8a62b91Sopenharmony_ci    let old_result = old_result.assume_init();
334b8a62b91Sopenharmony_ci    Ok(Itimerspec {
335b8a62b91Sopenharmony_ci        it_interval: Timespec {
336b8a62b91Sopenharmony_ci            tv_sec: old_result
337b8a62b91Sopenharmony_ci                .it_interval
338b8a62b91Sopenharmony_ci                .tv_sec
339b8a62b91Sopenharmony_ci                .try_into()
340b8a62b91Sopenharmony_ci                .map_err(|_| io::Errno::OVERFLOW)?,
341b8a62b91Sopenharmony_ci            tv_nsec: old_result.it_interval.tv_nsec as _,
342b8a62b91Sopenharmony_ci        },
343b8a62b91Sopenharmony_ci        it_value: Timespec {
344b8a62b91Sopenharmony_ci            tv_sec: old_result
345b8a62b91Sopenharmony_ci                .it_interval
346b8a62b91Sopenharmony_ci                .tv_sec
347b8a62b91Sopenharmony_ci                .try_into()
348b8a62b91Sopenharmony_ci                .map_err(|_| io::Errno::OVERFLOW)?,
349b8a62b91Sopenharmony_ci            tv_nsec: old_result.it_interval.tv_nsec as _,
350b8a62b91Sopenharmony_ci        },
351b8a62b91Sopenharmony_ci    })
352b8a62b91Sopenharmony_ci}
353b8a62b91Sopenharmony_ci
354b8a62b91Sopenharmony_ci#[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
355b8a62b91Sopenharmony_ci#[cfg(feature = "time")]
356b8a62b91Sopenharmony_cipub(crate) fn timerfd_gettime(fd: BorrowedFd<'_>) -> io::Result<Itimerspec> {
357b8a62b91Sopenharmony_ci    let mut result = MaybeUninit::<LibcItimerspec>::uninit();
358b8a62b91Sopenharmony_ci
359b8a62b91Sopenharmony_ci    #[cfg(all(
360b8a62b91Sopenharmony_ci        any(target_arch = "arm", target_arch = "mips", target_arch = "x86"),
361b8a62b91Sopenharmony_ci        target_env = "gnu",
362b8a62b91Sopenharmony_ci    ))]
363b8a62b91Sopenharmony_ci    unsafe {
364b8a62b91Sopenharmony_ci        if let Some(libc_timerfd_gettime) = __timerfd_gettime64.get() {
365b8a62b91Sopenharmony_ci            ret(libc_timerfd_gettime(borrowed_fd(fd), result.as_mut_ptr()))?;
366b8a62b91Sopenharmony_ci            Ok(result.assume_init().into())
367b8a62b91Sopenharmony_ci        } else {
368b8a62b91Sopenharmony_ci            timerfd_gettime_old(fd)
369b8a62b91Sopenharmony_ci        }
370b8a62b91Sopenharmony_ci    }
371b8a62b91Sopenharmony_ci
372b8a62b91Sopenharmony_ci    #[cfg(not(all(
373b8a62b91Sopenharmony_ci        any(target_arch = "arm", target_arch = "mips", target_arch = "x86"),
374b8a62b91Sopenharmony_ci        target_env = "gnu",
375b8a62b91Sopenharmony_ci    )))]
376b8a62b91Sopenharmony_ci    unsafe {
377b8a62b91Sopenharmony_ci        ret(c::timerfd_gettime(borrowed_fd(fd), result.as_mut_ptr()))?;
378b8a62b91Sopenharmony_ci        Ok(result.assume_init())
379b8a62b91Sopenharmony_ci    }
380b8a62b91Sopenharmony_ci}
381b8a62b91Sopenharmony_ci
382b8a62b91Sopenharmony_ci#[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
383b8a62b91Sopenharmony_ci#[cfg(all(
384b8a62b91Sopenharmony_ci    any(target_arch = "arm", target_arch = "mips", target_arch = "x86"),
385b8a62b91Sopenharmony_ci    target_env = "gnu",
386b8a62b91Sopenharmony_ci))]
387b8a62b91Sopenharmony_ci#[cfg(feature = "time")]
388b8a62b91Sopenharmony_ciunsafe fn timerfd_gettime_old(fd: BorrowedFd<'_>) -> io::Result<Itimerspec> {
389b8a62b91Sopenharmony_ci    use core::convert::TryInto;
390b8a62b91Sopenharmony_ci
391b8a62b91Sopenharmony_ci    let mut old_result = MaybeUninit::<c::itimerspec>::uninit();
392b8a62b91Sopenharmony_ci
393b8a62b91Sopenharmony_ci    ret(c::timerfd_gettime(borrowed_fd(fd), old_result.as_mut_ptr()))?;
394b8a62b91Sopenharmony_ci
395b8a62b91Sopenharmony_ci    let old_result = old_result.assume_init();
396b8a62b91Sopenharmony_ci    Ok(Itimerspec {
397b8a62b91Sopenharmony_ci        it_interval: Timespec {
398b8a62b91Sopenharmony_ci            tv_sec: old_result
399b8a62b91Sopenharmony_ci                .it_interval
400b8a62b91Sopenharmony_ci                .tv_sec
401b8a62b91Sopenharmony_ci                .try_into()
402b8a62b91Sopenharmony_ci                .map_err(|_| io::Errno::OVERFLOW)?,
403b8a62b91Sopenharmony_ci            tv_nsec: old_result.it_interval.tv_nsec as _,
404b8a62b91Sopenharmony_ci        },
405b8a62b91Sopenharmony_ci        it_value: Timespec {
406b8a62b91Sopenharmony_ci            tv_sec: old_result
407b8a62b91Sopenharmony_ci                .it_interval
408b8a62b91Sopenharmony_ci                .tv_sec
409b8a62b91Sopenharmony_ci                .try_into()
410b8a62b91Sopenharmony_ci                .map_err(|_| io::Errno::OVERFLOW)?,
411b8a62b91Sopenharmony_ci            tv_nsec: old_result.it_interval.tv_nsec as _,
412b8a62b91Sopenharmony_ci        },
413b8a62b91Sopenharmony_ci    })
414b8a62b91Sopenharmony_ci}
415