xref: /aosp_15_r20/external/crosvm/base/src/sys/linux/event.rs (revision bb4ee6a4ae7042d18b07a98463b9c8b875e44b39)
1*bb4ee6a4SAndroid Build Coastguard Worker // Copyright 2017 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::ptr;
7*bb4ee6a4SAndroid Build Coastguard Worker use std::time::Duration;
8*bb4ee6a4SAndroid Build Coastguard Worker 
9*bb4ee6a4SAndroid Build Coastguard Worker use libc::c_void;
10*bb4ee6a4SAndroid Build Coastguard Worker use libc::eventfd;
11*bb4ee6a4SAndroid Build Coastguard Worker use libc::read;
12*bb4ee6a4SAndroid Build Coastguard Worker use libc::write;
13*bb4ee6a4SAndroid Build Coastguard Worker use libc::POLLIN;
14*bb4ee6a4SAndroid Build Coastguard Worker use serde::Deserialize;
15*bb4ee6a4SAndroid Build Coastguard Worker use serde::Serialize;
16*bb4ee6a4SAndroid Build Coastguard Worker 
17*bb4ee6a4SAndroid Build Coastguard Worker use super::errno_result;
18*bb4ee6a4SAndroid Build Coastguard Worker use super::Error;
19*bb4ee6a4SAndroid Build Coastguard Worker use super::RawDescriptor;
20*bb4ee6a4SAndroid Build Coastguard Worker use super::Result;
21*bb4ee6a4SAndroid Build Coastguard Worker use crate::descriptor::AsRawDescriptor;
22*bb4ee6a4SAndroid Build Coastguard Worker use crate::descriptor::FromRawDescriptor;
23*bb4ee6a4SAndroid Build Coastguard Worker use crate::descriptor::IntoRawDescriptor;
24*bb4ee6a4SAndroid Build Coastguard Worker use crate::descriptor::SafeDescriptor;
25*bb4ee6a4SAndroid Build Coastguard Worker use crate::handle_eintr_errno;
26*bb4ee6a4SAndroid Build Coastguard Worker use crate::unix::duration_to_timespec;
27*bb4ee6a4SAndroid Build Coastguard Worker use crate::EventWaitResult;
28*bb4ee6a4SAndroid Build Coastguard Worker 
29*bb4ee6a4SAndroid Build Coastguard Worker /// A safe wrapper around a Linux eventfd (man 2 eventfd).
30*bb4ee6a4SAndroid Build Coastguard Worker ///
31*bb4ee6a4SAndroid Build Coastguard Worker /// An eventfd is useful because it is sendable across processes and can be used for signaling in
32*bb4ee6a4SAndroid Build Coastguard Worker /// and out of the KVM API. They can also be polled like any other file descriptor.
33*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
34*bb4ee6a4SAndroid Build Coastguard Worker #[serde(transparent)]
35*bb4ee6a4SAndroid Build Coastguard Worker pub(crate) struct PlatformEvent {
36*bb4ee6a4SAndroid Build Coastguard Worker     event_handle: SafeDescriptor,
37*bb4ee6a4SAndroid Build Coastguard Worker }
38*bb4ee6a4SAndroid Build Coastguard Worker 
39*bb4ee6a4SAndroid Build Coastguard Worker /// Linux specific extensions to `Event`.
40*bb4ee6a4SAndroid Build Coastguard Worker pub trait EventExt {
41*bb4ee6a4SAndroid Build Coastguard Worker     /// Adds `v` to the eventfd's count, blocking until this won't overflow the count.
write_count(&self, v: u64) -> Result<()>42*bb4ee6a4SAndroid Build Coastguard Worker     fn write_count(&self, v: u64) -> Result<()>;
43*bb4ee6a4SAndroid Build Coastguard Worker     /// Blocks until the the eventfd's count is non-zero, then resets the count to zero.
read_count(&self) -> Result<u64>44*bb4ee6a4SAndroid Build Coastguard Worker     fn read_count(&self) -> Result<u64>;
45*bb4ee6a4SAndroid Build Coastguard Worker }
46*bb4ee6a4SAndroid Build Coastguard Worker 
47*bb4ee6a4SAndroid Build Coastguard Worker impl EventExt for crate::Event {
write_count(&self, v: u64) -> Result<()>48*bb4ee6a4SAndroid Build Coastguard Worker     fn write_count(&self, v: u64) -> Result<()> {
49*bb4ee6a4SAndroid Build Coastguard Worker         self.0.write_count(v)
50*bb4ee6a4SAndroid Build Coastguard Worker     }
51*bb4ee6a4SAndroid Build Coastguard Worker 
read_count(&self) -> Result<u64>52*bb4ee6a4SAndroid Build Coastguard Worker     fn read_count(&self) -> Result<u64> {
53*bb4ee6a4SAndroid Build Coastguard Worker         self.0.read_count()
54*bb4ee6a4SAndroid Build Coastguard Worker     }
55*bb4ee6a4SAndroid Build Coastguard Worker }
56*bb4ee6a4SAndroid Build Coastguard Worker 
57*bb4ee6a4SAndroid Build Coastguard Worker impl PlatformEvent {
58*bb4ee6a4SAndroid Build Coastguard Worker     /// Creates a new blocking eventfd with an initial value of 0.
new() -> Result<PlatformEvent>59*bb4ee6a4SAndroid Build Coastguard Worker     pub fn new() -> Result<PlatformEvent> {
60*bb4ee6a4SAndroid Build Coastguard Worker         // SAFETY:
61*bb4ee6a4SAndroid Build Coastguard Worker         // This is safe because eventfd merely allocated an eventfd for our process and we handle
62*bb4ee6a4SAndroid Build Coastguard Worker         // the error case.
63*bb4ee6a4SAndroid Build Coastguard Worker         let ret = unsafe { eventfd(0, 0) };
64*bb4ee6a4SAndroid Build Coastguard Worker         if ret < 0 {
65*bb4ee6a4SAndroid Build Coastguard Worker             return errno_result();
66*bb4ee6a4SAndroid Build Coastguard Worker         }
67*bb4ee6a4SAndroid Build Coastguard Worker         Ok(PlatformEvent {
68*bb4ee6a4SAndroid Build Coastguard Worker             // SAFETY:
69*bb4ee6a4SAndroid Build Coastguard Worker             // This is safe because we checked ret for success and know the kernel gave us an fd
70*bb4ee6a4SAndroid Build Coastguard Worker             // that we own.
71*bb4ee6a4SAndroid Build Coastguard Worker             event_handle: unsafe { SafeDescriptor::from_raw_descriptor(ret) },
72*bb4ee6a4SAndroid Build Coastguard Worker         })
73*bb4ee6a4SAndroid Build Coastguard Worker     }
74*bb4ee6a4SAndroid Build Coastguard Worker 
75*bb4ee6a4SAndroid Build Coastguard Worker     /// See `EventExt::write_count`.
write_count(&self, v: u64) -> Result<()>76*bb4ee6a4SAndroid Build Coastguard Worker     pub fn write_count(&self, v: u64) -> Result<()> {
77*bb4ee6a4SAndroid Build Coastguard Worker         // SAFETY:
78*bb4ee6a4SAndroid Build Coastguard Worker         // This is safe because we made this fd and the pointer we pass can not overflow because we
79*bb4ee6a4SAndroid Build Coastguard Worker         // give the syscall's size parameter properly.
80*bb4ee6a4SAndroid Build Coastguard Worker         let ret = handle_eintr_errno!(unsafe {
81*bb4ee6a4SAndroid Build Coastguard Worker             write(
82*bb4ee6a4SAndroid Build Coastguard Worker                 self.as_raw_descriptor(),
83*bb4ee6a4SAndroid Build Coastguard Worker                 &v as *const u64 as *const c_void,
84*bb4ee6a4SAndroid Build Coastguard Worker                 mem::size_of::<u64>(),
85*bb4ee6a4SAndroid Build Coastguard Worker             )
86*bb4ee6a4SAndroid Build Coastguard Worker         });
87*bb4ee6a4SAndroid Build Coastguard Worker         if ret < 0 {
88*bb4ee6a4SAndroid Build Coastguard Worker             return errno_result();
89*bb4ee6a4SAndroid Build Coastguard Worker         }
90*bb4ee6a4SAndroid Build Coastguard Worker         if ret as usize != mem::size_of::<u64>() {
91*bb4ee6a4SAndroid Build Coastguard Worker             return Err(Error::new(libc::EIO));
92*bb4ee6a4SAndroid Build Coastguard Worker         }
93*bb4ee6a4SAndroid Build Coastguard Worker         Ok(())
94*bb4ee6a4SAndroid Build Coastguard Worker     }
95*bb4ee6a4SAndroid Build Coastguard Worker 
96*bb4ee6a4SAndroid Build Coastguard Worker     /// See `EventExt::read_count`.
read_count(&self) -> Result<u64>97*bb4ee6a4SAndroid Build Coastguard Worker     pub fn read_count(&self) -> Result<u64> {
98*bb4ee6a4SAndroid Build Coastguard Worker         let mut buf: u64 = 0;
99*bb4ee6a4SAndroid Build Coastguard Worker         // SAFETY:
100*bb4ee6a4SAndroid Build Coastguard Worker         // This is safe because we made this fd and the pointer we pass can not overflow because
101*bb4ee6a4SAndroid Build Coastguard Worker         // we give the syscall's size parameter properly.
102*bb4ee6a4SAndroid Build Coastguard Worker         let ret = handle_eintr_errno!(unsafe {
103*bb4ee6a4SAndroid Build Coastguard Worker             read(
104*bb4ee6a4SAndroid Build Coastguard Worker                 self.as_raw_descriptor(),
105*bb4ee6a4SAndroid Build Coastguard Worker                 &mut buf as *mut u64 as *mut c_void,
106*bb4ee6a4SAndroid Build Coastguard Worker                 mem::size_of::<u64>(),
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         if ret as usize != mem::size_of::<u64>() {
113*bb4ee6a4SAndroid Build Coastguard Worker             return Err(Error::new(libc::EIO));
114*bb4ee6a4SAndroid Build Coastguard Worker         }
115*bb4ee6a4SAndroid Build Coastguard Worker         Ok(buf)
116*bb4ee6a4SAndroid Build Coastguard Worker     }
117*bb4ee6a4SAndroid Build Coastguard Worker 
118*bb4ee6a4SAndroid Build Coastguard Worker     /// See `Event::signal`.
signal(&self) -> Result<()>119*bb4ee6a4SAndroid Build Coastguard Worker     pub fn signal(&self) -> Result<()> {
120*bb4ee6a4SAndroid Build Coastguard Worker         self.write_count(1)
121*bb4ee6a4SAndroid Build Coastguard Worker     }
122*bb4ee6a4SAndroid Build Coastguard Worker 
123*bb4ee6a4SAndroid Build Coastguard Worker     /// See `Event::wait`.
wait(&self) -> Result<()>124*bb4ee6a4SAndroid Build Coastguard Worker     pub fn wait(&self) -> Result<()> {
125*bb4ee6a4SAndroid Build Coastguard Worker         self.read_count().map(|_| ())
126*bb4ee6a4SAndroid Build Coastguard Worker     }
127*bb4ee6a4SAndroid Build Coastguard Worker 
128*bb4ee6a4SAndroid Build Coastguard Worker     /// See `Event::wait_timeout`.
wait_timeout(&self, timeout: Duration) -> Result<EventWaitResult>129*bb4ee6a4SAndroid Build Coastguard Worker     pub fn wait_timeout(&self, timeout: Duration) -> Result<EventWaitResult> {
130*bb4ee6a4SAndroid Build Coastguard Worker         let mut pfd = libc::pollfd {
131*bb4ee6a4SAndroid Build Coastguard Worker             fd: self.as_raw_descriptor(),
132*bb4ee6a4SAndroid Build Coastguard Worker             events: POLLIN,
133*bb4ee6a4SAndroid Build Coastguard Worker             revents: 0,
134*bb4ee6a4SAndroid Build Coastguard Worker         };
135*bb4ee6a4SAndroid Build Coastguard Worker         let timeoutspec: libc::timespec = duration_to_timespec(timeout);
136*bb4ee6a4SAndroid Build Coastguard Worker         // SAFETY:
137*bb4ee6a4SAndroid Build Coastguard Worker         // Safe because this only modifies |pfd| and we check the return value
138*bb4ee6a4SAndroid Build Coastguard Worker         let ret = unsafe {
139*bb4ee6a4SAndroid Build Coastguard Worker             libc::ppoll(
140*bb4ee6a4SAndroid Build Coastguard Worker                 &mut pfd as *mut libc::pollfd,
141*bb4ee6a4SAndroid Build Coastguard Worker                 1,
142*bb4ee6a4SAndroid Build Coastguard Worker                 &timeoutspec,
143*bb4ee6a4SAndroid Build Coastguard Worker                 ptr::null_mut(),
144*bb4ee6a4SAndroid Build Coastguard Worker             )
145*bb4ee6a4SAndroid Build Coastguard Worker         };
146*bb4ee6a4SAndroid Build Coastguard Worker         if ret < 0 {
147*bb4ee6a4SAndroid Build Coastguard Worker             return errno_result();
148*bb4ee6a4SAndroid Build Coastguard Worker         }
149*bb4ee6a4SAndroid Build Coastguard Worker 
150*bb4ee6a4SAndroid Build Coastguard Worker         // no return events (revents) means we got a timeout
151*bb4ee6a4SAndroid Build Coastguard Worker         if pfd.revents == 0 {
152*bb4ee6a4SAndroid Build Coastguard Worker             return Ok(EventWaitResult::TimedOut);
153*bb4ee6a4SAndroid Build Coastguard Worker         }
154*bb4ee6a4SAndroid Build Coastguard Worker 
155*bb4ee6a4SAndroid Build Coastguard Worker         self.wait()?;
156*bb4ee6a4SAndroid Build Coastguard Worker         Ok(EventWaitResult::Signaled)
157*bb4ee6a4SAndroid Build Coastguard Worker     }
158*bb4ee6a4SAndroid Build Coastguard Worker 
159*bb4ee6a4SAndroid Build Coastguard Worker     /// See `Event::reset`.
reset(&self) -> Result<()>160*bb4ee6a4SAndroid Build Coastguard Worker     pub fn reset(&self) -> Result<()> {
161*bb4ee6a4SAndroid Build Coastguard Worker         // If the eventfd is currently signaled (counter > 0), `wait_timeout()` will `read()` it to
162*bb4ee6a4SAndroid Build Coastguard Worker         // reset the count. Otherwise (if the eventfd is not signaled), `wait_timeout()` will return
163*bb4ee6a4SAndroid Build Coastguard Worker         // immediately since we pass a zero duration. We don't care about the EventWaitResult; we
164*bb4ee6a4SAndroid Build Coastguard Worker         // just want a non-blocking read to reset the counter.
165*bb4ee6a4SAndroid Build Coastguard Worker         let _: EventWaitResult = self.wait_timeout(Duration::ZERO)?;
166*bb4ee6a4SAndroid Build Coastguard Worker         Ok(())
167*bb4ee6a4SAndroid Build Coastguard Worker     }
168*bb4ee6a4SAndroid Build Coastguard Worker 
169*bb4ee6a4SAndroid Build Coastguard Worker     /// Clones this eventfd, internally creating a new file descriptor. The new eventfd will share
170*bb4ee6a4SAndroid Build Coastguard Worker     /// the same underlying count within the kernel.
try_clone(&self) -> Result<PlatformEvent>171*bb4ee6a4SAndroid Build Coastguard Worker     pub fn try_clone(&self) -> Result<PlatformEvent> {
172*bb4ee6a4SAndroid Build Coastguard Worker         self.event_handle
173*bb4ee6a4SAndroid Build Coastguard Worker             .try_clone()
174*bb4ee6a4SAndroid Build Coastguard Worker             .map(|event_handle| PlatformEvent { event_handle })
175*bb4ee6a4SAndroid Build Coastguard Worker     }
176*bb4ee6a4SAndroid Build Coastguard Worker }
177*bb4ee6a4SAndroid Build Coastguard Worker 
178*bb4ee6a4SAndroid Build Coastguard Worker impl AsRawDescriptor for PlatformEvent {
as_raw_descriptor(&self) -> RawDescriptor179*bb4ee6a4SAndroid Build Coastguard Worker     fn as_raw_descriptor(&self) -> RawDescriptor {
180*bb4ee6a4SAndroid Build Coastguard Worker         self.event_handle.as_raw_descriptor()
181*bb4ee6a4SAndroid Build Coastguard Worker     }
182*bb4ee6a4SAndroid Build Coastguard Worker }
183*bb4ee6a4SAndroid Build Coastguard Worker 
184*bb4ee6a4SAndroid Build Coastguard Worker impl FromRawDescriptor for PlatformEvent {
from_raw_descriptor(descriptor: RawDescriptor) -> Self185*bb4ee6a4SAndroid Build Coastguard Worker     unsafe fn from_raw_descriptor(descriptor: RawDescriptor) -> Self {
186*bb4ee6a4SAndroid Build Coastguard Worker         PlatformEvent {
187*bb4ee6a4SAndroid Build Coastguard Worker             event_handle: SafeDescriptor::from_raw_descriptor(descriptor),
188*bb4ee6a4SAndroid Build Coastguard Worker         }
189*bb4ee6a4SAndroid Build Coastguard Worker     }
190*bb4ee6a4SAndroid Build Coastguard Worker }
191*bb4ee6a4SAndroid Build Coastguard Worker 
192*bb4ee6a4SAndroid Build Coastguard Worker impl IntoRawDescriptor for PlatformEvent {
into_raw_descriptor(self) -> RawDescriptor193*bb4ee6a4SAndroid Build Coastguard Worker     fn into_raw_descriptor(self) -> RawDescriptor {
194*bb4ee6a4SAndroid Build Coastguard Worker         self.event_handle.into_raw_descriptor()
195*bb4ee6a4SAndroid Build Coastguard Worker     }
196*bb4ee6a4SAndroid Build Coastguard Worker }
197*bb4ee6a4SAndroid Build Coastguard Worker 
198*bb4ee6a4SAndroid Build Coastguard Worker impl From<PlatformEvent> for SafeDescriptor {
from(evt: PlatformEvent) -> Self199*bb4ee6a4SAndroid Build Coastguard Worker     fn from(evt: PlatformEvent) -> Self {
200*bb4ee6a4SAndroid Build Coastguard Worker         evt.event_handle
201*bb4ee6a4SAndroid Build Coastguard Worker     }
202*bb4ee6a4SAndroid Build Coastguard Worker }
203*bb4ee6a4SAndroid Build Coastguard Worker 
204*bb4ee6a4SAndroid Build Coastguard Worker impl From<SafeDescriptor> for PlatformEvent {
from(sd: SafeDescriptor) -> Self205*bb4ee6a4SAndroid Build Coastguard Worker     fn from(sd: SafeDescriptor) -> Self {
206*bb4ee6a4SAndroid Build Coastguard Worker         PlatformEvent { event_handle: sd }
207*bb4ee6a4SAndroid Build Coastguard Worker     }
208*bb4ee6a4SAndroid Build Coastguard Worker }
209*bb4ee6a4SAndroid Build Coastguard Worker 
210*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(test)]
211*bb4ee6a4SAndroid Build Coastguard Worker mod tests {
212*bb4ee6a4SAndroid Build Coastguard Worker     use super::*;
213*bb4ee6a4SAndroid Build Coastguard Worker     use crate::Event;
214*bb4ee6a4SAndroid Build Coastguard Worker     use crate::EventExt;
215*bb4ee6a4SAndroid Build Coastguard Worker 
216*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
new()217*bb4ee6a4SAndroid Build Coastguard Worker     fn new() {
218*bb4ee6a4SAndroid Build Coastguard Worker         Event::new().unwrap();
219*bb4ee6a4SAndroid Build Coastguard Worker     }
220*bb4ee6a4SAndroid Build Coastguard Worker 
221*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
read_write()222*bb4ee6a4SAndroid Build Coastguard Worker     fn read_write() {
223*bb4ee6a4SAndroid Build Coastguard Worker         let evt = Event::new().unwrap();
224*bb4ee6a4SAndroid Build Coastguard Worker         evt.write_count(55).unwrap();
225*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(evt.read_count(), Ok(55));
226*bb4ee6a4SAndroid Build Coastguard Worker     }
227*bb4ee6a4SAndroid Build Coastguard Worker 
228*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
clone()229*bb4ee6a4SAndroid Build Coastguard Worker     fn clone() {
230*bb4ee6a4SAndroid Build Coastguard Worker         let evt = Event::new().unwrap();
231*bb4ee6a4SAndroid Build Coastguard Worker         let evt_clone = evt.try_clone().unwrap();
232*bb4ee6a4SAndroid Build Coastguard Worker         evt.write_count(923).unwrap();
233*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(evt_clone.read_count(), Ok(923));
234*bb4ee6a4SAndroid Build Coastguard Worker     }
235*bb4ee6a4SAndroid Build Coastguard Worker 
236*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
timeout()237*bb4ee6a4SAndroid Build Coastguard Worker     fn timeout() {
238*bb4ee6a4SAndroid Build Coastguard Worker         let evt = Event::new().expect("failed to create eventfd");
239*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(
240*bb4ee6a4SAndroid Build Coastguard Worker             evt.wait_timeout(Duration::from_millis(1))
241*bb4ee6a4SAndroid Build Coastguard Worker                 .expect("failed to read from eventfd with timeout"),
242*bb4ee6a4SAndroid Build Coastguard Worker             EventWaitResult::TimedOut
243*bb4ee6a4SAndroid Build Coastguard Worker         );
244*bb4ee6a4SAndroid Build Coastguard Worker     }
245*bb4ee6a4SAndroid Build Coastguard Worker }
246