diff --git a/net_util/src/lib.rs b/net_util/src/lib.rs index ba7d507896..273c1ca995 100644 --- a/net_util/src/lib.rs +++ b/net_util/src/lib.rs @@ -18,7 +18,7 @@ use std::str::FromStr; use libc::EPERM; -use sys_util::{Error as SysError, Pollable}; +use sys_util::{Error as SysError}; use sys_util::{ioctl_with_val, ioctl_with_ref, ioctl_with_mut_ref}; #[derive(Debug)] @@ -160,7 +160,7 @@ pub struct Tap { if_name: [u8; 16usize], } -pub trait TapT: Read + Write + AsRawFd + Pollable + Send + Sized { +pub trait TapT: Read + Write + AsRawFd + Send + Sized { /// Create a new tap interface. Set the `vnet_hdr` flag to true to allow offloading on this tap, /// which will add an extra 12 byte virtio net header to incoming frames. Offloading cannot /// be used if `vnet_hdr` is false. @@ -449,14 +449,6 @@ impl AsRawFd for Tap { } } -// Safe since the tap fd's lifetime lasts as long as this trait object, and the -// tap fd is pollable. -unsafe impl Pollable for Tap { - fn pollable_fd(&self) -> RawFd { - self.tap_file.as_raw_fd() - } -} - pub mod fakes { use super::*; use std::fs::OpenOptions; @@ -549,12 +541,6 @@ pub mod fakes { self.tap_file.as_raw_fd() } } - - unsafe impl Pollable for FakeTap { - fn pollable_fd(&self) -> RawFd { - self.tap_file.as_raw_fd() - } - } } #[cfg(test)] diff --git a/sys_util/src/eventfd.rs b/sys_util/src/eventfd.rs index c253f6dcec..3d6b8503c8 100644 --- a/sys_util/src/eventfd.rs +++ b/sys_util/src/eventfd.rs @@ -97,12 +97,6 @@ impl IntoRawFd for EventFd { } } -unsafe impl ::Pollable for EventFd { - fn pollable_fd(&self) -> RawFd { - self.eventfd.as_raw_fd() - } -} - #[cfg(test)] mod tests { use super::*; diff --git a/sys_util/src/poll.rs b/sys_util/src/poll.rs index a52e2b019e..2a4eb63563 100644 --- a/sys_util/src/poll.rs +++ b/sys_util/src/poll.rs @@ -9,152 +9,18 @@ use std::i32; use std::i64; use std::marker::PhantomData; use std::os::unix::io::{RawFd, AsRawFd, IntoRawFd, FromRawFd}; -use std::os::unix::net::{UnixDatagram, UnixStream}; -use std::ptr::{null, null_mut}; +use std::ptr::null_mut; use std::slice; use std::thread; use std::time::Duration; -use libc::{c_int, c_long, timespec, time_t, nfds_t, sigset_t, pollfd, syscall, SYS_ppoll, POLLIN, - POLLHUP, EPOLL_CLOEXEC, EPOLLIN, EPOLLHUP, EPOLL_CTL_ADD, EPOLL_CTL_MOD, EPOLL_CTL_DEL, +use libc::{c_int, EPOLL_CLOEXEC, EPOLLIN, EPOLLHUP, EPOLL_CTL_ADD, EPOLL_CTL_MOD, EPOLL_CTL_DEL, epoll_create1, epoll_ctl, epoll_wait, epoll_event}; use {Result, errno_result}; const POLL_CONTEXT_MAX_EVENTS: usize = 16; -// The libc wrapper suppresses the kernel's changes to timeout, so we use the syscall directly. -unsafe fn ppoll(fds: *mut pollfd, - nfds: nfds_t, - timeout: *mut timespec, - sigmask: *const sigset_t, - sigsetsize: usize) - -> c_int { - syscall(SYS_ppoll, fds, nfds, timeout, sigmask, sigsetsize) as c_int -} - -/// Trait for file descriptors that can be polled for input. -/// -/// This is marked unsafe because the implementation must promise that the returned RawFd is valid -/// for polling purposes and that the lifetime of the returned fd is at least that of the trait -/// object. -pub unsafe trait Pollable { - /// Gets the file descriptor that can be polled for input. - fn pollable_fd(&self) -> RawFd; -} - -unsafe impl Pollable for UnixStream { - fn pollable_fd(&self) -> RawFd { - self.as_raw_fd() - } -} - -unsafe impl Pollable for UnixDatagram { - fn pollable_fd(&self) -> RawFd { - self.as_raw_fd() - } -} - -unsafe impl Pollable for File { - fn pollable_fd(&self) -> RawFd { - self.as_raw_fd() - } -} - -/// Used to poll multiple `Pollable` objects at once. -/// -/// # Example -/// -/// ``` -/// # use sys_util::{Result, EventFd, Poller, Pollable}; -/// # fn test() -> Result<()> { -/// let evt1 = EventFd::new()?; -/// let evt2 = EventFd::new()?; -/// evt2.write(1)?; -/// -/// let pollables: Vec<(u32, &Pollable)> = vec![(1, &evt1), (2, &evt2)]; -/// -/// let mut poller = Poller::new(2); -/// assert_eq!(poller.poll(&pollables[..]), Ok([2].as_ref())); -/// # Ok(()) -/// # } -/// ``` -pub struct Poller { - pollfds: Vec, - tokens: Vec, -} - -impl Poller { - /// Constructs a new poller object with the given `capacity` of Pollable objects pre-allocated. - pub fn new(capacity: usize) -> Poller { - Poller { - pollfds: Vec::with_capacity(capacity), - tokens: Vec::with_capacity(capacity), - } - } - - /// Waits for any of the given slice of `token`-`Pollable` tuples to be readable without - /// blocking and returns the `token` of each that is readable. - /// - /// This is guaranteed to not allocate if `pollables.len()` is less than the `capacity` given in - /// `Poller::new`. - pub fn poll(&mut self, pollables: &[(u32, &Pollable)]) -> Result<&[u32]> { - self.poll_timeout(pollables, &mut Duration::new(time_t::max_value() as u64, 0)) - } - - /// Waits for up to the given timeout for any of the given slice of `token`-`Pollable` tuples to - /// be readable without blocking and returns the `token` of each that is readable. - /// - /// If a timeout duration is given, the duration will be modified to the unused portion of the - /// timeout, even if an error is returned. - /// - /// This is guaranteed to not allocate if `pollables.len()` is less than the `capacity` given in - /// `Poller::new`. - pub fn poll_timeout(&mut self, - pollables: &[(u32, &Pollable)], - timeout: &mut Duration) - -> Result<&[u32]> { - self.pollfds.clear(); - for pollable in pollables.iter() { - self.pollfds - .push(pollfd { - fd: pollable.1.pollable_fd(), - events: POLLIN, - revents: 0, - }); - } - - let mut timeout_spec = timespec { - tv_sec: timeout.as_secs() as time_t, - tv_nsec: timeout.subsec_nanos() as c_long, - }; - // Safe because poll is given the correct length of properly initialized pollfds, and we - // check the return result. - let ret = unsafe { - handle_eintr_errno!(ppoll(self.pollfds.as_mut_ptr(), - self.pollfds.len() as nfds_t, - &mut timeout_spec, - null(), - 0)) - }; - - *timeout = Duration::new(timeout_spec.tv_sec as u64, timeout_spec.tv_nsec as u32); - - if ret < 0 { - return errno_result(); - } - - self.tokens.clear(); - for (pollfd, pollable) in self.pollfds.iter().zip(pollables.iter()) { - if (pollfd.revents & (POLLIN | POLLHUP)) != 0 { - self.tokens.push(pollable.0); - } - } - - Ok(&self.tokens) - } -} - /// Trait for a token that can be associated with an `fd` in a `PollContext`. /// /// Simple enums that have no or primitive variant data data can use the `#[derive(PollToken)]` @@ -590,49 +456,9 @@ impl IntoRawFd for PollContext { mod tests { use super::*; use std::time::Instant; + use std::os::unix::net::UnixStream; use EventFd; - #[test] - fn poller() { - let evt1 = EventFd::new().unwrap(); - let evt2 = EventFd::new().unwrap(); - evt2.write(1).unwrap(); - - let pollables: Vec<(u32, &Pollable)> = vec![(1, &evt1), (2, &evt2)]; - - let mut poller = Poller::new(2); - assert_eq!(poller.poll(&pollables[..]), Ok([2].as_ref())); - } - - #[test] - fn poller_multi() { - let evt1 = EventFd::new().unwrap(); - let evt2 = EventFd::new().unwrap(); - evt1.write(1).unwrap(); - evt2.write(1).unwrap(); - - let pollables: Vec<(u32, &Pollable)> = vec![(1, &evt1), (2, &evt2)]; - - let mut poller = Poller::new(2); - assert_eq!(poller.poll(&pollables[..]), Ok([1, 2].as_ref())); - } - - #[test] - fn timeout() { - let evt1 = EventFd::new().unwrap(); - let initial_dur = Duration::from_millis(10); - let mut timeout_dur = initial_dur; - let mut poller = Poller::new(0); - assert_eq!(poller.poll_timeout(&[(1, &evt1)], &mut timeout_dur), - Ok([].as_ref())); - assert_eq!(timeout_dur, Duration::from_secs(0)); - evt1.write(1).unwrap(); - timeout_dur = initial_dur; - assert_eq!(poller.poll_timeout(&[(1, &evt1)], &mut timeout_dur), - Ok([1].as_ref())); - assert!(timeout_dur < initial_dur); - } - #[test] fn poll_context() { let evt1 = EventFd::new().unwrap(); diff --git a/sys_util/src/signalfd.rs b/sys_util/src/signalfd.rs index 62e9ba93b9..3dad3a7d8a 100644 --- a/sys_util/src/signalfd.rs +++ b/sys_util/src/signalfd.rs @@ -100,14 +100,6 @@ impl SignalFd { } } -// Safe since the signalfd lifetime lasts as long as this trait object, and the -// signalfd is pollable. -unsafe impl ::Pollable for SignalFd { - fn pollable_fd(&self) -> RawFd { - self.signalfd.as_raw_fd() - } -} - impl AsRawFd for SignalFd { fn as_raw_fd(&self) -> RawFd { self.signalfd.as_raw_fd() diff --git a/sys_util/src/terminal.rs b/sys_util/src/terminal.rs index 675692c96f..211fb15190 100644 --- a/sys_util/src/terminal.rs +++ b/sys_util/src/terminal.rs @@ -111,10 +111,3 @@ unsafe impl<'a> Terminal for StdinLock<'a> { STDIN_FILENO } } - -// Safe because we return a genuine pollable fd that never changes and shares our lifetime. -unsafe impl ::Pollable for T { - fn pollable_fd(&self) -> RawFd { - self.tty_fd() - } -}