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/libc/event | |
| parent | 4351c74c7c5f97156bc94d3a8549b9940ac80e3f (diff) | |
chore: add vendor directory
Diffstat (limited to 'vendor/rustix/src/backend/libc/event')
| -rw-r--r-- | vendor/rustix/src/backend/libc/event/epoll.rs | 74 | ||||
| -rw-r--r-- | vendor/rustix/src/backend/libc/event/mod.rs | 9 | ||||
| -rw-r--r-- | vendor/rustix/src/backend/libc/event/poll_fd.rs | 143 | ||||
| -rw-r--r-- | vendor/rustix/src/backend/libc/event/syscalls.rs | 631 | ||||
| -rw-r--r-- | vendor/rustix/src/backend/libc/event/types.rs | 37 | ||||
| -rw-r--r-- | vendor/rustix/src/backend/libc/event/windows_syscalls.rs | 79 |
6 files changed, 973 insertions, 0 deletions
diff --git a/vendor/rustix/src/backend/libc/event/epoll.rs b/vendor/rustix/src/backend/libc/event/epoll.rs new file mode 100644 index 00000000..08f4bacc --- /dev/null +++ b/vendor/rustix/src/backend/libc/event/epoll.rs @@ -0,0 +1,74 @@ +use crate::backend::c; +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: u32 { + /// `EPOLL_CLOEXEC` + const CLOEXEC = bitcast!(c::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 = bitcast!(c::EPOLLIN); + + /// `EPOLLOUT` + const OUT = bitcast!(c::EPOLLOUT); + + /// `EPOLLPRI` + const PRI = bitcast!(c::EPOLLPRI); + + /// `EPOLLERR` + const ERR = bitcast!(c::EPOLLERR); + + /// `EPOLLHUP` + const HUP = bitcast!(c::EPOLLHUP); + + /// `EPOLLRDNORM` + const RDNORM = bitcast!(c::EPOLLRDNORM); + + /// `EPOLLRDBAND` + const RDBAND = bitcast!(c::EPOLLRDBAND); + + /// `EPOLLWRNORM` + const WRNORM = bitcast!(c::EPOLLWRNORM); + + /// `EPOLLWRBAND` + const WRBAND = bitcast!(c::EPOLLWRBAND); + + /// `EPOLLMSG` + const MSG = bitcast!(c::EPOLLMSG); + + /// `EPOLLRDHUP` + const RDHUP = bitcast!(c::EPOLLRDHUP); + + /// `EPOLLET` + const ET = bitcast!(c::EPOLLET); + + /// `EPOLLONESHOT` + const ONESHOT = bitcast!(c::EPOLLONESHOT); + + /// `EPOLLWAKEUP` + const WAKEUP = bitcast!(c::EPOLLWAKEUP); + + /// `EPOLLEXCLUSIVE` + const EXCLUSIVE = bitcast!(c::EPOLLEXCLUSIVE); + + /// <https://docs.rs/bitflags/*/bitflags/#externally-defined-flags> + const _ = !0; + } +} diff --git a/vendor/rustix/src/backend/libc/event/mod.rs b/vendor/rustix/src/backend/libc/event/mod.rs new file mode 100644 index 00000000..ff826fc4 --- /dev/null +++ b/vendor/rustix/src/backend/libc/event/mod.rs @@ -0,0 +1,9 @@ +pub(crate) mod poll_fd; +#[cfg(not(windows))] +pub(crate) mod types; + +#[cfg_attr(windows, path = "windows_syscalls.rs")] +pub(crate) mod syscalls; + +#[cfg(any(linux_kernel, target_os = "illumos", target_os = "redox"))] +pub mod epoll; diff --git a/vendor/rustix/src/backend/libc/event/poll_fd.rs b/vendor/rustix/src/backend/libc/event/poll_fd.rs new file mode 100644 index 00000000..fdaa6c68 --- /dev/null +++ b/vendor/rustix/src/backend/libc/event/poll_fd.rs @@ -0,0 +1,143 @@ +use crate::backend::c; +use crate::backend::conv::borrowed_fd; +use crate::backend::fd::{AsFd, AsRawFd as _, BorrowedFd, LibcFd}; +#[cfg(windows)] +use crate::backend::fd::{AsSocket, RawFd}; +use crate::ffi; +use bitflags::bitflags; +use core::fmt; +use core::marker::PhantomData; + +bitflags! { + /// `POLL*` flags for use with [`poll`]. + /// + /// [`poll`]: crate::event::poll + #[repr(transparent)] + #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] + pub struct PollFlags: ffi::c_short { + /// `POLLIN` + const IN = c::POLLIN; + /// `POLLPRI` + #[cfg(not(target_os = "wasi"))] + const PRI = c::POLLPRI; + /// `POLLOUT` + const OUT = c::POLLOUT; + /// `POLLRDNORM` + const RDNORM = c::POLLRDNORM; + /// `POLLWRNORM` + #[cfg(not(target_os = "l4re"))] + const WRNORM = c::POLLWRNORM; + /// `POLLRDBAND` + #[cfg(not(any(target_os = "l4re", target_os = "wasi")))] + const RDBAND = c::POLLRDBAND; + /// `POLLWRBAND` + #[cfg(not(any(target_os = "l4re", target_os = "wasi")))] + const WRBAND = c::POLLWRBAND; + /// `POLLERR` + const ERR = c::POLLERR; + /// `POLLHUP` + const HUP = c::POLLHUP; + /// `POLLNVAL` + #[cfg(not(target_os = "espidf"))] + const NVAL = c::POLLNVAL; + /// `POLLRDHUP` + #[cfg(any( + target_os = "freebsd", + target_os = "illumos", + all( + linux_kernel, + not(any(target_arch = "sparc", target_arch = "sparc64")) + ), + ))] + const RDHUP = c::POLLRDHUP; + + /// <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")] +#[derive(Clone)] +#[repr(transparent)] +pub struct PollFd<'fd> { + pollfd: c::pollfd, + _phantom: PhantomData<BorrowedFd<'fd>>, +} + +impl<'fd> fmt::Debug for PollFd<'fd> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("PollFd") + .field("fd", &self.pollfd.fd) + .field("events", &self.pollfd.events) + .field("revents", &self.pollfd.revents) + .finish() + } +} + +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.pollfd.fd = fd.as_fd().as_raw_fd() as LibcFd; + } + + /// Clears the ready events. + #[inline] + pub fn clear_revents(&mut self) { + self.pollfd.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 { + pollfd: c::pollfd { + fd: borrowed_fd(fd), + events: events.bits(), + revents: 0, + }, + _phantom: PhantomData, + } + } + + /// 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.pollfd.revents).unwrap() + } +} + +#[cfg(not(windows))] +impl<'fd> AsFd for PollFd<'fd> { + #[inline] + fn as_fd(&self) -> BorrowedFd<'_> { + // SAFETY: Our constructors and `set_fd` require `pollfd.fd` to be + // valid for the `'fd` lifetime. + unsafe { BorrowedFd::borrow_raw(self.pollfd.fd) } + } +} + +#[cfg(windows)] +impl<'fd> AsSocket for PollFd<'fd> { + #[inline] + fn as_socket(&self) -> BorrowedFd<'_> { + // SAFETY: Our constructors and `set_fd` require `pollfd.fd` to be + // valid for the `'fd` lifetime. + unsafe { BorrowedFd::borrow_raw(self.pollfd.fd as RawFd) } + } +} diff --git a/vendor/rustix/src/backend/libc/event/syscalls.rs b/vendor/rustix/src/backend/libc/event/syscalls.rs new file mode 100644 index 00000000..3827a2f9 --- /dev/null +++ b/vendor/rustix/src/backend/libc/event/syscalls.rs @@ -0,0 +1,631 @@ +//! libc syscalls supporting `rustix::event`. + +use crate::backend::c; +#[cfg(any(linux_kernel, solarish, target_os = "redox"))] +use crate::backend::conv::ret; +use crate::backend::conv::ret_c_int; +#[cfg(any(linux_kernel, target_os = "illumos", target_os = "redox"))] +use crate::backend::conv::ret_u32; +#[cfg(bsd)] +use crate::event::kqueue::Event; +#[cfg(solarish)] +use crate::event::port::Event; +#[cfg(any( + linux_kernel, + target_os = "freebsd", + target_os = "illumos", + target_os = "espidf" +))] +use crate::event::EventfdFlags; +#[cfg(any(bsd, linux_kernel, target_os = "wasi"))] +use crate::event::FdSetElement; +use crate::event::{PollFd, Timespec}; +use crate::io; +#[cfg(any(linux_kernel, target_os = "illumos", target_os = "redox"))] +use crate::utils::as_ptr; +#[cfg(solarish)] +use core::mem::MaybeUninit; +#[cfg(any( + bsd, + linux_kernel, + target_os = "fuchsia", + target_os = "haiku", + target_os = "hurd", + target_os = "netbsd", + target_os = "wasi" +))] +use core::ptr::null; +#[cfg(any(bsd, linux_kernel, solarish, target_os = "redox", target_os = "wasi"))] +use core::ptr::null_mut; +#[cfg(any(bsd, linux_kernel, solarish, target_os = "redox"))] +use {crate::backend::conv::borrowed_fd, crate::fd::BorrowedFd}; +#[cfg(any( + bsd, + linux_kernel, + solarish, + target_os = "freebsd", + target_os = "illumos", + target_os = "espidf", + target_os = "redox" +))] +use {crate::backend::conv::ret_owned_fd, crate::fd::OwnedFd}; + +#[cfg(any( + linux_kernel, + target_os = "freebsd", + target_os = "illumos", + target_os = "espidf" +))] +pub(crate) fn eventfd(initval: u32, flags: EventfdFlags) -> io::Result<OwnedFd> { + #[cfg(linux_kernel)] + unsafe { + syscall! { + fn eventfd2( + initval: c::c_uint, + flags: c::c_int + ) via SYS_eventfd2 -> c::c_int + } + ret_owned_fd(eventfd2(initval, bitflags_bits!(flags))) + } + + // `eventfd` was added in FreeBSD 13, so it isn't available on FreeBSD 12. + #[cfg(target_os = "freebsd")] + unsafe { + weakcall! { + fn eventfd( + initval: c::c_uint, + flags: c::c_int + ) -> c::c_int + } + ret_owned_fd(eventfd(initval, bitflags_bits!(flags))) + } + + #[cfg(any(target_os = "illumos", target_os = "espidf"))] + unsafe { + ret_owned_fd(c::eventfd(initval, bitflags_bits!(flags))) + } +} + +#[cfg(bsd)] +pub(crate) fn kqueue() -> io::Result<OwnedFd> { + unsafe { ret_owned_fd(c::kqueue()) } +} + +#[cfg(bsd)] +pub(crate) unsafe fn kevent( + kq: BorrowedFd<'_>, + changelist: &[Event], + eventlist: (*mut Event, usize), + timeout: Option<&Timespec>, +) -> io::Result<c::c_int> { + // If we don't have to fix y2038 on this platform, `Timespec` is the same + // as `c::timespec` and it's easy. + #[cfg(not(fix_y2038))] + let timeout = crate::timespec::option_as_libc_timespec_ptr(timeout); + + // If we do have to fix y2038 on this platform, convert to `c::timespec`. + #[cfg(fix_y2038)] + let converted_timeout; + #[cfg(fix_y2038)] + let timeout = match timeout { + None => null(), + Some(timeout) => { + converted_timeout = c::timespec { + tv_sec: timeout.tv_sec.try_into().map_err(|_| io::Errno::OVERFLOW)?, + tv_nsec: timeout.tv_nsec as _, + }; + &converted_timeout + } + }; + + ret_c_int(c::kevent( + borrowed_fd(kq), + changelist.as_ptr().cast(), + changelist + .len() + .try_into() + .map_err(|_| io::Errno::OVERFLOW)?, + eventlist.0.cast(), + eventlist.1.try_into().map_err(|_| io::Errno::OVERFLOW)?, + timeout, + )) +} + +#[inline] +pub(crate) fn poll(fds: &mut [PollFd<'_>], timeout: Option<&Timespec>) -> io::Result<usize> { + let nfds = fds + .len() + .try_into() + .map_err(|_convert_err| io::Errno::INVAL)?; + + // If we have `ppoll`, it supports a `timespec` timeout, so use it. + #[cfg(any( + linux_kernel, + freebsdlike, + target_os = "fuchsia", + target_os = "haiku", + target_os = "hurd", + target_os = "netbsd" + ))] + { + // If we don't have to fix y2038 on this platform, `Timespec` is + // the same as `c::timespec` and it's easy. + #[cfg(not(fix_y2038))] + let timeout = crate::timespec::option_as_libc_timespec_ptr(timeout); + + // If we do have to fix y2038 on this platform, convert to + // `c::timespec`. + #[cfg(fix_y2038)] + let converted_timeout; + #[cfg(fix_y2038)] + let timeout = match timeout { + None => null(), + Some(timeout) => { + converted_timeout = c::timespec { + tv_sec: timeout.tv_sec.try_into().map_err(|_| io::Errno::OVERFLOW)?, + tv_nsec: timeout.tv_nsec as _, + }; + &converted_timeout + } + }; + + #[cfg(not(target_os = "netbsd"))] + { + ret_c_int(unsafe { c::ppoll(fds.as_mut_ptr().cast(), nfds, timeout, null()) }) + .map(|nready| nready as usize) + } + + // NetBSD 9.x lacks `ppoll`, so use a weak symbol and fall back to + // plain `poll` if needed. + #[cfg(target_os = "netbsd")] + { + weak! { + fn ppoll( + *mut c::pollfd, + c::nfds_t, + *const c::timespec, + *const c::sigset_t + ) -> c::c_int + } + if let Some(func) = ppoll.get() { + return ret_c_int(unsafe { func(fds.as_mut_ptr().cast(), nfds, timeout, null()) }) + .map(|nready| nready as usize); + } + } + } + + // If we don't have `ppoll`, convert the timeout to `c_int` and use `poll`. + #[cfg(not(any( + linux_kernel, + freebsdlike, + target_os = "fuchsia", + target_os = "haiku", + target_os = "hurd" + )))] + { + let timeout = match timeout { + None => -1, + Some(timeout) => timeout.as_c_int_millis().ok_or(io::Errno::INVAL)?, + }; + ret_c_int(unsafe { c::poll(fds.as_mut_ptr().cast(), nfds, timeout) }) + .map(|nready| nready as usize) + } +} + +#[cfg(any(bsd, linux_kernel))] +pub(crate) unsafe fn select( + nfds: i32, + readfds: Option<&mut [FdSetElement]>, + writefds: Option<&mut [FdSetElement]>, + exceptfds: Option<&mut [FdSetElement]>, + timeout: Option<&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(), + }; + + let timeout_data; + let timeout_ptr = match timeout { + Some(timeout) => { + // Convert from `Timespec` to `c::timeval`. + timeout_data = c::timeval { + tv_sec: timeout.tv_sec.try_into().map_err(|_| io::Errno::INVAL)?, + tv_usec: ((timeout.tv_nsec + 999) / 1000) as _, + }; + &timeout_data + } + None => null(), + }; + + // On Apple platforms, use the specially mangled `select` which doesn't + // have an `FD_SETSIZE` limitation. + #[cfg(apple)] + { + extern "C" { + #[link_name = "select$DARWIN_EXTSN$NOCANCEL"] + fn select( + nfds: c::c_int, + readfds: *mut FdSetElement, + writefds: *mut FdSetElement, + errorfds: *mut FdSetElement, + timeout: *const c::timeval, + ) -> c::c_int; + } + + ret_c_int(select(nfds, readfds, writefds, exceptfds, timeout_ptr)) + } + + // Otherwise just use the normal `select`. + #[cfg(not(apple))] + { + ret_c_int(c::select( + nfds, + readfds.cast(), + writefds.cast(), + exceptfds.cast(), + timeout_ptr as *mut c::timeval, + )) + } +} + +// WASI uses a count + array instead of a bitvector. +#[cfg(target_os = "wasi")] +pub(crate) unsafe fn select( + nfds: i32, + readfds: Option<&mut [FdSetElement]>, + writefds: Option<&mut [FdSetElement]>, + exceptfds: Option<&mut [FdSetElement]>, + timeout: Option<&Timespec>, +) -> io::Result<i32> { + let len = crate::event::fd_set_num_elements_for_fd_array(nfds as usize); + + 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(), + }; + + let timeout_data; + let timeout_ptr = match timeout { + Some(timeout) => { + // Convert from `Timespec` to `c::timeval`. + timeout_data = c::timeval { + tv_sec: timeout.tv_sec.try_into().map_err(|_| io::Errno::INVAL)?, + tv_usec: ((timeout.tv_nsec + 999) / 1000) as _, + }; + &timeout_data + } + None => null(), + }; + + ret_c_int(c::select( + nfds, + readfds.cast(), + writefds.cast(), + exceptfds.cast(), + timeout_ptr as *mut c::timeval, + )) +} + +#[cfg(solarish)] +pub(crate) fn port_create() -> io::Result<OwnedFd> { + unsafe { ret_owned_fd(c::port_create()) } +} + +#[cfg(solarish)] +pub(crate) unsafe fn port_associate( + port: BorrowedFd<'_>, + source: c::c_int, + object: c::uintptr_t, + events: c::c_int, + user: *mut c::c_void, +) -> io::Result<()> { + ret(c::port_associate( + borrowed_fd(port), + source, + object, + events, + user, + )) +} + +#[cfg(solarish)] +pub(crate) unsafe fn port_dissociate( + port: BorrowedFd<'_>, + source: c::c_int, + object: c::uintptr_t, +) -> io::Result<()> { + ret(c::port_dissociate(borrowed_fd(port), source, object)) +} + +#[cfg(solarish)] +pub(crate) fn port_get(port: BorrowedFd<'_>, timeout: Option<&Timespec>) -> io::Result<Event> { + // If we don't have to fix y2038 on this platform, `Timespec` is + // the same as `c::timespec` and it's easy. + #[cfg(not(fix_y2038))] + let timeout = crate::timespec::option_as_libc_timespec_ptr(timeout); + + // If we do have to fix y2038 on this platform, convert to + // `c::timespec`. + #[cfg(fix_y2038)] + let converted_timeout; + #[cfg(fix_y2038)] + let timeout = match timeout { + None => null(), + Some(timeout) => { + converted_timeout = c::timespec { + tv_sec: timeout.tv_sec.try_into().map_err(|_| io::Errno::OVERFLOW)?, + tv_nsec: timeout.tv_nsec as _, + }; + &converted_timeout + } + }; + + let mut event = MaybeUninit::<c::port_event>::uninit(); + + // In Rust ≥ 1.65, the `as _` can be `.cast_mut()`. + unsafe { + ret(c::port_get( + borrowed_fd(port), + event.as_mut_ptr(), + timeout as _, + ))?; + } + + // If we're done, initialize the event and return it. + Ok(Event(unsafe { event.assume_init() })) +} + +#[cfg(solarish)] +pub(crate) unsafe fn port_getn( + port: BorrowedFd<'_>, + events: (*mut Event, usize), + mut nget: u32, + timeout: Option<&Timespec>, +) -> io::Result<usize> { + // If we don't have to fix y2038 on this platform, `Timespec` is + // the same as `c::timespec` and it's easy. + #[cfg(not(fix_y2038))] + let timeout = crate::timespec::option_as_libc_timespec_ptr(timeout); + + // If we do have to fix y2038 on this platform, convert to + // `c::timespec`. + #[cfg(fix_y2038)] + let converted_timeout; + #[cfg(fix_y2038)] + let timeout = match timeout { + None => null(), + Some(timeout) => { + converted_timeout = c::timespec { + tv_sec: timeout.tv_sec.try_into().map_err(|_| io::Errno::OVERFLOW)?, + tv_nsec: timeout.tv_nsec as _, + }; + &converted_timeout + } + }; + + // `port_getn` special-cases a max value of 0 to be a query that returns + // the number of events, so bail out early if needed. + if events.1 == 0 { + return Ok(0); + } + + // In Rust ≥ 1.65, the `as _` can be `.cast_mut()`. + ret(c::port_getn( + borrowed_fd(port), + events.0.cast(), + events.1.try_into().unwrap_or(u32::MAX), + &mut nget, + timeout as _, + ))?; + + Ok(nget as usize) +} + +#[cfg(solarish)] +pub(crate) fn port_getn_query(port: BorrowedFd<'_>) -> io::Result<u32> { + let mut nget: u32 = 0; + + // Pass a `max` of 0 to query the number of available events. + unsafe { + ret(c::port_getn( + borrowed_fd(port), + null_mut(), + 0, + &mut nget, + null_mut(), + ))?; + } + + Ok(nget) +} + +#[cfg(solarish)] +pub(crate) fn port_send( + port: BorrowedFd<'_>, + events: c::c_int, + userdata: *mut c::c_void, +) -> io::Result<()> { + unsafe { ret(c::port_send(borrowed_fd(port), events, userdata)) } +} + +#[cfg(not(any(target_os = "redox", target_os = "wasi")))] +pub(crate) fn pause() { + let r = unsafe { c::pause() }; + let errno = libc_errno::errno().0; + debug_assert_eq!(r, -1); + debug_assert_eq!(errno, c::EINTR); +} + +#[inline] +#[cfg(any(linux_kernel, target_os = "illumos", target_os = "redox"))] +pub(crate) fn epoll_create(flags: super::epoll::CreateFlags) -> io::Result<OwnedFd> { + unsafe { ret_owned_fd(c::epoll_create1(bitflags_bits!(flags))) } +} + +#[inline] +#[cfg(any(linux_kernel, target_os = "illumos", target_os = "redox"))] +pub(crate) fn epoll_add( + epoll: BorrowedFd<'_>, + source: BorrowedFd<'_>, + event: &crate::event::epoll::Event, +) -> io::Result<()> { + // We use our own `Event` struct instead of libc's because + // ours preserves pointer provenance instead of just using a `u64`, + // and we have tests elsewhere for layout equivalence. + unsafe { + ret(c::epoll_ctl( + borrowed_fd(epoll), + c::EPOLL_CTL_ADD, + borrowed_fd(source), + // The event is read-only even though libc has a non-const pointer. + as_ptr(event) as *mut c::epoll_event, + )) + } +} + +#[inline] +#[cfg(any(linux_kernel, target_os = "illumos", target_os = "redox"))] +pub(crate) fn epoll_mod( + epoll: BorrowedFd<'_>, + source: BorrowedFd<'_>, + event: &crate::event::epoll::Event, +) -> io::Result<()> { + unsafe { + ret(c::epoll_ctl( + borrowed_fd(epoll), + c::EPOLL_CTL_MOD, + borrowed_fd(source), + // The event is read-only even though libc has a non-const pointer. + as_ptr(event) as *mut c::epoll_event, + )) + } +} + +#[inline] +#[cfg(any(linux_kernel, target_os = "illumos", target_os = "redox"))] +pub(crate) fn epoll_del(epoll: BorrowedFd<'_>, source: BorrowedFd<'_>) -> io::Result<()> { + unsafe { + ret(c::epoll_ctl( + borrowed_fd(epoll), + c::EPOLL_CTL_DEL, + borrowed_fd(source), + null_mut(), + )) + } +} + +#[inline] +#[cfg(any(linux_kernel, target_os = "illumos", target_os = "redox"))] +pub(crate) unsafe fn epoll_wait( + epoll: BorrowedFd<'_>, + events: (*mut crate::event::epoll::Event, usize), + timeout: Option<&Timespec>, +) -> io::Result<usize> { + // If we're on Linux ≥ 5.11 and a libc that has an `epoll_pwait2` + // function, and it's y2038-safe, use it. + #[cfg(all( + linux_kernel, + feature = "linux_5_11", + target_env = "gnu", + not(fix_y2038) + ))] + { + weak! { + fn epoll_pwait2( + c::c_int, + *mut c::epoll_event, + c::c_int, + *const c::timespec, + *const c::sigset_t + ) -> c::c_int + } + + if let Some(epoll_pwait2_func) = epoll_pwait2.get() { + return ret_u32(epoll_pwait2_func( + borrowed_fd(epoll), + events.0.cast::<c::epoll_event>(), + events.1.try_into().unwrap_or(i32::MAX), + crate::utils::option_as_ptr(timeout).cast(), + null(), + )) + .map(|i| i as usize); + } + } + + // If we're on Linux ≥ 5.11, use `epoll_pwait2` via `libc::syscall`. + #[cfg(all(linux_kernel, feature = "linux_5_11"))] + { + syscall! { + fn epoll_pwait2( + epfd: c::c_int, + events: *mut c::epoll_event, + maxevents: c::c_int, + timeout: *const Timespec, + sigmask: *const c::sigset_t + ) via SYS_epoll_pwait2 -> c::c_int + } + + ret_u32(epoll_pwait2( + borrowed_fd(epoll), + events.0.cast::<c::epoll_event>(), + events.1.try_into().unwrap_or(i32::MAX), + crate::utils::option_as_ptr(timeout).cast(), + null(), + )) + .map(|i| i as usize) + } + + // Otherwise just use `epoll_wait`. + #[cfg(not(all(linux_kernel, feature = "linux_5_11")))] + { + let timeout = match timeout { + None => -1, + Some(timeout) => timeout.as_c_int_millis().ok_or(io::Errno::INVAL)?, + }; + + ret_u32(c::epoll_wait( + borrowed_fd(epoll), + events.0.cast::<c::epoll_event>(), + events.1.try_into().unwrap_or(i32::MAX), + timeout, + )) + .map(|i| i as usize) + } +} diff --git a/vendor/rustix/src/backend/libc/event/types.rs b/vendor/rustix/src/backend/libc/event/types.rs new file mode 100644 index 00000000..a04d7e6c --- /dev/null +++ b/vendor/rustix/src/backend/libc/event/types.rs @@ -0,0 +1,37 @@ +#[cfg(any(linux_kernel, target_os = "freebsd", target_os = "illumos"))] +use crate::backend::c; +#[cfg(any( + linux_kernel, + target_os = "freebsd", + target_os = "illumos", + target_os = "espidf" +))] +use bitflags::bitflags; + +#[cfg(any( + linux_kernel, + target_os = "freebsd", + target_os = "illumos", + target_os = "espidf" +))] +bitflags! { + /// `EFD_*` flags for use with [`eventfd`]. + /// + /// [`eventfd`]: crate::event::eventfd + #[repr(transparent)] + #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] + pub struct EventfdFlags: u32 { + /// `EFD_CLOEXEC` + #[cfg(not(target_os = "espidf"))] + const CLOEXEC = bitcast!(c::EFD_CLOEXEC); + /// `EFD_NONBLOCK` + #[cfg(not(target_os = "espidf"))] + const NONBLOCK = bitcast!(c::EFD_NONBLOCK); + /// `EFD_SEMAPHORE` + #[cfg(not(target_os = "espidf"))] + const SEMAPHORE = bitcast!(c::EFD_SEMAPHORE); + + /// <https://docs.rs/bitflags/*/bitflags/#externally-defined-flags> + const _ = !0; + } +} diff --git a/vendor/rustix/src/backend/libc/event/windows_syscalls.rs b/vendor/rustix/src/backend/libc/event/windows_syscalls.rs new file mode 100644 index 00000000..05394f55 --- /dev/null +++ b/vendor/rustix/src/backend/libc/event/windows_syscalls.rs @@ -0,0 +1,79 @@ +//! Windows system calls in the `event` module. + +use crate::backend::c; +use crate::backend::conv::ret_c_int; +use crate::event::{FdSetElement, PollFd, Timespec}; +use crate::io; + +pub(crate) fn poll(fds: &mut [PollFd<'_>], timeout: Option<&Timespec>) -> io::Result<usize> { + let nfds = fds + .len() + .try_into() + .map_err(|_convert_err| io::Errno::INVAL)?; + + let timeout = match timeout { + None => -1, + Some(timeout) => timeout.as_c_int_millis().ok_or(io::Errno::INVAL)?, + }; + + ret_c_int(unsafe { c::poll(fds.as_mut_ptr().cast(), nfds, timeout) }) + .map(|nready| nready as usize) +} + +pub(crate) fn select( + nfds: i32, + readfds: Option<&mut [FdSetElement]>, + writefds: Option<&mut [FdSetElement]>, + exceptfds: Option<&mut [FdSetElement]>, + timeout: Option<&crate::timespec::Timespec>, +) -> io::Result<i32> { + use core::ptr::{null, null_mut}; + + let readfds = match readfds { + Some(readfds) => { + assert!(readfds.len() >= readfds[0].0 as usize); + readfds.as_mut_ptr() + } + None => null_mut(), + }; + let writefds = match writefds { + Some(writefds) => { + assert!(writefds.len() >= writefds[0].0 as usize); + writefds.as_mut_ptr() + } + None => null_mut(), + }; + let exceptfds = match exceptfds { + Some(exceptfds) => { + assert!(exceptfds.len() >= exceptfds[0].0 as usize); + exceptfds.as_mut_ptr() + } + None => null_mut(), + }; + + let timeout_data; + let timeout_ptr = match timeout { + Some(timeout) => { + // Convert from `Timespec` to `TIMEVAL`. + timeout_data = c::TIMEVAL { + tv_sec: timeout + .tv_sec + .try_into() + .map_err(|_| io::Errno::OPNOTSUPP)?, + tv_usec: ((timeout.tv_nsec + 999) / 1000) as _, + }; + &timeout_data + } + None => null(), + }; + + unsafe { + ret_c_int(c::select( + nfds, + readfds.cast(), + writefds.cast(), + exceptfds.cast(), + timeout_ptr, + )) + } +} |
