1 // Copyright 2017 The Chromium OS Authors. All rights reserved. 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::{ 6 mem, 7 ops::Deref, 8 os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd}, 9 ptr, 10 time::Duration, 11 }; 12 13 use libc::{c_void, eventfd, read, write, POLLIN}; 14 use serde::{Deserialize, Serialize}; 15 16 use super::{ 17 duration_to_timespec, errno_result, generate_scoped_event, AsRawDescriptor, FromRawDescriptor, 18 IntoRawDescriptor, RawDescriptor, Result, SafeDescriptor, 19 }; 20 21 /// A safe wrapper around a Linux eventfd (man 2 eventfd). 22 /// 23 /// An eventfd is useful because it is sendable across processes and can be used for signaling in 24 /// and out of the KVM API. They can also be polled like any other file descriptor. 25 #[derive(Debug, PartialEq, Eq, Serialize, Deserialize)] 26 #[serde(transparent)] 27 pub struct EventFd { 28 event_handle: SafeDescriptor, 29 } 30 31 /// Wrapper around the return value of doing a read on an EventFd which distinguishes between 32 /// getting a valid count of the number of times the eventfd has been written to and timing out 33 /// waiting for the count to be non-zero. 34 #[derive(Debug, PartialEq, Eq)] 35 pub enum EventReadResult { 36 Count(u64), 37 Timeout, 38 } 39 40 impl EventFd { 41 /// Creates a new blocking EventFd with an initial value of 0. new() -> Result<EventFd>42 pub fn new() -> Result<EventFd> { 43 // This is safe because eventfd merely allocated an eventfd for our process and we handle 44 // the error case. 45 let ret = unsafe { eventfd(0, 0) }; 46 if ret < 0 { 47 return errno_result(); 48 } 49 // This is safe because we checked ret for success and know the kernel gave us an fd that we 50 // own. 51 Ok(EventFd { 52 event_handle: unsafe { SafeDescriptor::from_raw_descriptor(ret) }, 53 }) 54 } 55 56 /// Adds `v` to the eventfd's count, blocking until this won't overflow the count. write(&self, v: u64) -> Result<()>57 pub fn write(&self, v: u64) -> Result<()> { 58 // This is safe because we made this fd and the pointer we pass can not overflow because we 59 // give the syscall's size parameter properly. 60 let ret = unsafe { 61 write( 62 self.as_raw_fd(), 63 &v as *const u64 as *const c_void, 64 mem::size_of::<u64>(), 65 ) 66 }; 67 if ret <= 0 { 68 return errno_result(); 69 } 70 Ok(()) 71 } 72 73 /// Blocks until the the eventfd's count is non-zero, then resets the count to zero. read(&self) -> Result<u64>74 pub fn read(&self) -> Result<u64> { 75 let mut buf: u64 = 0; 76 let ret = unsafe { 77 // This is safe because we made this fd and the pointer we pass can not overflow because 78 // we give the syscall's size parameter properly. 79 read( 80 self.as_raw_fd(), 81 &mut buf as *mut u64 as *mut c_void, 82 mem::size_of::<u64>(), 83 ) 84 }; 85 if ret <= 0 { 86 return errno_result(); 87 } 88 Ok(buf) 89 } 90 91 /// Blocks for a maximum of `timeout` duration until the the eventfd's count is non-zero. If 92 /// a timeout does not occur then the count is returned as a EventReadResult::Count(count), 93 /// and the count is reset to 0. If a timeout does occur then this function will return 94 /// EventReadResult::Timeout. read_timeout(&self, timeout: Duration) -> Result<EventReadResult>95 pub fn read_timeout(&self, timeout: Duration) -> Result<EventReadResult> { 96 let mut pfd = libc::pollfd { 97 fd: self.as_raw_descriptor(), 98 events: POLLIN, 99 revents: 0, 100 }; 101 let timeoutspec: libc::timespec = duration_to_timespec(timeout); 102 // Safe because this only modifies |pfd| and we check the return value 103 let ret = unsafe { 104 libc::ppoll( 105 &mut pfd as *mut libc::pollfd, 106 1, 107 &timeoutspec, 108 ptr::null_mut(), 109 ) 110 }; 111 if ret < 0 { 112 return errno_result(); 113 } 114 115 // no return events (revents) means we got a timeout 116 if pfd.revents == 0 { 117 return Ok(EventReadResult::Timeout); 118 } 119 120 let mut buf = 0u64; 121 // This is safe because we made this fd and the pointer we pass can not overflow because 122 // we give the syscall's size parameter properly. 123 let ret = unsafe { 124 libc::read( 125 self.as_raw_descriptor(), 126 &mut buf as *mut _ as *mut c_void, 127 mem::size_of::<u64>(), 128 ) 129 }; 130 if ret < 0 { 131 return errno_result(); 132 } 133 Ok(EventReadResult::Count(buf)) 134 } 135 136 /// Clones this EventFd, internally creating a new file descriptor. The new EventFd will share 137 /// the same underlying count within the kernel. try_clone(&self) -> Result<EventFd>138 pub fn try_clone(&self) -> Result<EventFd> { 139 self.event_handle 140 .try_clone() 141 .map(|event_handle| EventFd { event_handle }) 142 } 143 } 144 145 impl AsRawFd for EventFd { as_raw_fd(&self) -> RawFd146 fn as_raw_fd(&self) -> RawFd { 147 self.event_handle.as_raw_fd() 148 } 149 } 150 151 impl AsRawDescriptor for EventFd { as_raw_descriptor(&self) -> RawDescriptor152 fn as_raw_descriptor(&self) -> RawDescriptor { 153 self.event_handle.as_raw_descriptor() 154 } 155 } 156 157 impl FromRawFd for EventFd { from_raw_fd(fd: RawFd) -> Self158 unsafe fn from_raw_fd(fd: RawFd) -> Self { 159 EventFd { 160 event_handle: SafeDescriptor::from_raw_descriptor(fd), 161 } 162 } 163 } 164 165 impl IntoRawFd for EventFd { into_raw_fd(self) -> RawFd166 fn into_raw_fd(self) -> RawFd { 167 self.event_handle.into_raw_descriptor() 168 } 169 } 170 171 impl From<EventFd> for SafeDescriptor { from(evt: EventFd) -> Self172 fn from(evt: EventFd) -> Self { 173 evt.event_handle 174 } 175 } 176 177 generate_scoped_event!(EventFd); 178 179 #[cfg(test)] 180 mod tests { 181 use super::*; 182 183 #[test] new()184 fn new() { 185 EventFd::new().unwrap(); 186 } 187 188 #[test] read_write()189 fn read_write() { 190 let evt = EventFd::new().unwrap(); 191 evt.write(55).unwrap(); 192 assert_eq!(evt.read(), Ok(55)); 193 } 194 195 #[test] clone()196 fn clone() { 197 let evt = EventFd::new().unwrap(); 198 let evt_clone = evt.try_clone().unwrap(); 199 evt.write(923).unwrap(); 200 assert_eq!(evt_clone.read(), Ok(923)); 201 } 202 203 #[test] scoped_event()204 fn scoped_event() { 205 let scoped_evt = ScopedEvent::new().unwrap(); 206 let evt_clone: EventFd = scoped_evt.try_clone().unwrap(); 207 drop(scoped_evt); 208 assert_eq!(evt_clone.read(), Ok(1)); 209 } 210 211 #[test] eventfd_from_scoped_event()212 fn eventfd_from_scoped_event() { 213 let scoped_evt = ScopedEvent::new().unwrap(); 214 let evt: EventFd = scoped_evt.into(); 215 evt.write(1).unwrap(); 216 } 217 218 #[test] timeout()219 fn timeout() { 220 let evt = EventFd::new().expect("failed to create eventfd"); 221 assert_eq!( 222 evt.read_timeout(Duration::from_millis(1)) 223 .expect("failed to read from eventfd with timeout"), 224 EventReadResult::Timeout 225 ); 226 } 227 } 228