summaryrefslogtreecommitdiffstats
path: root/third_party/rust/nix/src/poll.rs
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 19:33:14 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 19:33:14 +0000
commit36d22d82aa202bb199967e9512281e9a53db42c9 (patch)
tree105e8c98ddea1c1e4784a60a5a6410fa416be2de /third_party/rust/nix/src/poll.rs
parentInitial commit. (diff)
downloadfirefox-esr-36d22d82aa202bb199967e9512281e9a53db42c9.tar.xz
firefox-esr-36d22d82aa202bb199967e9512281e9a53db42c9.zip
Adding upstream version 115.7.0esr.upstream/115.7.0esr
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-rw-r--r--third_party/rust/nix/src/poll.rs197
1 files changed, 197 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..6f227fee9e
--- /dev/null
+++ b/third_party/rust/nix/src/poll.rs
@@ -0,0 +1,197 @@
+//! Wait for events to trigger on specific file descriptors
+use std::os::unix::io::{AsRawFd, RawFd};
+
+use crate::errno::Errno;
+use crate::Result;
+
+/// 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 occurred can be
+/// retrieved by calling [`revents()`](#method.revents) on the `PollFd`.
+#[repr(transparent)]
+#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
+pub struct PollFd {
+ pollfd: libc::pollfd,
+}
+
+impl PollFd {
+ /// Creates a new `PollFd` specifying the events of interest
+ /// for a given file descriptor.
+ pub const fn new(fd: RawFd, events: PollFlags) -> PollFd {
+ PollFd {
+ pollfd: libc::pollfd {
+ fd,
+ events: events.bits(),
+ revents: PollFlags::empty().bits(),
+ },
+ }
+ }
+
+ /// Returns the events that occurred in the last call to `poll` or `ppoll`. Will only return
+ /// `None` if the kernel provides status flags that Nix does not know about.
+ pub fn revents(self) -> Option<PollFlags> {
+ PollFlags::from_bits(self.pollfd.revents)
+ }
+
+ /// Returns if any of the events of interest occured in the last call to `poll` or `ppoll`. Will
+ /// only return `None` if the kernel provides status flags that Nix does not know about.
+ ///
+ /// Equivalent to `x.revents()? != PollFlags::empty()`.
+ ///
+ /// This is marginally more efficient than [`PollFd::all`].
+ pub fn any(self) -> Option<bool> {
+ Some(self.revents()? != PollFlags::empty())
+ }
+
+ /// Returns if all the events of interest occured in the last call to `poll` or `ppoll`. Will
+ /// only return `None` if the kernel provides status flags that Nix does not know about.
+ ///
+ /// Equivalent to `x.revents()? & x.events() == x.events()`.
+ ///
+ /// This is marginally less efficient than [`PollFd::any`].
+ pub fn all(self) -> Option<bool> {
+ Some(self.revents()? & self.events() == self.events())
+ }
+
+ /// The events of interest for this `PollFd`.
+ pub fn events(self) -> PollFlags {
+ PollFlags::from_bits(self.pollfd.events).unwrap()
+ }
+
+ /// Modify the events of interest for this `PollFd`.
+ pub fn set_events(&mut self, events: PollFlags) {
+ self.pollfd.events = events.bits();
+ }
+}
+
+impl AsRawFd for PollFd {
+ fn as_raw_fd(&self) -> RawFd {
+ self.pollfd.fd
+ }
+}
+
+libc_bitflags! {
+ /// These flags define the different events that can be monitored by `poll` and `ppoll`
+ pub struct PollFlags: 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)](https://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)](https://man7.org/linux/man-pages/man2/ioctl_tty.2.html)).
+ /// * A cgroup.events file has been modified (see
+ /// [cgroups(7)](https://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)
+ #[cfg(not(target_os = "redox"))]
+ #[cfg_attr(docsrs, doc(cfg(all())))]
+ POLLRDNORM;
+ #[cfg(not(target_os = "redox"))]
+ #[cfg_attr(docsrs, doc(cfg(all())))]
+ /// Equivalent to [`POLLOUT`](constant.POLLOUT.html)
+ POLLWRNORM;
+ /// Priority band data can be read (generally unused on Linux).
+ #[cfg(not(target_os = "redox"))]
+ #[cfg_attr(docsrs, doc(cfg(all())))]
+ POLLRDBAND;
+ /// Priority data may be written.
+ #[cfg(not(target_os = "redox"))]
+ #[cfg_attr(docsrs, doc(cfg(all())))]
+ 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)`](https://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)
+}
+
+feature! {
+#![feature = "signal"]
+/// `ppoll()` allows an application to safely wait until either a file
+/// descriptor becomes ready or until a signal is caught.
+/// ([`poll(2)`](https://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. If you want `ppoll` to block indefinitely,
+/// specify `None` as `timeout` (it is like `timeout = -1` for `poll`).
+/// If `sigmask` is `None`, then no signal mask manipulation is performed,
+/// so in that case `ppoll` differs from `poll` only in the precision of the
+/// timeout argument.
+///
+#[cfg(any(target_os = "android", target_os = "dragonfly", target_os = "freebsd", target_os = "linux"))]
+pub fn ppoll(
+ fds: &mut [PollFd],
+ timeout: Option<crate::sys::time::TimeSpec>,
+ sigmask: Option<crate::sys::signal::SigSet>
+ ) -> Result<libc::c_int>
+{
+ let timeout = timeout.as_ref().map_or(core::ptr::null(), |r| r.as_ref());
+ let sigmask = sigmask.as_ref().map_or(core::ptr::null(), |r| r.as_ref());
+ let res = unsafe {
+ libc::ppoll(fds.as_mut_ptr() as *mut libc::pollfd,
+ fds.len() as libc::nfds_t,
+ timeout,
+ sigmask)
+ };
+ Errno::result(res)
+}
+}