diff options
| author | Valentin Popov <valentin@popov.link> | 2024-01-08 00:21:28 +0300 | 
|---|---|---|
| committer | Valentin Popov <valentin@popov.link> | 2024-01-08 00:21:28 +0300 | 
| commit | 1b6a04ca5504955c571d1c97504fb45ea0befee4 (patch) | |
| tree | 7579f518b23313e8a9748a88ab6173d5e030b227 /vendor/rustix/src/backend/libc/event | |
| parent | 5ecd8cf2cba827454317368b68571df0d13d7842 (diff) | |
| download | fparkan-1b6a04ca5504955c571d1c97504fb45ea0befee4.tar.xz fparkan-1b6a04ca5504955c571d1c97504fb45ea0befee4.zip  | |
Initial vendor packages
Signed-off-by: Valentin Popov <valentin@popov.link>
Diffstat (limited to 'vendor/rustix/src/backend/libc/event')
| -rw-r--r-- | vendor/rustix/src/backend/libc/event/epoll.rs | 496 | ||||
| -rw-r--r-- | vendor/rustix/src/backend/libc/event/mod.rs | 9 | ||||
| -rw-r--r-- | vendor/rustix/src/backend/libc/event/poll_fd.rs | 142 | ||||
| -rw-r--r-- | vendor/rustix/src/backend/libc/event/syscalls.rs | 191 | ||||
| -rw-r--r-- | vendor/rustix/src/backend/libc/event/types.rs | 37 | ||||
| -rw-r--r-- | vendor/rustix/src/backend/libc/event/windows_syscalls.rs | 16 | 
6 files changed, 891 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 0000000..ced3be1 --- /dev/null +++ b/vendor/rustix/src/backend/libc/event/epoll.rs @@ -0,0 +1,496 @@ +//! Linux `epoll` support. +//! +//! # Examples +//! +//! ```no_run +//! # #[cfg(feature = "net")] +//! # fn main() -> std::io::Result<()> { +//! use rustix::event::epoll; +//! use rustix::fd::AsFd; +//! use rustix::io::{ioctl_fionbio, read, write}; +//! use rustix::net::{ +//!     accept, bind_v4, listen, socket, AddressFamily, Ipv4Addr, SocketAddrV4, SocketType, +//! }; +//! use std::collections::HashMap; +//! use std::os::unix::io::AsRawFd; +//! +//! // Create a socket and listen on it. +//! let listen_sock = socket(AddressFamily::INET, SocketType::STREAM, None)?; +//! bind_v4(&listen_sock, &SocketAddrV4::new(Ipv4Addr::LOCALHOST, 0))?; +//! listen(&listen_sock, 1)?; +//! +//! // Create an epoll object. Using `Owning` here means the epoll object will +//! // take ownership of the file descriptors registered with it. +//! let epoll = epoll::create(epoll::CreateFlags::CLOEXEC)?; +//! +//! // Register the socket with the epoll object. +//! epoll::add( +//!     &epoll, +//!     &listen_sock, +//!     epoll::EventData::new_u64(1), +//!     epoll::EventFlags::IN, +//! )?; +//! +//! // Keep track of the sockets we've opened. +//! let mut next_id = epoll::EventData::new_u64(2); +//! let mut sockets = HashMap::new(); +//! +//! // Process events. +//! let mut event_list = epoll::EventVec::with_capacity(4); +//! loop { +//!     epoll::wait(&epoll, &mut event_list, -1)?; +//!     for event in &event_list { +//!         let target = event.data; +//!         if target.u64() == 1 { +//!             // Accept a new connection, set it to non-blocking, and +//!             // register to be notified when it's ready to write to. +//!             let conn_sock = accept(&listen_sock)?; +//!             ioctl_fionbio(&conn_sock, true)?; +//!             epoll::add( +//!                 &epoll, +//!                 &conn_sock, +//!                 next_id, +//!                 epoll::EventFlags::OUT | epoll::EventFlags::ET, +//!             )?; +//! +//!             // Keep track of the socket. +//!             sockets.insert(next_id, conn_sock); +//!             next_id = epoll::EventData::new_u64(next_id.u64() + 1); +//!         } else { +//!             // Write a message to the stream and then unregister it. +//!             let target = sockets.remove(&target).unwrap(); +//!             write(&target, b"hello\n")?; +//!             let _ = epoll::delete(&epoll, &target)?; +//!         } +//!     } +//! } +//! # } +//! # #[cfg(not(feature = "net"))] +//! # fn main() {} +//! ``` + +use crate::backend::c; +#[cfg(feature = "alloc")] +use crate::backend::conv::ret_u32; +use crate::backend::conv::{ret, ret_owned_fd}; +use crate::fd::{AsFd, AsRawFd, OwnedFd}; +use crate::io; +use crate::utils::as_mut_ptr; +#[cfg(feature = "alloc")] +use alloc::vec::Vec; +use bitflags::bitflags; +use core::ffi::c_void; +use core::hash::{Hash, Hasher}; +use core::ptr::null_mut; +use core::slice; + +bitflags! { +    /// `EPOLL_*` for use with [`new`]. +    #[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 [`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` +        #[cfg(not(target_os = "android"))] +        const EXCLUSIVE = bitcast!(c::EPOLLEXCLUSIVE); + +        /// <https://docs.rs/bitflags/*/bitflags/#externally-defined-flags> +        const _ = !0; +    } +} + +/// `epoll_create1(flags)`—Creates a new epoll object. +/// +/// Use the [`CreateFlags::CLOEXEC`] flag to prevent the resulting file +/// descriptor from being implicitly passed across `exec` boundaries. +#[inline] +#[doc(alias = "epoll_create1")] +pub fn create(flags: CreateFlags) -> io::Result<OwnedFd> { +    // SAFETY: We're calling `epoll_create1` via FFI and we know how it +    // behaves. +    unsafe { ret_owned_fd(c::epoll_create1(bitflags_bits!(flags))) } +} + +/// `epoll_ctl(self, EPOLL_CTL_ADD, data, event)`—Adds an element to an epoll +/// object. +/// +/// This registers interest in any of the events set in `events` occurring on +/// the file descriptor associated with `data`. +/// +/// If [`delete`] is not called on the I/O source passed into this function +/// before the I/O source is `close`d, then the `epoll` will act as if the I/O +/// source is still registered with it. This can lead to spurious events being +/// returned from [`wait`]. If a file descriptor is an +/// `Arc<dyn SystemResource>`, then `epoll` can be thought to maintain a +/// `Weak<dyn SystemResource>` to the file descriptor. +#[doc(alias = "epoll_ctl")] +pub fn add( +    epoll: impl AsFd, +    source: impl AsFd, +    data: EventData, +    event_flags: EventFlags, +) -> io::Result<()> { +    // SAFETY: We're calling `epoll_ctl` via FFI and we know how it +    // behaves. 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 elsehwere for layout equivalence. +    unsafe { +        let raw_fd = source.as_fd().as_raw_fd(); +        ret(c::epoll_ctl( +            epoll.as_fd().as_raw_fd(), +            c::EPOLL_CTL_ADD, +            raw_fd, +            as_mut_ptr(&mut Event { +                flags: event_flags, +                data, +            }) +            .cast(), +        )) +    } +} + +/// `epoll_ctl(self, EPOLL_CTL_MOD, target, event)`—Modifies an element in a +/// given epoll object. +/// +/// This sets the events of interest with `target` to `events`. +#[doc(alias = "epoll_ctl")] +pub fn modify( +    epoll: impl AsFd, +    source: impl AsFd, +    data: EventData, +    event_flags: EventFlags, +) -> io::Result<()> { +    let raw_fd = source.as_fd().as_raw_fd(); + +    // SAFETY: We're calling `epoll_ctl` via FFI and we know how it +    // behaves. 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 elsehwere for layout equivalence. +    unsafe { +        ret(c::epoll_ctl( +            epoll.as_fd().as_raw_fd(), +            c::EPOLL_CTL_MOD, +            raw_fd, +            as_mut_ptr(&mut Event { +                flags: event_flags, +                data, +            }) +            .cast(), +        )) +    } +} + +/// `epoll_ctl(self, EPOLL_CTL_DEL, target, NULL)`—Removes an element in a +/// given epoll object. +#[doc(alias = "epoll_ctl")] +pub fn delete(epoll: impl AsFd, source: impl AsFd) -> io::Result<()> { +    // SAFETY: We're calling `epoll_ctl` via FFI and we know how it +    // behaves. +    unsafe { +        let raw_fd = source.as_fd().as_raw_fd(); +        ret(c::epoll_ctl( +            epoll.as_fd().as_raw_fd(), +            c::EPOLL_CTL_DEL, +            raw_fd, +            null_mut(), +        )) +    } +} + +/// `epoll_wait(self, events, timeout)`—Waits for registered events of +/// interest. +/// +/// For each event of interest, an element is written to `events`. On +/// success, this returns the number of written elements. +#[cfg(feature = "alloc")] +#[cfg_attr(doc_cfg, doc(cfg(feature = "alloc")))] +pub fn wait(epoll: impl AsFd, event_list: &mut EventVec, timeout: c::c_int) -> io::Result<()> { +    // SAFETY: We're calling `epoll_wait` via FFI and we know how it +    // behaves. +    unsafe { +        event_list.events.set_len(0); +        let nfds = ret_u32(c::epoll_wait( +            epoll.as_fd().as_raw_fd(), +            event_list.events.as_mut_ptr().cast::<c::epoll_event>(), +            event_list.events.capacity().try_into().unwrap_or(i32::MAX), +            timeout, +        ))?; +        event_list.events.set_len(nfds as usize); +    } + +    Ok(()) +} + +/// An iterator over the `Event`s in an `EventVec`. +pub struct Iter<'a> { +    /// Use `Copied` to copy the struct, since `Event` is `packed` on some +    /// platforms, and it's common for users to directly destructure it, which +    /// would lead to errors about forming references to packed fields. +    iter: core::iter::Copied<slice::Iter<'a, Event>>, +} + +impl<'a> Iterator for Iter<'a> { +    type Item = Event; + +    #[inline] +    fn next(&mut self) -> Option<Self::Item> { +        self.iter.next() +    } +} + +/// A record of an event that occurred. +#[repr(C)] +#[cfg_attr( +    any( +        all( +            target_arch = "x86", +            not(target_env = "musl"), +            not(target_os = "android"), +        ), +        target_arch = "x86_64", +    ), +    repr(packed) +)] +#[derive(Copy, Clone, Eq, PartialEq, Hash)] +pub struct Event { +    /// Which specific event(s) occurred. +    pub flags: EventFlags, +    /// User data. +    pub data: EventData, +} + +/// Data associated with an [`Event`]. This can either be a 64-bit integer +/// value or a pointer which preserves pointer provenance. +#[repr(C)] +#[derive(Copy, Clone)] +pub union EventData { +    /// A 64-bit integer value. +    as_u64: u64, + +    /// A `*mut c_void` which preserves pointer provenance, extended to be +    /// 64-bit so that if we read the value as a `u64` union field, we don't +    /// get uninitialized memory. +    sixty_four_bit_pointer: SixtyFourBitPointer, +} + +impl EventData { +    /// Construct a new value containing a `u64`. +    #[inline] +    pub const fn new_u64(value: u64) -> Self { +        Self { as_u64: value } +    } + +    /// Construct a new value containing a `*mut c_void`. +    #[inline] +    pub const fn new_ptr(value: *mut c_void) -> Self { +        Self { +            sixty_four_bit_pointer: SixtyFourBitPointer { +                pointer: value, +                #[cfg(target_pointer_width = "32")] +                _padding: 0, +            }, +        } +    } + +    /// Return the value as a `u64`. +    /// +    /// If the stored value was a pointer, the pointer is zero-extended to a +    /// `u64`. +    #[inline] +    pub fn u64(self) -> u64 { +        unsafe { self.as_u64 } +    } + +    /// Return the value as a `*mut c_void`. +    /// +    /// If the stored value was a `u64`, the least-significant bits of the +    /// `u64` are returned as a pointer value. +    #[inline] +    pub fn ptr(self) -> *mut c_void { +        unsafe { self.sixty_four_bit_pointer.pointer } +    } +} + +impl PartialEq for EventData { +    #[inline] +    fn eq(&self, other: &Self) -> bool { +        self.u64() == other.u64() +    } +} + +impl Eq for EventData {} + +impl Hash for EventData { +    #[inline] +    fn hash<H: Hasher>(&self, state: &mut H) { +        self.u64().hash(state) +    } +} + +#[repr(C)] +#[derive(Copy, Clone)] +struct SixtyFourBitPointer { +    #[cfg(target_endian = "big")] +    #[cfg(target_pointer_width = "32")] +    _padding: u32, + +    pointer: *mut c_void, + +    #[cfg(target_endian = "little")] +    #[cfg(target_pointer_width = "32")] +    _padding: u32, +} + +/// A vector of `Event`s, plus context for interpreting them. +#[cfg(feature = "alloc")] +pub struct EventVec { +    events: Vec<Event>, +} + +#[cfg(feature = "alloc")] +impl EventVec { +    /// Constructs an `EventVec` from raw pointer, length, and capacity. +    /// +    /// # Safety +    /// +    /// This function calls [`Vec::from_raw_parts`] with its arguments. +    /// +    /// [`Vec::from_raw_parts`]: https://doc.rust-lang.org/stable/std/vec/struct.Vec.html#method.from_raw_parts +    #[inline] +    pub unsafe fn from_raw_parts(ptr: *mut Event, len: usize, capacity: usize) -> Self { +        Self { +            events: Vec::from_raw_parts(ptr, len, capacity), +        } +    } + +    /// Constructs an `EventVec` with memory for `capacity` `Event`s. +    #[inline] +    pub fn with_capacity(capacity: usize) -> Self { +        Self { +            events: Vec::with_capacity(capacity), +        } +    } + +    /// Returns the current `Event` capacity of this `EventVec`. +    #[inline] +    pub fn capacity(&self) -> usize { +        self.events.capacity() +    } + +    /// Reserves enough memory for at least `additional` more `Event`s. +    #[inline] +    pub fn reserve(&mut self, additional: usize) { +        self.events.reserve(additional); +    } + +    /// Reserves enough memory for exactly `additional` more `Event`s. +    #[inline] +    pub fn reserve_exact(&mut self, additional: usize) { +        self.events.reserve_exact(additional); +    } + +    /// Clears all the `Events` out of this `EventVec`. +    #[inline] +    pub fn clear(&mut self) { +        self.events.clear(); +    } + +    /// Shrinks the capacity of this `EventVec` as much as possible. +    #[inline] +    pub fn shrink_to_fit(&mut self) { +        self.events.shrink_to_fit(); +    } + +    /// Returns an iterator over the `Event`s in this `EventVec`. +    #[inline] +    pub fn iter(&self) -> Iter<'_> { +        Iter { +            iter: self.events.iter().copied(), +        } +    } + +    /// Returns the number of `Event`s logically contained in this `EventVec`. +    #[inline] +    pub fn len(&mut self) -> usize { +        self.events.len() +    } + +    /// Tests whether this `EventVec` is logically empty. +    #[inline] +    pub fn is_empty(&mut self) -> bool { +        self.events.is_empty() +    } +} + +#[cfg(feature = "alloc")] +impl<'a> IntoIterator for &'a EventVec { +    type IntoIter = Iter<'a>; +    type Item = Event; + +    #[inline] +    fn into_iter(self) -> Self::IntoIter { +        self.iter() +    } +} + +#[test] +fn test_epoll_layouts() { +    check_renamed_type!(Event, epoll_event); +    check_renamed_type!(Event, epoll_event); +    check_renamed_struct_renamed_field!(Event, epoll_event, flags, events); +    check_renamed_struct_renamed_field!(Event, epoll_event, data, u64); +} 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 0000000..6aed461 --- /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(linux_kernel)] +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 0000000..32fd83d --- /dev/null +++ b/vendor/rustix/src/backend/libc/event/poll_fd.rs @@ -0,0 +1,142 @@ +use crate::backend::c; +use crate::backend::conv::borrowed_fd; +use crate::backend::fd::{AsFd, AsRawFd, BorrowedFd, LibcFd}; +use bitflags::bitflags; +use core::marker::PhantomData; +#[cfg(windows)] +use { +    crate::backend::fd::{AsSocket, RawFd}, +    core::fmt, +}; + +bitflags! { +    /// `POLL*` flags for use with [`poll`]. +    /// +    /// [`poll`]: crate::event::poll +    #[repr(transparent)] +    #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] +    pub struct PollFlags: c::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(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)] +#[cfg_attr(not(windows), derive(Debug))] +#[repr(transparent)] +pub struct PollFd<'fd> { +    pollfd: c::pollfd, +    _phantom: PhantomData<BorrowedFd<'fd>>, +} + +#[cfg(windows)] +impl<'fd> fmt::Debug for PollFd<'fd> { +    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { +        fmt.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 0000000..725ec82 --- /dev/null +++ b/vendor/rustix/src/backend/libc/event/syscalls.rs @@ -0,0 +1,191 @@ +//! libc syscalls supporting `rustix::event`. + +use crate::backend::c; +use crate::backend::conv::ret_c_int; +#[cfg(any(apple, netbsdlike, target_os = "dragonfly", target_os = "solaris"))] +use crate::backend::conv::ret_owned_fd; +use crate::event::PollFd; +#[cfg(any(linux_kernel, bsd, solarish, target_os = "espidf"))] +use crate::fd::OwnedFd; +use crate::io; +#[cfg(any(bsd, solarish))] +use {crate::backend::conv::borrowed_fd, crate::fd::BorrowedFd, core::mem::MaybeUninit}; +#[cfg(solarish)] +use { +    crate::backend::conv::ret, crate::event::port::Event, crate::utils::as_mut_ptr, +    core::ptr::null_mut, +}; +#[cfg(any( +    linux_kernel, +    target_os = "freebsd", +    target_os = "illumos", +    target_os = "espidf" +))] +use {crate::backend::conv::ret_owned_fd, crate::event::EventfdFlags}; +#[cfg(all(feature = "alloc", bsd))] +use {crate::event::kqueue::Event, crate::utils::as_ptr, core::ptr::null}; + +#[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(all(feature = "alloc", bsd))] +pub(crate) fn kqueue() -> io::Result<OwnedFd> { +    unsafe { ret_owned_fd(c::kqueue()) } +} + +#[cfg(all(feature = "alloc", bsd))] +pub(crate) unsafe fn kevent( +    kq: BorrowedFd<'_>, +    changelist: &[Event], +    eventlist: &mut [MaybeUninit<Event>], +    timeout: Option<&c::timespec>, +) -> io::Result<c::c_int> { +    ret_c_int(c::kevent( +        borrowed_fd(kq), +        changelist.as_ptr().cast(), +        changelist +            .len() +            .try_into() +            .map_err(|_| io::Errno::OVERFLOW)?, +        eventlist.as_mut_ptr().cast(), +        eventlist +            .len() +            .try_into() +            .map_err(|_| io::Errno::OVERFLOW)?, +        timeout.map_or(null(), as_ptr), +    )) +} + +#[inline] +pub(crate) fn poll(fds: &mut [PollFd<'_>], timeout: c::c_int) -> io::Result<usize> { +    let nfds = fds +        .len() +        .try_into() +        .map_err(|_convert_err| io::Errno::INVAL)?; + +    ret_c_int(unsafe { c::poll(fds.as_mut_ptr().cast(), nfds, timeout) }) +        .map(|nready| nready as usize) +} + +#[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<&mut c::timespec>, +) -> io::Result<Event> { +    let mut event = MaybeUninit::<c::port_event>::uninit(); +    let timeout = timeout.map_or(null_mut(), as_mut_ptr); + +    unsafe { +        ret(c::port_get(borrowed_fd(port), event.as_mut_ptr(), timeout))?; +    } + +    // If we're done, initialize the event and return it. +    Ok(Event(unsafe { event.assume_init() })) +} + +#[cfg(all(feature = "alloc", solarish))] +pub(crate) fn port_getn( +    port: BorrowedFd<'_>, +    timeout: Option<&mut c::timespec>, +    events: &mut Vec<Event>, +    mut nget: u32, +) -> io::Result<()> { +    let timeout = timeout.map_or(null_mut(), as_mut_ptr); +    unsafe { +        ret(c::port_getn( +            borrowed_fd(port), +            events.as_mut_ptr().cast(), +            events.len().try_into().unwrap(), +            &mut nget, +            timeout, +        ))?; +    } + +    // Update the vector length. +    unsafe { +        events.set_len(nget.try_into().unwrap()); +    } + +    Ok(()) +} + +#[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(windows, target_os = "redox", target_os = "wasi")))] +pub(crate) fn pause() { +    let r = unsafe { libc::pause() }; +    let errno = libc_errno::errno().0; +    debug_assert_eq!(r, -1); +    debug_assert_eq!(errno, libc::EINTR); +} 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 0000000..a04d7e6 --- /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 0000000..8ccad47 --- /dev/null +++ b/vendor/rustix/src/backend/libc/event/windows_syscalls.rs @@ -0,0 +1,16 @@ +//! Windows system calls in the `event` module. + +use crate::backend::c; +use crate::backend::conv::ret_c_int; +use crate::event::PollFd; +use crate::io; + +pub(crate) fn poll(fds: &mut [PollFd<'_>], timeout: c::c_int) -> io::Result<usize> { +    let nfds = fds +        .len() +        .try_into() +        .map_err(|_convert_err| io::Errno::INVAL)?; + +    ret_c_int(unsafe { c::poll(fds.as_mut_ptr().cast(), nfds, timeout) }) +        .map(|nready| nready as usize) +}  | 
