summaryrefslogtreecommitdiff
path: root/vendor/rustix/src/backend/linux_raw/event
diff options
context:
space:
mode:
authormo khan <mo@mokhan.ca>2025-07-02 18:36:06 -0600
committermo khan <mo@mokhan.ca>2025-07-02 18:36:06 -0600
commit8cdfa445d6629ffef4cb84967ff7017654045bc2 (patch)
tree22f0b0907c024c78d26a731e2e1f5219407d8102 /vendor/rustix/src/backend/linux_raw/event
parent4351c74c7c5f97156bc94d3a8549b9940ac80e3f (diff)
chore: add vendor directory
Diffstat (limited to 'vendor/rustix/src/backend/linux_raw/event')
-rw-r--r--vendor/rustix/src/backend/linux_raw/event/epoll.rs74
-rw-r--r--vendor/rustix/src/backend/linux_raw/event/mod.rs4
-rw-r--r--vendor/rustix/src/backend/linux_raw/event/poll_fd.rs98
-rw-r--r--vendor/rustix/src/backend/linux_raw/event/syscalls.rs358
-rw-r--r--vendor/rustix/src/backend/linux_raw/event/types.rs21
5 files changed, 555 insertions, 0 deletions
diff --git a/vendor/rustix/src/backend/linux_raw/event/epoll.rs b/vendor/rustix/src/backend/linux_raw/event/epoll.rs
new file mode 100644
index 00000000..093129db
--- /dev/null
+++ b/vendor/rustix/src/backend/linux_raw/event/epoll.rs
@@ -0,0 +1,74 @@
+use crate::ffi;
+use bitflags::bitflags;
+
+bitflags! {
+ /// `EPOLL_*` for use with [`epoll::create`].
+ ///
+ /// [`epoll::create`]: crate::event::epoll::create
+ #[repr(transparent)]
+ #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
+ pub struct CreateFlags: ffi::c_uint {
+ /// `EPOLL_CLOEXEC`
+ const CLOEXEC = linux_raw_sys::general::EPOLL_CLOEXEC;
+
+ /// <https://docs.rs/bitflags/*/bitflags/#externally-defined-flags>
+ const _ = !0;
+ }
+}
+
+bitflags! {
+ /// `EPOLL*` for use with [`epoll::add`].
+ ///
+ /// [`epoll::add`]: crate::event::epoll::add
+ #[repr(transparent)]
+ #[derive(Default, Copy, Clone, Eq, PartialEq, Hash, Debug)]
+ pub struct EventFlags: u32 {
+ /// `EPOLLIN`
+ const IN = linux_raw_sys::general::EPOLLIN as u32;
+
+ /// `EPOLLOUT`
+ const OUT = linux_raw_sys::general::EPOLLOUT as u32;
+
+ /// `EPOLLPRI`
+ const PRI = linux_raw_sys::general::EPOLLPRI as u32;
+
+ /// `EPOLLERR`
+ const ERR = linux_raw_sys::general::EPOLLERR as u32;
+
+ /// `EPOLLHUP`
+ const HUP = linux_raw_sys::general::EPOLLHUP as u32;
+
+ /// `EPOLLRDNORM`
+ const RDNORM = linux_raw_sys::general::EPOLLRDNORM as u32;
+
+ /// `EPOLLRDBAND`
+ const RDBAND = linux_raw_sys::general::EPOLLRDBAND as u32;
+
+ /// `EPOLLWRNORM`
+ const WRNORM = linux_raw_sys::general::EPOLLWRNORM as u32;
+
+ /// `EPOLLWRBAND`
+ const WRBAND = linux_raw_sys::general::EPOLLWRBAND as u32;
+
+ /// `EPOLLMSG`
+ const MSG = linux_raw_sys::general::EPOLLMSG as u32;
+
+ /// `EPOLLRDHUP`
+ const RDHUP = linux_raw_sys::general::EPOLLRDHUP as u32;
+
+ /// `EPOLLET`
+ const ET = linux_raw_sys::general::EPOLLET as u32;
+
+ /// `EPOLLONESHOT`
+ const ONESHOT = linux_raw_sys::general::EPOLLONESHOT as u32;
+
+ /// `EPOLLWAKEUP`
+ const WAKEUP = linux_raw_sys::general::EPOLLWAKEUP as u32;
+
+ /// `EPOLLEXCLUSIVE`
+ const EXCLUSIVE = linux_raw_sys::general::EPOLLEXCLUSIVE as u32;
+
+ /// <https://docs.rs/bitflags/*/bitflags/#externally-defined-flags>
+ const _ = !0;
+ }
+}
diff --git a/vendor/rustix/src/backend/linux_raw/event/mod.rs b/vendor/rustix/src/backend/linux_raw/event/mod.rs
new file mode 100644
index 00000000..605de253
--- /dev/null
+++ b/vendor/rustix/src/backend/linux_raw/event/mod.rs
@@ -0,0 +1,4 @@
+pub mod epoll;
+pub(crate) mod poll_fd;
+pub(crate) mod syscalls;
+pub(crate) mod types;
diff --git a/vendor/rustix/src/backend/linux_raw/event/poll_fd.rs b/vendor/rustix/src/backend/linux_raw/event/poll_fd.rs
new file mode 100644
index 00000000..9de43f26
--- /dev/null
+++ b/vendor/rustix/src/backend/linux_raw/event/poll_fd.rs
@@ -0,0 +1,98 @@
+use crate::fd::{AsFd, BorrowedFd};
+use bitflags::bitflags;
+
+bitflags! {
+ /// `POLL*` flags for use with [`poll`].
+ ///
+ /// [`poll`]: crate::event::poll
+ #[repr(transparent)]
+ #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
+ pub struct PollFlags: u16 {
+ /// `POLLIN`
+ const IN = linux_raw_sys::general::POLLIN as u16;
+ /// `POLLPRI`
+ const PRI = linux_raw_sys::general::POLLPRI as u16;
+ /// `POLLOUT`
+ const OUT = linux_raw_sys::general::POLLOUT as u16;
+ /// `POLLRDNORM`
+ const RDNORM = linux_raw_sys::general::POLLRDNORM as u16;
+ /// `POLLWRNORM`
+ const WRNORM = linux_raw_sys::general::POLLWRNORM as u16;
+ /// `POLLRDBAND`
+ const RDBAND = linux_raw_sys::general::POLLRDBAND as u16;
+ /// `POLLWRBAND`
+ const WRBAND = linux_raw_sys::general::POLLWRBAND as u16;
+ /// `POLLERR`
+ const ERR = linux_raw_sys::general::POLLERR as u16;
+ /// `POLLHUP`
+ const HUP = linux_raw_sys::general::POLLHUP as u16;
+ /// `POLLNVAL`
+ const NVAL = linux_raw_sys::general::POLLNVAL as u16;
+ /// `POLLRDHUP`
+ const RDHUP = linux_raw_sys::general::POLLRDHUP as u16;
+
+ /// <https://docs.rs/bitflags/*/bitflags/#externally-defined-flags>
+ const _ = !0;
+ }
+}
+
+/// `struct pollfd`—File descriptor and flags for use with [`poll`].
+///
+/// [`poll`]: crate::event::poll
+#[doc(alias = "pollfd")]
+#[repr(C)]
+#[derive(Debug, Clone)]
+pub struct PollFd<'fd> {
+ pub(crate) fd: BorrowedFd<'fd>,
+ pub(crate) events: u16,
+ pub(crate) revents: u16,
+}
+
+impl<'fd> PollFd<'fd> {
+ /// Constructs a new `PollFd` holding `fd` and `events`.
+ #[inline]
+ pub fn new<Fd: AsFd>(fd: &'fd Fd, events: PollFlags) -> Self {
+ Self::from_borrowed_fd(fd.as_fd(), events)
+ }
+
+ /// Sets the contained file descriptor to `fd`.
+ #[inline]
+ pub fn set_fd<Fd: AsFd>(&mut self, fd: &'fd Fd) {
+ self.fd = fd.as_fd();
+ }
+
+ /// Clears the ready events.
+ #[inline]
+ pub fn clear_revents(&mut self) {
+ self.revents = 0;
+ }
+
+ /// Constructs a new `PollFd` holding `fd` and `events`.
+ ///
+ /// This is the same as `new`, but can be used to avoid borrowing the
+ /// `BorrowedFd`, which can be tricky in situations where the `BorrowedFd`
+ /// is a temporary.
+ #[inline]
+ pub fn from_borrowed_fd(fd: BorrowedFd<'fd>, events: PollFlags) -> Self {
+ Self {
+ fd,
+ events: events.bits(),
+ revents: 0,
+ }
+ }
+
+ /// Returns the ready events.
+ #[inline]
+ pub fn revents(&self) -> PollFlags {
+ // Use `.unwrap()` here because in theory we know we know all the bits
+ // the OS might set here, but OS's have added extensions in the past.
+ PollFlags::from_bits(self.revents).unwrap()
+ }
+}
+
+impl<'fd> AsFd for PollFd<'fd> {
+ #[inline]
+ fn as_fd(&self) -> BorrowedFd<'_> {
+ self.fd.as_fd()
+ }
+}
diff --git a/vendor/rustix/src/backend/linux_raw/event/syscalls.rs b/vendor/rustix/src/backend/linux_raw/event/syscalls.rs
new file mode 100644
index 00000000..8a4e24bd
--- /dev/null
+++ b/vendor/rustix/src/backend/linux_raw/event/syscalls.rs
@@ -0,0 +1,358 @@
+//! linux_raw syscalls supporting `rustix::event`.
+//!
+//! # Safety
+//!
+//! See the `rustix::backend` module documentation for details.
+#![allow(unsafe_code, clippy::undocumented_unsafe_blocks)]
+
+use crate::backend::conv::{
+ by_ref, c_int, c_uint, opt_mut, opt_ref, pass_usize, ret, ret_c_int, ret_error, ret_owned_fd,
+ ret_usize, size_of, slice_mut, zero,
+};
+use crate::event::{epoll, EventfdFlags, FdSetElement, PollFd, Timespec};
+use crate::fd::{BorrowedFd, OwnedFd};
+use crate::io;
+use core::ptr::null_mut;
+use linux_raw_sys::general::{kernel_sigset_t, EPOLL_CTL_ADD, EPOLL_CTL_DEL, EPOLL_CTL_MOD};
+
+#[inline]
+pub(crate) fn poll(fds: &mut [PollFd<'_>], timeout: Option<&Timespec>) -> io::Result<usize> {
+ let (fds_addr_mut, fds_len) = slice_mut(fds);
+
+ #[cfg(target_pointer_width = "32")]
+ unsafe {
+ // If we don't have Linux 5.1, and the timeout fits in a
+ // `__kernel_old_timespec`, use plain `ppoll`.
+ //
+ // We do this unconditionally, rather than trying `ppoll_time64` and
+ // falling back on `Errno::NOSYS`, because seccomp configurations will
+ // sometimes abort the process on syscalls they don't recognize.
+ #[cfg(not(feature = "linux_5_1"))]
+ {
+ use linux_raw_sys::general::__kernel_old_timespec;
+
+ // If we don't have a timeout, or if we can convert the timeout to
+ // a `__kernel_old_timespec`, the use `__NR_ppoll`.
+ fn convert(timeout: &Timespec) -> Option<__kernel_old_timespec> {
+ Some(__kernel_old_timespec {
+ tv_sec: timeout.tv_sec.try_into().ok()?,
+ tv_nsec: timeout.tv_nsec.try_into().ok()?,
+ })
+ }
+ let old_timeout = if let Some(timeout) = timeout {
+ match convert(timeout) {
+ // Could not convert timeout.
+ None => None,
+ // Could convert timeout. Ok!
+ Some(old_timeout) => Some(Some(old_timeout)),
+ }
+ } else {
+ // No timeout. Ok!
+ Some(None)
+ };
+ if let Some(mut old_timeout) = old_timeout {
+ // Call `ppoll`.
+ //
+ // Linux's `ppoll` mutates the timeout argument. Our public
+ // interface does not do this, because it's not portable to other
+ // platforms, so we create a temporary value to hide this behavior.
+ return ret_usize(syscall!(
+ __NR_ppoll,
+ fds_addr_mut,
+ fds_len,
+ opt_mut(old_timeout.as_mut()),
+ zero(),
+ size_of::<kernel_sigset_t, _>()
+ ));
+ }
+ }
+
+ // We either have Linux 5.1 or the timeout didn't fit in
+ // `__kernel_old_timespec` so `__NR_ppoll_time64` will either
+ // succeed or fail due to our having no other options.
+
+ // Call `ppoll_time64`.
+ //
+ // Linux's `ppoll_time64` mutates the timeout argument. Our public
+ // interface does not do this, because it's not portable to other
+ // platforms, so we create a temporary value to hide this behavior.
+ ret_usize(syscall!(
+ __NR_ppoll_time64,
+ fds_addr_mut,
+ fds_len,
+ opt_mut(timeout.copied().as_mut()),
+ zero(),
+ size_of::<kernel_sigset_t, _>()
+ ))
+ }
+
+ #[cfg(target_pointer_width = "64")]
+ unsafe {
+ // Call `ppoll`.
+ //
+ // Linux's `ppoll` mutates the timeout argument. Our public interface
+ // does not do this, because it's not portable to other platforms, so
+ // we create a temporary value to hide this behavior.
+ ret_usize(syscall!(
+ __NR_ppoll,
+ fds_addr_mut,
+ fds_len,
+ opt_mut(timeout.copied().as_mut()),
+ zero(),
+ size_of::<kernel_sigset_t, _>()
+ ))
+ }
+}
+
+pub(crate) unsafe fn select(
+ nfds: i32,
+ readfds: Option<&mut [FdSetElement]>,
+ writefds: Option<&mut [FdSetElement]>,
+ exceptfds: Option<&mut [FdSetElement]>,
+ timeout: Option<&crate::timespec::Timespec>,
+) -> io::Result<i32> {
+ let len = crate::event::fd_set_num_elements_for_bitvector(nfds);
+
+ let readfds = match readfds {
+ Some(readfds) => {
+ assert!(readfds.len() >= len);
+ readfds.as_mut_ptr()
+ }
+ None => null_mut(),
+ };
+ let writefds = match writefds {
+ Some(writefds) => {
+ assert!(writefds.len() >= len);
+ writefds.as_mut_ptr()
+ }
+ None => null_mut(),
+ };
+ let exceptfds = match exceptfds {
+ Some(exceptfds) => {
+ assert!(exceptfds.len() >= len);
+ exceptfds.as_mut_ptr()
+ }
+ None => null_mut(),
+ };
+
+ #[cfg(target_pointer_width = "32")]
+ {
+ // If we don't have Linux 5.1, and the timeout fits in a
+ // `__kernel_old_timespec`, use plain `pselect6`.
+ //
+ // We do this unconditionally, rather than trying `pselect6_time64` and
+ // falling back on `Errno::NOSYS`, because seccomp configurations will
+ // sometimes abort the process on syscalls they don't recognize.
+ #[cfg(not(feature = "linux_5_1"))]
+ {
+ use linux_raw_sys::general::__kernel_old_timespec;
+
+ // If we don't have a timeout, or if we can convert the timeout to
+ // a `__kernel_old_timespec`, the use `__NR_pselect6`.
+ fn convert(timeout: &Timespec) -> Option<__kernel_old_timespec> {
+ Some(__kernel_old_timespec {
+ tv_sec: timeout.tv_sec.try_into().ok()?,
+ tv_nsec: timeout.tv_nsec.try_into().ok()?,
+ })
+ }
+ let old_timeout = if let Some(timeout) = timeout {
+ match convert(timeout) {
+ // Could not convert timeout.
+ None => None,
+ // Could convert timeout. Ok!
+ Some(old_timeout) => Some(Some(old_timeout)),
+ }
+ } else {
+ // No timeout. Ok!
+ Some(None)
+ };
+ if let Some(mut old_timeout) = old_timeout {
+ // Call `pselect6`.
+ //
+ // Linux's `pselect6` mutates the timeout argument. Our public
+ // interface does not do this, because it's not portable to other
+ // platforms, so we create a temporary value to hide this behavior.
+ return ret_c_int(syscall!(
+ __NR_pselect6,
+ c_int(nfds),
+ readfds,
+ writefds,
+ exceptfds,
+ opt_mut(old_timeout.as_mut()),
+ zero()
+ ));
+ }
+ }
+
+ // We either have Linux 5.1 or the timeout didn't fit in
+ // `__kernel_old_timespec` so `__NR_pselect6_time64` will either
+ // succeed or fail due to our having no other options.
+
+ // Call `pselect6_time64`.
+ //
+ // Linux's `pselect6_time64` mutates the timeout argument. Our public
+ // interface does not do this, because it's not portable to other
+ // platforms, so we create a temporary value to hide this behavior.
+ ret_c_int(syscall!(
+ __NR_pselect6_time64,
+ c_int(nfds),
+ readfds,
+ writefds,
+ exceptfds,
+ opt_mut(timeout.copied().as_mut()),
+ zero()
+ ))
+ }
+
+ #[cfg(target_pointer_width = "64")]
+ {
+ // Call `pselect6`.
+ //
+ // Linux's `pselect6` mutates the timeout argument. Our public interface
+ // does not do this, because it's not portable to other platforms, so we
+ // create a temporary value to hide this behavior.
+ ret_c_int(syscall!(
+ __NR_pselect6,
+ c_int(nfds),
+ readfds,
+ writefds,
+ exceptfds,
+ opt_mut(timeout.copied().as_mut()),
+ zero()
+ ))
+ }
+}
+
+#[inline]
+pub(crate) fn epoll_create(flags: epoll::CreateFlags) -> io::Result<OwnedFd> {
+ // SAFETY: `__NR_epoll_create1` doesn't access any user memory.
+ unsafe { ret_owned_fd(syscall_readonly!(__NR_epoll_create1, flags)) }
+}
+
+#[inline]
+pub(crate) fn epoll_add(
+ epfd: BorrowedFd<'_>,
+ fd: BorrowedFd<'_>,
+ event: &epoll::Event,
+) -> io::Result<()> {
+ // SAFETY: `__NR_epoll_ctl` with `EPOLL_CTL_ADD` doesn't modify any user
+ // memory, and it only reads from `event`.
+ unsafe {
+ ret(syscall_readonly!(
+ __NR_epoll_ctl,
+ epfd,
+ c_uint(EPOLL_CTL_ADD),
+ fd,
+ by_ref(event)
+ ))
+ }
+}
+
+#[inline]
+pub(crate) fn epoll_mod(
+ epfd: BorrowedFd<'_>,
+ fd: BorrowedFd<'_>,
+ event: &epoll::Event,
+) -> io::Result<()> {
+ // SAFETY: `__NR_epoll_ctl` with `EPOLL_CTL_MOD` doesn't modify any user
+ // memory, and it only reads from `event`.
+ unsafe {
+ ret(syscall_readonly!(
+ __NR_epoll_ctl,
+ epfd,
+ c_uint(EPOLL_CTL_MOD),
+ fd,
+ by_ref(event)
+ ))
+ }
+}
+
+#[inline]
+pub(crate) fn epoll_del(epfd: BorrowedFd<'_>, fd: BorrowedFd<'_>) -> io::Result<()> {
+ // SAFETY: `__NR_epoll_ctl` with `EPOLL_CTL_DEL` doesn't access any user
+ // memory.
+ unsafe {
+ ret(syscall_readonly!(
+ __NR_epoll_ctl,
+ epfd,
+ c_uint(EPOLL_CTL_DEL),
+ fd,
+ zero()
+ ))
+ }
+}
+
+#[inline]
+pub(crate) unsafe fn epoll_wait(
+ epfd: BorrowedFd<'_>,
+ events: (*mut crate::event::epoll::Event, usize),
+ timeout: Option<&Timespec>,
+) -> io::Result<usize> {
+ // If we don't have Linux 5.1, and the timeout fits in an `i32`, use plain
+ // `epoll_pwait`.
+ //
+ // We do this unconditionally, rather than trying `epoll_pwait2` and
+ // falling back on `Errno::NOSYS`, because seccomp configurations will
+ // sometimes abort the process on syscalls they don't recognize.
+ #[cfg(not(feature = "linux_5_11"))]
+ {
+ // If we don't have a timeout, or if we can convert the timeout to an
+ // `i32`, the use `__NR_epoll_pwait`.
+ let old_timeout = if let Some(timeout) = timeout {
+ // Try to convert the timeout; if this is `Some`, we're ok!
+ timeout.as_c_int_millis()
+ } else {
+ // No timeout. Ok!
+ Some(-1)
+ };
+ if let Some(old_timeout) = old_timeout {
+ // Call `epoll_pwait`.
+ return ret_usize(syscall!(
+ __NR_epoll_pwait,
+ epfd,
+ events.0,
+ pass_usize(events.1),
+ c_int(old_timeout),
+ zero()
+ ));
+ }
+ }
+
+ // Call `epoll_pwait2`.
+ //
+ // We either have Linux 5.1 or the timeout didn't fit in an `i32`, so
+ // `__NR_epoll_pwait2` will either succeed or fail due to our having no
+ // other options.
+ ret_usize(syscall!(
+ __NR_epoll_pwait2,
+ epfd,
+ events.0,
+ pass_usize(events.1),
+ opt_ref(timeout),
+ zero()
+ ))
+}
+
+#[inline]
+pub(crate) fn eventfd(initval: u32, flags: EventfdFlags) -> io::Result<OwnedFd> {
+ unsafe { ret_owned_fd(syscall_readonly!(__NR_eventfd2, c_uint(initval), flags)) }
+}
+
+#[inline]
+pub(crate) fn pause() {
+ unsafe {
+ #[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))]
+ let error = ret_error(syscall_readonly!(
+ __NR_ppoll,
+ zero(),
+ zero(),
+ zero(),
+ zero()
+ ));
+
+ #[cfg(not(any(target_arch = "aarch64", target_arch = "riscv64")))]
+ let error = ret_error(syscall_readonly!(__NR_pause));
+
+ debug_assert_eq!(error, io::Errno::INTR);
+ }
+}
diff --git a/vendor/rustix/src/backend/linux_raw/event/types.rs b/vendor/rustix/src/backend/linux_raw/event/types.rs
new file mode 100644
index 00000000..9d320dfe
--- /dev/null
+++ b/vendor/rustix/src/backend/linux_raw/event/types.rs
@@ -0,0 +1,21 @@
+use crate::ffi;
+use bitflags::bitflags;
+
+bitflags! {
+ /// `EFD_*` flags for use with [`eventfd`].
+ ///
+ /// [`eventfd`]: crate::event::eventfd
+ #[repr(transparent)]
+ #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
+ pub struct EventfdFlags: ffi::c_uint {
+ /// `EFD_CLOEXEC`
+ const CLOEXEC = linux_raw_sys::general::EFD_CLOEXEC;
+ /// `EFD_NONBLOCK`
+ const NONBLOCK = linux_raw_sys::general::EFD_NONBLOCK;
+ /// `EFD_SEMAPHORE`
+ const SEMAPHORE = linux_raw_sys::general::EFD_SEMAPHORE;
+
+ /// <https://docs.rs/bitflags/*/bitflags/#externally-defined-flags>
+ const _ = !0;
+ }
+}