diff options
Diffstat (limited to 'vendor/rustix/src/backend/libc/event/epoll.rs')
-rw-r--r-- | vendor/rustix/src/backend/libc/event/epoll.rs | 496 |
1 files changed, 0 insertions, 496 deletions
diff --git a/vendor/rustix/src/backend/libc/event/epoll.rs b/vendor/rustix/src/backend/libc/event/epoll.rs deleted file mode 100644 index ced3be1..0000000 --- a/vendor/rustix/src/backend/libc/event/epoll.rs +++ /dev/null @@ -1,496 +0,0 @@ -//! 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); -} |