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