From 10f85a8a0bfcc19dad534a3a257d4a86de84c78b Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Mon, 18 Nov 2024 10:30:13 -0800 Subject: [PATCH] Add a `port_getn_query` function. (#1216) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Add a `port_getn_query` function. The solarish [`port_getn` function] special-cases a `max` argument value of 0 to be a query of the number of events available. #1215 added a special-case to protect the code from doing a resize in that case. And in case users actually do want to do a query, this PR adds a new `port_getn_query` function that passes a zero. [`port_getn` function]: https://illumos.org/man/3C/port_getn * Fix errors. * Update src/event/port.rs Co-authored-by: 王宇逸 --------- Co-authored-by: 王宇逸 --- src/backend/libc/event/syscalls.rs | 22 ++++++++++++++++++++++ src/event/port.rs | 22 ++++++++++++++++++++++ 2 files changed, 44 insertions(+) diff --git a/src/backend/libc/event/syscalls.rs b/src/backend/libc/event/syscalls.rs index def689ebd..5beaed161 100644 --- a/src/backend/libc/event/syscalls.rs +++ b/src/backend/libc/event/syscalls.rs @@ -314,9 +314,13 @@ pub(crate) fn port_getn( events: &mut Vec, mut nget: u32, ) -> io::Result<()> { + // `port_getn` special-cases a max value of 0 to be a query that returns + // the number of events. We don't want to do the `set_len` in that case, so + // so bail out early if needed. if events.capacity() == 0 { return Ok(()); } + let timeout = timeout.map_or(null_mut(), as_mut_ptr); unsafe { ret(c::port_getn( @@ -336,6 +340,24 @@ pub(crate) fn port_getn( Ok(()) } +#[cfg(solarish)] +pub(crate) fn port_getn_query(port: BorrowedFd<'_>) -> io::Result { + 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<'_>, diff --git a/src/event/port.rs b/src/event/port.rs index 39fe5ac16..094618317 100644 --- a/src/event/port.rs +++ b/src/event/port.rs @@ -110,6 +110,13 @@ pub fn port_get(port: impl AsFd, timeout: Option) -> io::Result /// `port_getn(port, events, min_events, timeout)`—Gets multiple events from a /// port. /// +/// This requests up to a max of `events.capacity()` events, and then resizes +/// `events` to the number of events retrieved. If `events.capacity()` is 0, +/// this does nothing and returns immediately. +/// +/// To query the number of events without retrieving any, use +/// [`port_getn_query`]. +/// /// # References /// - [OpenSolaris] /// - [illumos] @@ -138,6 +145,21 @@ pub fn port_getn( ) } +/// `port_getn(port, NULL, 0, NULL)`—Queries the number of events +/// available from a port. +/// +/// To retrieve the events, use [`port_getn`]. +/// +/// # References +/// - [OpenSolaris] +/// - [illumos] +/// +/// [OpenSolaris]: https://www.unix.com/man-page/opensolaris/3C/port_getn/ +/// [illumos]: https://illumos.org/man/3C/port_getn +pub fn port_getn_query(port: impl AsFd) -> io::Result { + syscalls::port_getn_query(port.as_fd()) +} + /// `port_send(port, events, userdata)`—Sends an event to a port. /// /// # References