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