diff options
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) +} |