diff --git a/src/sys/eventfd.rs b/src/sys/eventfd.rs index 0199b18125..50abc22546 100644 --- a/src/sys/eventfd.rs +++ b/src/sys/eventfd.rs @@ -3,9 +3,14 @@ use crate::{unistd, Result}; use std::os::unix::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, OwnedFd, RawFd}; libc_bitflags! { + /// Eventfd flags. pub struct EfdFlags: libc::c_int { + /// Set the close-on-exec (`FD_CLOEXEC`) flag on the new event file descriptor. EFD_CLOEXEC; // Since Linux 2.6.27/FreeBSD 13.0 + /// Set the `O_NONBLOCK` file status flag on the new event file description. EFD_NONBLOCK; // Since Linux 2.6.27/FreeBSD 13.0 + /// Provide semaphore-like semantics for reads from the new event file + /// descriptor. EFD_SEMAPHORE; // Since Linux 2.6.30/FreeBSD 13.0 } } @@ -14,20 +19,24 @@ libc_bitflags! { since = "0.28.0", note = "Use EventFd::from_value_and_flags() instead" )] +#[allow(missing_docs)] pub fn eventfd(initval: libc::c_uint, flags: EfdFlags) -> Result { let res = unsafe { libc::eventfd(initval, flags.bits()) }; Errno::result(res).map(|r| unsafe { OwnedFd::from_raw_fd(r) }) } +/// An eventfd file descriptor. #[derive(Debug)] #[repr(transparent)] pub struct EventFd(OwnedFd); + impl EventFd { /// [`EventFd::from_value_and_flags`] with `init_val = 0` and `flags = EfdFlags::empty()`. pub fn new() -> Result { Self::from_value_and_flags(0, EfdFlags::empty()) } + /// Constructs [`EventFd`] with the given `init_val` and `flags`. /// /// Wrapper around [`libc::eventfd`]. @@ -38,27 +47,33 @@ impl EventFd { let res = unsafe { libc::eventfd(init_val, flags.bits()) }; Errno::result(res).map(|r| Self(unsafe { OwnedFd::from_raw_fd(r) })) } + /// [`EventFd::from_value_and_flags`] with `init_val = 0` and given `flags`. pub fn from_flags(flags: EfdFlags) -> Result { Self::from_value_and_flags(0, flags) } + /// [`EventFd::from_value_and_flags`] with given `init_val` and `flags = EfdFlags::empty()`. pub fn from_value(init_val: u32) -> Result { Self::from_value_and_flags(init_val, EfdFlags::empty()) } + /// Arms `self`, a following call to `poll`, `select` or `epoll` will return immediately. /// /// [`EventFd::write`] with `1`. pub fn arm(&self) -> Result { self.write(1) } + /// Defuses `self`, a following call to `poll`, `select` or `epoll` will block. /// /// [`EventFd::write`] with `0`. pub fn defuse(&self) -> Result { self.write(0) } - /// Enqueues `value` triggers. + + /// Enqueues `value` triggers, i.e., adds the integer value supplied in `value` + /// to the counter. /// /// The next `value` calls to `poll`, `select` or `epoll` will return immediately. /// @@ -66,7 +81,24 @@ impl EventFd { pub fn write(&self, value: u64) -> Result { unistd::write(&self.0, &value.to_ne_bytes()) } - // Reads the value from the file descriptor. + + /// Reads the value from the file descriptor. + /// + /// * If [`EFD_SEMAPHORE`](EfdFlags::EFD_SEMAPHORE) was not specified and + /// the eventfd counter has a nonzero value, then this function returns + /// an `u64` containing that value, and the counter's value is reset to + /// zero. + /// + /// * If [`EFD_SEMAPHORE`](EfdFlags::EFD_SEMAPHORE) was specified and the + /// eventfd counter has a nonzero value, then this function returns an + /// `u64` containing the value 1, and the counter's value is decremented + /// by 1. + /// + /// * If the eventfd counter is zero at the time of this call, then the + /// call either blocks until the counter becomes nonzero (at which time, + /// this function proceeds as described above) or fails with the error + /// `EAGAIN` if the file descriptor has been made nonblocking with + /// [`EFD_NONBLOCK`](EfdFlags::EFD_NONBLOCK). pub fn read(&self) -> Result { let mut arr = [0; std::mem::size_of::()]; unistd::read(&self.0, &mut arr)?; diff --git a/src/sys/mod.rs b/src/sys/mod.rs index 93339d1935..8bcd9afd15 100644 --- a/src/sys/mod.rs +++ b/src/sys/mod.rs @@ -20,8 +20,8 @@ feature! { #[cfg(bsd)] pub mod event; + /// Event file descriptor. #[cfg(any(linux_android, target_os = "freebsd"))] - #[allow(missing_docs)] pub mod eventfd; }