1 // Copyright 2019 Intel Corporation. All Rights Reserved.
2 //
3 // Copyright 2017 The Chromium OS Authors. All rights reserved.
4 //
5 // SPDX-License-Identifier: BSD-3-Clause
6 
7 //! Structure and wrapper functions for working with
8 //! [`eventfd`](http://man7.org/linux/man-pages/man2/eventfd.2.html).
9 
10 use std::fs::File;
11 use std::os::unix::io::{AsRawFd, FromRawFd, RawFd};
12 use std::{io, mem, result};
13 
14 use libc::{c_void, dup, eventfd, read, write};
15 
16 // Reexport commonly used flags from libc.
17 pub use libc::{EFD_CLOEXEC, EFD_NONBLOCK, EFD_SEMAPHORE};
18 
19 /// A safe wrapper around Linux
20 /// [`eventfd`](http://man7.org/linux/man-pages/man2/eventfd.2.html).
21 #[derive(Debug)]
22 pub struct EventFd {
23     eventfd: File,
24 }
25 
26 impl EventFd {
27     /// Create a new EventFd with an initial value.
28     ///
29     /// # Arguments
30     ///
31     /// * `flag`: The initial value used for creating the `EventFd`.
32     /// Refer to Linux [`eventfd`](http://man7.org/linux/man-pages/man2/eventfd.2.html).
33     /// # Examples
34     ///
35     /// ```
36     /// extern crate vmm_sys_util;
37     /// use vmm_sys_util::eventfd::{EventFd, EFD_NONBLOCK};
38     ///
39     /// EventFd::new(EFD_NONBLOCK).unwrap();
40     /// ```
new(flag: i32) -> result::Result<EventFd, io::Error>41     pub fn new(flag: i32) -> result::Result<EventFd, io::Error> {
42         // SAFETY: This is safe because eventfd merely allocated an eventfd for
43         // our process and we handle the error case.
44         let ret = unsafe { eventfd(0, flag) };
45         if ret < 0 {
46             Err(io::Error::last_os_error())
47         } else {
48             Ok(EventFd {
49                 // SAFETY: This is safe because we checked ret for success and know
50                 // the kernel gave us an fd that we own.
51                 eventfd: unsafe { File::from_raw_fd(ret) },
52             })
53         }
54     }
55 
56     /// Add a value to the eventfd's counter.
57     ///
58     /// When the addition causes the counter overflow, this would either block
59     /// until a [`read`](http://man7.org/linux/man-pages/man2/read.2.html) is
60     /// performed on the file descriptor, or fail with the
61     /// error EAGAIN if the file descriptor has been made nonblocking.
62     ///
63     /// # Arguments
64     ///
65     /// * `v`: the value to be added to the eventfd's counter.
66     ///
67     /// # Examples
68     ///
69     /// ```
70     /// extern crate vmm_sys_util;
71     /// use vmm_sys_util::eventfd::{EventFd, EFD_NONBLOCK};
72     ///
73     /// let evt = EventFd::new(EFD_NONBLOCK).unwrap();
74     /// evt.write(55).unwrap();
75     /// ```
write(&self, v: u64) -> result::Result<(), io::Error>76     pub fn write(&self, v: u64) -> result::Result<(), io::Error> {
77         // SAFETY: This is safe because we made this fd and the pointer we pass
78         // can not overflow because we give the syscall's size parameter properly.
79         let ret = unsafe {
80             write(
81                 self.as_raw_fd(),
82                 &v as *const u64 as *const c_void,
83                 mem::size_of::<u64>(),
84             )
85         };
86         if ret <= 0 {
87             Err(io::Error::last_os_error())
88         } else {
89             Ok(())
90         }
91     }
92 
93     /// Read a value from the eventfd.
94     ///
95     /// If the counter is zero, this would either block
96     /// until the counter becomes nonzero, or fail with the
97     /// error EAGAIN if the file descriptor has been made nonblocking.
98     ///
99     /// # Examples
100     ///
101     /// ```
102     /// extern crate vmm_sys_util;
103     /// use vmm_sys_util::eventfd::{EventFd, EFD_NONBLOCK};
104     ///
105     /// let evt = EventFd::new(EFD_NONBLOCK).unwrap();
106     /// evt.write(55).unwrap();
107     /// assert_eq!(evt.read().unwrap(), 55);
108     /// ```
read(&self) -> result::Result<u64, io::Error>109     pub fn read(&self) -> result::Result<u64, io::Error> {
110         let mut buf: u64 = 0;
111         // SAFETY: This is safe because we made this fd and the pointer we
112         // pass can not overflow because we give the syscall's size parameter properly.
113         let ret = unsafe {
114             read(
115                 self.as_raw_fd(),
116                 &mut buf as *mut u64 as *mut c_void,
117                 mem::size_of::<u64>(),
118             )
119         };
120         if ret < 0 {
121             Err(io::Error::last_os_error())
122         } else {
123             Ok(buf)
124         }
125     }
126 
127     /// Clone this EventFd.
128     ///
129     /// This internally creates a new file descriptor and it will share the same
130     /// underlying count within the kernel.
131     ///
132     /// # Examples
133     ///
134     /// ```
135     /// extern crate vmm_sys_util;
136     /// use vmm_sys_util::eventfd::{EventFd, EFD_NONBLOCK};
137     ///
138     /// let evt = EventFd::new(EFD_NONBLOCK).unwrap();
139     /// let evt_clone = evt.try_clone().unwrap();
140     /// evt.write(923).unwrap();
141     /// assert_eq!(evt_clone.read().unwrap(), 923);
142     /// ```
try_clone(&self) -> result::Result<EventFd, io::Error>143     pub fn try_clone(&self) -> result::Result<EventFd, io::Error> {
144         // SAFETY: This is safe because we made this fd and properly check that it returns
145         // without error.
146         let ret = unsafe { dup(self.as_raw_fd()) };
147         if ret < 0 {
148             Err(io::Error::last_os_error())
149         } else {
150             Ok(EventFd {
151                 // SAFETY: This is safe because we checked ret for success and know the kernel
152                 // gave us an fd that we own.
153                 eventfd: unsafe { File::from_raw_fd(ret) },
154             })
155         }
156     }
157 }
158 
159 impl AsRawFd for EventFd {
as_raw_fd(&self) -> RawFd160     fn as_raw_fd(&self) -> RawFd {
161         self.eventfd.as_raw_fd()
162     }
163 }
164 
165 impl FromRawFd for EventFd {
from_raw_fd(fd: RawFd) -> Self166     unsafe fn from_raw_fd(fd: RawFd) -> Self {
167         EventFd {
168             eventfd: File::from_raw_fd(fd),
169         }
170     }
171 }
172 
173 #[cfg(test)]
174 mod tests {
175     use super::*;
176 
177     #[test]
test_new()178     fn test_new() {
179         EventFd::new(EFD_NONBLOCK).unwrap();
180         EventFd::new(0).unwrap();
181     }
182 
183     #[test]
test_read_write()184     fn test_read_write() {
185         let evt = EventFd::new(EFD_NONBLOCK).unwrap();
186         evt.write(55).unwrap();
187         assert_eq!(evt.read().unwrap(), 55);
188     }
189 
190     #[test]
test_write_overflow()191     fn test_write_overflow() {
192         let evt = EventFd::new(EFD_NONBLOCK).unwrap();
193         evt.write(std::u64::MAX - 1).unwrap();
194         let r = evt.write(1);
195         match r {
196             Err(ref inner) if inner.kind() == io::ErrorKind::WouldBlock => (),
197             _ => panic!("Unexpected"),
198         }
199     }
200     #[test]
test_read_nothing()201     fn test_read_nothing() {
202         let evt = EventFd::new(EFD_NONBLOCK).unwrap();
203         let r = evt.read();
204         match r {
205             Err(ref inner) if inner.kind() == io::ErrorKind::WouldBlock => (),
206             _ => panic!("Unexpected"),
207         }
208     }
209     #[test]
test_clone()210     fn test_clone() {
211         let evt = EventFd::new(EFD_NONBLOCK).unwrap();
212         let evt_clone = evt.try_clone().unwrap();
213         evt.write(923).unwrap();
214         assert_eq!(evt_clone.read().unwrap(), 923);
215     }
216 }
217