summaryrefslogtreecommitdiffstats
path: root/third_party/rust/nix/src/poll.rs
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/rust/nix/src/poll.rs')
-rw-r--r--third_party/rust/nix/src/poll.rs161
1 files changed, 161 insertions, 0 deletions
diff --git a/third_party/rust/nix/src/poll.rs b/third_party/rust/nix/src/poll.rs
new file mode 100644
index 0000000000..eb6b241784
--- /dev/null
+++ b/third_party/rust/nix/src/poll.rs
@@ -0,0 +1,161 @@
+//! Wait for events to trigger on specific file descriptors
+#[cfg(any(target_os = "android", target_os = "dragonfly", target_os = "freebsd", target_os = "linux"))]
+use sys::time::TimeSpec;
+#[cfg(any(target_os = "android", target_os = "dragonfly", target_os = "freebsd", target_os = "linux"))]
+use sys::signal::SigSet;
+use std::os::unix::io::RawFd;
+use std::fmt;
+
+use libc;
+use Result;
+use errno::Errno;
+
+/// This is a wrapper around `libc::pollfd`.
+///
+/// It's meant to be used as an argument to the [`poll`](fn.poll.html) and
+/// [`ppoll`](fn.ppoll.html) functions to specify the events of interest
+/// for a specific file descriptor.
+///
+/// After a call to `poll` or `ppoll`, the events that occured can be
+/// retrieved by calling [`revents()`](#method.revents) on the `PollFd`.
+#[repr(C)]
+#[derive(Clone, Copy)]
+pub struct PollFd {
+ pollfd: libc::pollfd,
+}
+
+impl PollFd {
+ /// Creates a new `PollFd` specifying the events of interest
+ /// for a given file descriptor.
+ pub fn new(fd: RawFd, events: EventFlags) -> PollFd {
+ PollFd {
+ pollfd: libc::pollfd {
+ fd: fd,
+ events: events.bits(),
+ revents: EventFlags::empty().bits(),
+ },
+ }
+ }
+
+ /// Returns the events that occured in the last call to `poll` or `ppoll`.
+ pub fn revents(&self) -> Option<EventFlags> {
+ EventFlags::from_bits(self.pollfd.revents)
+ }
+}
+
+impl fmt::Debug for PollFd {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ let pfd = self.pollfd;
+ let mut ds = f.debug_struct("PollFd");
+ ds.field("fd", &pfd.fd);
+ match EventFlags::from_bits(pfd.events) {
+ None => ds.field("events", &pfd.events),
+ Some(ef) => ds.field("events", &ef),
+ };
+ match EventFlags::from_bits(pfd.revents) {
+ None => ds.field("revents", &pfd.revents),
+ Some(ef) => ds.field("revents", &ef),
+ };
+ ds.finish()
+ }
+}
+
+libc_bitflags! {
+ /// These flags define the different events that can be monitored by `poll` and `ppoll`
+ pub struct EventFlags: libc::c_short {
+ /// There is data to read.
+ POLLIN;
+ /// There is some exceptional condition on the file descriptor.
+ ///
+ /// Possibilities include:
+ ///
+ /// * There is out-of-band data on a TCP socket (see
+ /// [tcp(7)](http://man7.org/linux/man-pages/man7/tcp.7.html)).
+ /// * A pseudoterminal master in packet mode has seen a state
+ /// change on the slave (see
+ /// [ioctl_tty(2)](http://man7.org/linux/man-pages/man2/ioctl_tty.2.html)).
+ /// * A cgroup.events file has been modified (see
+ /// [cgroups(7)](http://man7.org/linux/man-pages/man7/cgroups.7.html)).
+ POLLPRI;
+ /// Writing is now possible, though a write larger that the
+ /// available space in a socket or pipe will still block (unless
+ /// `O_NONBLOCK` is set).
+ POLLOUT;
+ /// Equivalent to [`POLLIN`](constant.POLLIN.html)
+ POLLRDNORM;
+ /// Equivalent to [`POLLOUT`](constant.POLLOUT.html)
+ POLLWRNORM;
+ /// Priority band data can be read (generally unused on Linux).
+ POLLRDBAND;
+ /// Priority data may be written.
+ POLLWRBAND;
+ /// Error condition (only returned in
+ /// [`PollFd::revents`](struct.PollFd.html#method.revents);
+ /// ignored in [`PollFd::new`](struct.PollFd.html#method.new)).
+ /// This bit is also set for a file descriptor referring to the
+ /// write end of a pipe when the read end has been closed.
+ POLLERR;
+ /// Hang up (only returned in [`PollFd::revents`](struct.PollFd.html#method.revents);
+ /// ignored in [`PollFd::new`](struct.PollFd.html#method.new)).
+ /// Note that when reading from a channel such as a pipe or a stream
+ /// socket, this event merely indicates that the peer closed its
+ /// end of the channel. Subsequent reads from the channel will
+ /// return 0 (end of file) only after all outstanding data in the
+ /// channel has been consumed.
+ POLLHUP;
+ /// Invalid request: `fd` not open (only returned in
+ /// [`PollFd::revents`](struct.PollFd.html#method.revents);
+ /// ignored in [`PollFd::new`](struct.PollFd.html#method.new)).
+ POLLNVAL;
+ }
+}
+
+/// `poll` waits for one of a set of file descriptors to become ready to perform I/O.
+/// ([`poll(2)`](http://pubs.opengroup.org/onlinepubs/9699919799/functions/poll.html))
+///
+/// `fds` contains all [`PollFd`](struct.PollFd.html) to poll.
+/// The function will return as soon as any event occur for any of these `PollFd`s.
+///
+/// The `timeout` argument specifies the number of milliseconds that `poll()`
+/// should block waiting for a file descriptor to become ready. The call
+/// will block until either:
+///
+/// * a file descriptor becomes ready;
+/// * the call is interrupted by a signal handler; or
+/// * the timeout expires.
+///
+/// Note that the timeout interval will be rounded up to the system clock
+/// granularity, and kernel scheduling delays mean that the blocking
+/// interval may overrun by a small amount. Specifying a negative value
+/// in timeout means an infinite timeout. Specifying a timeout of zero
+/// causes `poll()` to return immediately, even if no file descriptors are
+/// ready.
+pub fn poll(fds: &mut [PollFd], timeout: libc::c_int) -> Result<libc::c_int> {
+ let res = unsafe {
+ libc::poll(fds.as_mut_ptr() as *mut libc::pollfd,
+ fds.len() as libc::nfds_t,
+ timeout)
+ };
+
+ Errno::result(res)
+}
+
+/// `ppoll()` allows an application to safely wait until either a file
+/// descriptor becomes ready or until a signal is caught.
+/// ([`poll(2)`](http://man7.org/linux/man-pages/man2/poll.2.html))
+///
+/// `ppoll` behaves like `poll`, but let you specify what signals may interrupt it
+/// with the `sigmask` argument.
+///
+#[cfg(any(target_os = "android", target_os = "dragonfly", target_os = "freebsd", target_os = "linux"))]
+pub fn ppoll(fds: &mut [PollFd], timeout: TimeSpec, sigmask: SigSet) -> Result<libc::c_int> {
+
+
+ let res = unsafe {
+ libc::ppoll(fds.as_mut_ptr() as *mut libc::pollfd,
+ fds.len() as libc::nfds_t,
+ timeout.as_ref(),
+ sigmask.as_ref())
+ };
+ Errno::result(res)
+}