xref: /aosp_15_r20/external/crosvm/base/src/sys/linux/timer.rs (revision bb4ee6a4ae7042d18b07a98463b9c8b875e44b39)
1*bb4ee6a4SAndroid Build Coastguard Worker // Copyright 2018 The ChromiumOS Authors
2*bb4ee6a4SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*bb4ee6a4SAndroid Build Coastguard Worker // found in the LICENSE file.
4*bb4ee6a4SAndroid Build Coastguard Worker 
5*bb4ee6a4SAndroid Build Coastguard Worker use std::mem;
6*bb4ee6a4SAndroid Build Coastguard Worker use std::os::unix::io::AsRawFd;
7*bb4ee6a4SAndroid Build Coastguard Worker use std::os::unix::io::RawFd;
8*bb4ee6a4SAndroid Build Coastguard Worker use std::ptr;
9*bb4ee6a4SAndroid Build Coastguard Worker use std::time::Duration;
10*bb4ee6a4SAndroid Build Coastguard Worker 
11*bb4ee6a4SAndroid Build Coastguard Worker use libc::clock_getres;
12*bb4ee6a4SAndroid Build Coastguard Worker use libc::timerfd_create;
13*bb4ee6a4SAndroid Build Coastguard Worker use libc::timerfd_settime;
14*bb4ee6a4SAndroid Build Coastguard Worker use libc::CLOCK_MONOTONIC;
15*bb4ee6a4SAndroid Build Coastguard Worker use libc::EAGAIN;
16*bb4ee6a4SAndroid Build Coastguard Worker use libc::POLLIN;
17*bb4ee6a4SAndroid Build Coastguard Worker use libc::TFD_CLOEXEC;
18*bb4ee6a4SAndroid Build Coastguard Worker use libc::TFD_NONBLOCK;
19*bb4ee6a4SAndroid Build Coastguard Worker 
20*bb4ee6a4SAndroid Build Coastguard Worker use super::super::errno_result;
21*bb4ee6a4SAndroid Build Coastguard Worker use super::super::Error;
22*bb4ee6a4SAndroid Build Coastguard Worker use super::super::Result;
23*bb4ee6a4SAndroid Build Coastguard Worker use crate::descriptor::AsRawDescriptor;
24*bb4ee6a4SAndroid Build Coastguard Worker use crate::descriptor::FromRawDescriptor;
25*bb4ee6a4SAndroid Build Coastguard Worker use crate::descriptor::SafeDescriptor;
26*bb4ee6a4SAndroid Build Coastguard Worker use crate::handle_eintr_errno;
27*bb4ee6a4SAndroid Build Coastguard Worker use crate::timer::Timer;
28*bb4ee6a4SAndroid Build Coastguard Worker use crate::timer::TimerTrait;
29*bb4ee6a4SAndroid Build Coastguard Worker use crate::unix::duration_to_timespec;
30*bb4ee6a4SAndroid Build Coastguard Worker 
31*bb4ee6a4SAndroid Build Coastguard Worker impl AsRawFd for Timer {
as_raw_fd(&self) -> RawFd32*bb4ee6a4SAndroid Build Coastguard Worker     fn as_raw_fd(&self) -> RawFd {
33*bb4ee6a4SAndroid Build Coastguard Worker         self.handle.as_raw_descriptor()
34*bb4ee6a4SAndroid Build Coastguard Worker     }
35*bb4ee6a4SAndroid Build Coastguard Worker }
36*bb4ee6a4SAndroid Build Coastguard Worker 
37*bb4ee6a4SAndroid Build Coastguard Worker impl Timer {
38*bb4ee6a4SAndroid Build Coastguard Worker     /// Creates a new timerfd.  The timer is initally disarmed and must be armed by calling
39*bb4ee6a4SAndroid Build Coastguard Worker     /// `reset`.
new() -> Result<Timer>40*bb4ee6a4SAndroid Build Coastguard Worker     pub fn new() -> Result<Timer> {
41*bb4ee6a4SAndroid Build Coastguard Worker         // SAFETY:
42*bb4ee6a4SAndroid Build Coastguard Worker         // Safe because this doesn't modify any memory and we check the return value.
43*bb4ee6a4SAndroid Build Coastguard Worker         let ret = unsafe { timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC | TFD_NONBLOCK) };
44*bb4ee6a4SAndroid Build Coastguard Worker         if ret < 0 {
45*bb4ee6a4SAndroid Build Coastguard Worker             return errno_result();
46*bb4ee6a4SAndroid Build Coastguard Worker         }
47*bb4ee6a4SAndroid Build Coastguard Worker 
48*bb4ee6a4SAndroid Build Coastguard Worker         Ok(Timer {
49*bb4ee6a4SAndroid Build Coastguard Worker             // SAFETY:
50*bb4ee6a4SAndroid Build Coastguard Worker             // Safe because we uniquely own the file descriptor.
51*bb4ee6a4SAndroid Build Coastguard Worker             handle: unsafe { SafeDescriptor::from_raw_descriptor(ret) },
52*bb4ee6a4SAndroid Build Coastguard Worker             interval: None,
53*bb4ee6a4SAndroid Build Coastguard Worker         })
54*bb4ee6a4SAndroid Build Coastguard Worker     }
55*bb4ee6a4SAndroid Build Coastguard Worker 
56*bb4ee6a4SAndroid Build Coastguard Worker     // Calls `timerfd_settime()` and stores the new value of `interval`.
set_time(&mut self, dur: Option<Duration>, interval: Option<Duration>) -> Result<()>57*bb4ee6a4SAndroid Build Coastguard Worker     fn set_time(&mut self, dur: Option<Duration>, interval: Option<Duration>) -> Result<()> {
58*bb4ee6a4SAndroid Build Coastguard Worker         // The posix implementation of timer does not need self.interval, but we
59*bb4ee6a4SAndroid Build Coastguard Worker         // save it anyways to keep a consistent interface.
60*bb4ee6a4SAndroid Build Coastguard Worker         self.interval = interval;
61*bb4ee6a4SAndroid Build Coastguard Worker 
62*bb4ee6a4SAndroid Build Coastguard Worker         let spec = libc::itimerspec {
63*bb4ee6a4SAndroid Build Coastguard Worker             it_interval: duration_to_timespec(interval.unwrap_or_default()),
64*bb4ee6a4SAndroid Build Coastguard Worker             it_value: duration_to_timespec(dur.unwrap_or_default()),
65*bb4ee6a4SAndroid Build Coastguard Worker         };
66*bb4ee6a4SAndroid Build Coastguard Worker 
67*bb4ee6a4SAndroid Build Coastguard Worker         // SAFETY:
68*bb4ee6a4SAndroid Build Coastguard Worker         // Safe because this doesn't modify any memory and we check the return value.
69*bb4ee6a4SAndroid Build Coastguard Worker         let ret = unsafe { timerfd_settime(self.as_raw_descriptor(), 0, &spec, ptr::null_mut()) };
70*bb4ee6a4SAndroid Build Coastguard Worker         if ret < 0 {
71*bb4ee6a4SAndroid Build Coastguard Worker             return errno_result();
72*bb4ee6a4SAndroid Build Coastguard Worker         }
73*bb4ee6a4SAndroid Build Coastguard Worker 
74*bb4ee6a4SAndroid Build Coastguard Worker         Ok(())
75*bb4ee6a4SAndroid Build Coastguard Worker     }
76*bb4ee6a4SAndroid Build Coastguard Worker }
77*bb4ee6a4SAndroid Build Coastguard Worker 
78*bb4ee6a4SAndroid Build Coastguard Worker impl TimerTrait for Timer {
reset_oneshot(&mut self, dur: Duration) -> Result<()>79*bb4ee6a4SAndroid Build Coastguard Worker     fn reset_oneshot(&mut self, dur: Duration) -> Result<()> {
80*bb4ee6a4SAndroid Build Coastguard Worker         self.set_time(Some(dur), None)
81*bb4ee6a4SAndroid Build Coastguard Worker     }
82*bb4ee6a4SAndroid Build Coastguard Worker 
reset_repeating(&mut self, dur: Duration) -> Result<()>83*bb4ee6a4SAndroid Build Coastguard Worker     fn reset_repeating(&mut self, dur: Duration) -> Result<()> {
84*bb4ee6a4SAndroid Build Coastguard Worker         self.set_time(Some(dur), Some(dur))
85*bb4ee6a4SAndroid Build Coastguard Worker     }
86*bb4ee6a4SAndroid Build Coastguard Worker 
clear(&mut self) -> Result<()>87*bb4ee6a4SAndroid Build Coastguard Worker     fn clear(&mut self) -> Result<()> {
88*bb4ee6a4SAndroid Build Coastguard Worker         self.set_time(None, None)
89*bb4ee6a4SAndroid Build Coastguard Worker     }
90*bb4ee6a4SAndroid Build Coastguard Worker 
wait(&mut self) -> Result<()>91*bb4ee6a4SAndroid Build Coastguard Worker     fn wait(&mut self) -> Result<()> {
92*bb4ee6a4SAndroid Build Coastguard Worker         let mut pfd = libc::pollfd {
93*bb4ee6a4SAndroid Build Coastguard Worker             fd: self.as_raw_descriptor(),
94*bb4ee6a4SAndroid Build Coastguard Worker             events: POLLIN,
95*bb4ee6a4SAndroid Build Coastguard Worker             revents: 0,
96*bb4ee6a4SAndroid Build Coastguard Worker         };
97*bb4ee6a4SAndroid Build Coastguard Worker 
98*bb4ee6a4SAndroid Build Coastguard Worker         // SAFETY:
99*bb4ee6a4SAndroid Build Coastguard Worker         // Safe because this only modifies |pfd| and we check the return value
100*bb4ee6a4SAndroid Build Coastguard Worker         let ret = handle_eintr_errno!(unsafe {
101*bb4ee6a4SAndroid Build Coastguard Worker             libc::ppoll(
102*bb4ee6a4SAndroid Build Coastguard Worker                 &mut pfd as *mut libc::pollfd,
103*bb4ee6a4SAndroid Build Coastguard Worker                 1,
104*bb4ee6a4SAndroid Build Coastguard Worker                 ptr::null_mut(),
105*bb4ee6a4SAndroid Build Coastguard Worker                 ptr::null_mut(),
106*bb4ee6a4SAndroid Build Coastguard Worker             )
107*bb4ee6a4SAndroid Build Coastguard Worker         });
108*bb4ee6a4SAndroid Build Coastguard Worker 
109*bb4ee6a4SAndroid Build Coastguard Worker         if ret < 0 {
110*bb4ee6a4SAndroid Build Coastguard Worker             return errno_result();
111*bb4ee6a4SAndroid Build Coastguard Worker         }
112*bb4ee6a4SAndroid Build Coastguard Worker 
113*bb4ee6a4SAndroid Build Coastguard Worker         // EAGAIN is a valid error in the case where another thread has called timerfd_settime
114*bb4ee6a4SAndroid Build Coastguard Worker         // in between this thread calling ppoll and read. Since the ppoll returned originally
115*bb4ee6a4SAndroid Build Coastguard Worker         // without any revents it means the timer did expire, so we treat this as a
116*bb4ee6a4SAndroid Build Coastguard Worker         // WaitResult::Expired.
117*bb4ee6a4SAndroid Build Coastguard Worker         let _ = self.mark_waited()?;
118*bb4ee6a4SAndroid Build Coastguard Worker 
119*bb4ee6a4SAndroid Build Coastguard Worker         Ok(())
120*bb4ee6a4SAndroid Build Coastguard Worker     }
121*bb4ee6a4SAndroid Build Coastguard Worker 
mark_waited(&mut self) -> Result<bool>122*bb4ee6a4SAndroid Build Coastguard Worker     fn mark_waited(&mut self) -> Result<bool> {
123*bb4ee6a4SAndroid Build Coastguard Worker         let mut count = 0u64;
124*bb4ee6a4SAndroid Build Coastguard Worker 
125*bb4ee6a4SAndroid Build Coastguard Worker         // The timerfd is in non-blocking mode, so this should return immediately.
126*bb4ee6a4SAndroid Build Coastguard Worker         // SAFETY: We own the FD and provide a valid buffer we have exclusive access to.
127*bb4ee6a4SAndroid Build Coastguard Worker         let ret = unsafe {
128*bb4ee6a4SAndroid Build Coastguard Worker             libc::read(
129*bb4ee6a4SAndroid Build Coastguard Worker                 self.as_raw_descriptor(),
130*bb4ee6a4SAndroid Build Coastguard Worker                 &mut count as *mut _ as *mut libc::c_void,
131*bb4ee6a4SAndroid Build Coastguard Worker                 mem::size_of_val(&count),
132*bb4ee6a4SAndroid Build Coastguard Worker             )
133*bb4ee6a4SAndroid Build Coastguard Worker         };
134*bb4ee6a4SAndroid Build Coastguard Worker 
135*bb4ee6a4SAndroid Build Coastguard Worker         if ret < 0 {
136*bb4ee6a4SAndroid Build Coastguard Worker             if Error::last().errno() == EAGAIN {
137*bb4ee6a4SAndroid Build Coastguard Worker                 Ok(true)
138*bb4ee6a4SAndroid Build Coastguard Worker             } else {
139*bb4ee6a4SAndroid Build Coastguard Worker                 errno_result()
140*bb4ee6a4SAndroid Build Coastguard Worker             }
141*bb4ee6a4SAndroid Build Coastguard Worker         } else {
142*bb4ee6a4SAndroid Build Coastguard Worker             Ok(false)
143*bb4ee6a4SAndroid Build Coastguard Worker         }
144*bb4ee6a4SAndroid Build Coastguard Worker     }
145*bb4ee6a4SAndroid Build Coastguard Worker 
resolution(&self) -> Result<Duration>146*bb4ee6a4SAndroid Build Coastguard Worker     fn resolution(&self) -> Result<Duration> {
147*bb4ee6a4SAndroid Build Coastguard Worker         // SAFETY:
148*bb4ee6a4SAndroid Build Coastguard Worker         // Safe because we are zero-initializing a struct with only primitive member fields.
149*bb4ee6a4SAndroid Build Coastguard Worker         let mut res: libc::timespec = unsafe { mem::zeroed() };
150*bb4ee6a4SAndroid Build Coastguard Worker 
151*bb4ee6a4SAndroid Build Coastguard Worker         // SAFETY:
152*bb4ee6a4SAndroid Build Coastguard Worker         // Safe because it only modifies a local struct and we check the return value.
153*bb4ee6a4SAndroid Build Coastguard Worker         let ret = unsafe { clock_getres(CLOCK_MONOTONIC, &mut res) };
154*bb4ee6a4SAndroid Build Coastguard Worker 
155*bb4ee6a4SAndroid Build Coastguard Worker         if ret != 0 {
156*bb4ee6a4SAndroid Build Coastguard Worker             return errno_result();
157*bb4ee6a4SAndroid Build Coastguard Worker         }
158*bb4ee6a4SAndroid Build Coastguard Worker 
159*bb4ee6a4SAndroid Build Coastguard Worker         Ok(Duration::new(res.tv_sec as u64, res.tv_nsec as u32))
160*bb4ee6a4SAndroid Build Coastguard Worker     }
161*bb4ee6a4SAndroid Build Coastguard Worker }
162