diff options
| author | mo khan <mo@mokhan.ca> | 2025-07-02 18:36:06 -0600 |
|---|---|---|
| committer | mo khan <mo@mokhan.ca> | 2025-07-02 18:36:06 -0600 |
| commit | 8cdfa445d6629ffef4cb84967ff7017654045bc2 (patch) | |
| tree | 22f0b0907c024c78d26a731e2e1f5219407d8102 /vendor/rustix/src/backend/linux_raw/event | |
| parent | 4351c74c7c5f97156bc94d3a8549b9940ac80e3f (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.rs | 74 | ||||
| -rw-r--r-- | vendor/rustix/src/backend/linux_raw/event/mod.rs | 4 | ||||
| -rw-r--r-- | vendor/rustix/src/backend/linux_raw/event/poll_fd.rs | 98 | ||||
| -rw-r--r-- | vendor/rustix/src/backend/linux_raw/event/syscalls.rs | 358 | ||||
| -rw-r--r-- | vendor/rustix/src/backend/linux_raw/event/types.rs | 21 |
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; + } +} |
