Skip to content

Instantly share code, notes, and snippets.

@sunshowers
Created August 7, 2024 05:13
Show Gist options
  • Save sunshowers/c573ae448d2c1eb028216c3f3d644719 to your computer and use it in GitHub Desktop.
Save sunshowers/c573ae448d2c1eb028216c3f3d644719 to your computer and use it in GitHub Desktop.
diff --git a/src/sys/unix/mod.rs b/src/sys/unix/mod.rs
index cfbd525d28...47ef234cca 100644
--- a/src/sys/unix/mod.rs
+++ b/src/sys/unix/mod.rs
@@ -54,6 +54,18 @@
#[cfg_attr(all(
not(mio_unsupported_force_waker_pipe),
any(
+ target_os = "android",
+ target_os = "espidf",
+ target_os = "fuchsia",
+ target_os = "hermit",
+ target_os = "illumos",
+ target_os = "linux",
+ )
+ ), path = "waker/eventfd.rs")]
+ #[cfg_attr(all(
+ not(mio_unsupported_force_waker_pipe),
+ not(mio_unsupported_force_poll_poll), // `kqueue(2)` based waker doesn't work with `poll(2)`.
+ any(
target_os = "freebsd",
target_os = "ios",
target_os = "macos",
@@ -62,8 +74,34 @@
target_os = "watchos",
)
), path = "waker/kqueue.rs")]
+ #[cfg_attr(any(
+ // NOTE: also add to the list list for the `pipe` module below.
+ mio_unsupported_force_waker_pipe,
+ all(
+ // `kqueue(2)` based waker doesn't work with `poll(2)`.
+ mio_unsupported_force_poll_poll,
+ any(
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "tvos",
+ target_os = "visionos",
+ target_os = "watchos",
+ ),
+ ),
+ target_os = "aix",
+ target_os = "dragonfly",
+ target_os = "haiku",
+ target_os = "netbsd",
+ target_os = "nto",
+ target_os = "openbsd",
+ target_os = "redox",
+ target_os = "solaris",
+ target_os = "vita",
+ ), path = "waker/pipe.rs")]
mod waker;
- pub(crate) use self::waker::Waker;
+ // NOTE: the `Waker` type is expected in the selector module as the
+ // `poll(2)` implementation needs to do some special stuff.
mod sourcefd;
#[cfg(feature = "os-ext")]
@@ -83,10 +121,22 @@
all(feature = "os-ext", not(target_os = "hermit")),
// For the `Waker` type based on a pipe.
mio_unsupported_force_waker_pipe,
+ all(
+ // `kqueue(2)` based waker doesn't work with `poll(2)`.
+ mio_unsupported_force_poll_poll,
+ any(
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "tvos",
+ target_os = "visionos",
+ target_os = "watchos",
+ ),
+ ),
+ // NOTE: also add to the list list for the `pipe` module below.
target_os = "aix",
target_os = "dragonfly",
target_os = "haiku",
- target_os = "illumos",
target_os = "netbsd",
target_os = "nto",
target_os = "openbsd",
diff --git a/src/sys/unix/selector/epoll.rs b/src/sys/unix/selector/epoll.rs
index 0487dc2e87...082a65871a 100644
--- a/src/sys/unix/selector/epoll.rs
+++ b/src/sys/unix/selector/epoll.rs
@@ -222,7 +222,10 @@
}
}
+// No special requirement from the implementation around waking.
+pub(crate) use crate::sys::unix::waker::Waker;
+
cfg_io_source! {
mod stateless_io_source;
pub(crate) use stateless_io_source::IoSourceState;
}
diff --git a/src/sys/unix/selector/kqueue.rs b/src/sys/unix/selector/kqueue.rs
index d30b06e831...f31db35fb0 100644
--- a/src/sys/unix/selector/kqueue.rs
+++ b/src/sys/unix/selector/kqueue.rs
@@ -868,6 +868,9 @@
}
}
+// No special requirement from the implementation around waking.
+pub(crate) use crate::sys::unix::waker::Waker;
+
cfg_io_source! {
mod stateless_io_source;
pub(crate) use stateless_io_source::IoSourceState;
diff --git a/src/sys/unix/selector/poll.rs b/src/sys/unix/selector/poll.rs
index ee4f50a7e3...ac282c6275 100644
--- a/src/sys/unix/selector/poll.rs
+++ b/src/sys/unix/selector/poll.rs
@@ -16,7 +16,7 @@
use std::time::Duration;
use std::{cmp, fmt, io};
-use crate::sys::unix::waker::WakerInternal;
+use crate::sys::unix::waker::Waker as WakerInternal;
use crate::{Interest, Token};
/// Unique id for use as `SelectorId`.
@@ -161,7 +161,7 @@
impl SelectorState {
pub fn new() -> io::Result<SelectorState> {
- let notify_waker = WakerInternal::new()?;
+ let notify_waker = WakerInternal::new_unregistered()?;
Ok(Self {
fds: Mutex::new(Fds {
@@ -625,6 +625,25 @@
}
}
+#[derive(Debug)]
+pub(crate) struct Waker {
+ selector: Selector,
+ token: Token,
+}
+
+impl Waker {
+ pub(crate) fn new(selector: &Selector, token: Token) -> io::Result<Waker> {
+ Ok(Waker {
+ selector: selector.try_clone()?,
+ token,
+ })
+ }
+
+ pub(crate) fn wake(&self) -> io::Result<()> {
+ self.selector.wake(self.token)
+ }
+}
+
cfg_io_source! {
use crate::Registry;
diff --git a/src/sys/unix/waker/eventfd.rs b/src/sys/unix/waker/eventfd.rs
index 2b53d1c56a...c0086fce9c 100644
--- a/src/sys/unix/waker/eventfd.rs
+++ b/src/sys/unix/waker/eventfd.rs
@@ -7,6 +7,9 @@
#[cfg(target_os = "hermit")]
use std::os::hermit::io::{AsRawFd, FromRawFd, RawFd};
+use crate::sys::Selector;
+use crate::{Interest, Token};
+
/// Waker backed by `eventfd`.
///
/// `eventfd` is effectively an 64 bit counter. All writes must be of 8
@@ -19,14 +22,20 @@
}
impl Waker {
- pub(crate) fn new() -> io::Result<Waker> {
+ #[allow(dead_code)] // Not used by the `poll(2)` implementation.
+ pub(crate) fn new(selector: &Selector, token: Token) -> io::Result<Waker> {
+ let waker = Waker::new_unregistered()?;
+ selector.register(waker.fd.as_raw_fd(), token, Interest::READABLE)?;
+ Ok(waker)
+ }
+
+ pub(crate) fn new_unregistered() -> io::Result<Waker> {
#[cfg(not(target_os = "espidf"))]
let flags = libc::EFD_CLOEXEC | libc::EFD_NONBLOCK;
// ESP-IDF is EFD_NONBLOCK by default and errors if you try to pass this flag.
#[cfg(target_os = "espidf")]
let flags = 0;
let fd = syscall!(eventfd(0, flags))?;
-
let file = unsafe { File::from_raw_fd(fd) };
Ok(Waker { fd: file })
}
@@ -46,12 +55,7 @@
}
}
- #[cfg(any(
- mio_unsupported_force_poll_poll,
- target_os = "espidf",
- target_os = "fuchsia",
- target_os = "hermit",
- ))]
+ #[allow(dead_code)] // Only used by the `poll(2)` implementation.
pub(crate) fn ack_and_reset(&self) {
let _ = self.reset();
}
diff --git a/src/sys/unix/waker/pipe.rs b/src/sys/unix/waker/pipe.rs
index ab001849a6...a0a3acff68 100644
--- a/src/sys/unix/waker/pipe.rs
+++ b/src/sys/unix/waker/pipe.rs
@@ -8,6 +8,8 @@
use std::os::hermit::io::{AsRawFd, FromRawFd, RawFd};
use crate::sys::unix::pipe;
+use crate::sys::Selector;
+use crate::{Interest, Token};
/// Waker backed by a unix pipe.
///
@@ -20,7 +22,14 @@
}
impl Waker {
- pub(crate) fn new() -> io::Result<Waker> {
+ #[allow(dead_code)] // Not used by the `poll(2)` implementation.
+ pub(crate) fn new(selector: &Selector, token: Token) -> io::Result<Waker> {
+ let waker = Waker::new_unregistered()?;
+ selector.register(waker.receiver.as_raw_fd(), token, Interest::READABLE)?;
+ Ok(waker)
+ }
+
+ pub(crate) fn new_unregistered() -> io::Result<Waker> {
let [receiver, sender] = pipe::new_raw()?;
let sender = unsafe { File::from_raw_fd(sender) };
let receiver = unsafe { File::from_raw_fd(receiver) };
@@ -47,14 +56,7 @@
}
}
- #[cfg(any(
- mio_unsupported_force_poll_poll,
- target_os = "espidf",
- target_os = "haiku",
- target_os = "nto",
- target_os = "solaris",
- target_os = "vita",
- ))]
+ #[allow(dead_code)] // Only used by the `poll(2)` implementation.
pub(crate) fn ack_and_reset(&self) {
self.empty();
}
diff --git a/src/sys/unix/waker.rs b/src/sys/unix/waker.rs
deleted file mode 100644
index f97b1ebafe..0000000000
--- a/src/sys/unix/waker.rs
+++ /dev/null
@@ -1,188 +1,0 @@
-#[cfg(all(
- not(mio_unsupported_force_poll_poll),
- not(all(
- not(mio_unsupported_force_waker_pipe),
- any(
- target_os = "freebsd",
- target_os = "ios",
- target_os = "macos",
- target_os = "tvos",
- target_os = "visionos",
- target_os = "watchos",
- )
- )),
- not(any(
- target_os = "espidf",
- target_os = "haiku",
- target_os = "hermit",
- target_os = "nto",
- target_os = "solaris",
- target_os = "vita"
- )),
-))]
-mod fdbased {
- use std::io;
- use std::os::fd::AsRawFd;
-
- #[cfg(all(
- not(mio_unsupported_force_waker_pipe),
- any(target_os = "android", target_os = "fuchsia", target_os = "linux"),
- ))]
- use crate::sys::unix::waker::eventfd::Waker as WakerInternal;
- #[cfg(any(
- mio_unsupported_force_waker_pipe,
- target_os = "aix",
- target_os = "dragonfly",
- target_os = "illumos",
- target_os = "netbsd",
- target_os = "openbsd",
- target_os = "redox",
- ))]
- use crate::sys::unix::waker::pipe::Waker as WakerInternal;
- use crate::sys::Selector;
- use crate::{Interest, Token};
-
- #[derive(Debug)]
- pub(crate) struct Waker {
- waker: WakerInternal,
- }
-
- impl Waker {
- pub(crate) fn new(selector: &Selector, token: Token) -> io::Result<Waker> {
- let waker = WakerInternal::new()?;
- selector.register(waker.as_raw_fd(), token, Interest::READABLE)?;
- Ok(Waker { waker })
- }
-
- pub(crate) fn wake(&self) -> io::Result<()> {
- self.waker.wake()
- }
- }
-}
-
-#[cfg(all(
- not(mio_unsupported_force_poll_poll),
- not(all(
- not(mio_unsupported_force_waker_pipe),
- any(
- target_os = "freebsd",
- target_os = "ios",
- target_os = "macos",
- target_os = "tvos",
- target_os = "visionos",
- target_os = "watchos",
- )
- )),
- not(any(
- target_os = "espidf",
- target_os = "haiku",
- target_os = "hermit",
- target_os = "nto",
- target_os = "solaris",
- target_os = "vita"
- )),
-))]
-pub(crate) use self::fdbased::Waker;
-
-#[cfg(all(
- not(mio_unsupported_force_waker_pipe),
- any(
- target_os = "android",
- target_os = "espidf",
- target_os = "fuchsia",
- target_os = "hermit",
- target_os = "linux",
- )
-))]
-mod eventfd;
-
-#[cfg(all(
- not(mio_unsupported_force_waker_pipe),
- any(
- mio_unsupported_force_poll_poll,
- target_os = "espidf",
- target_os = "fuchsia",
- target_os = "hermit",
- )
-))]
-pub(crate) use self::eventfd::Waker as WakerInternal;
-
-#[cfg(any(
- mio_unsupported_force_waker_pipe,
- target_os = "aix",
- target_os = "dragonfly",
- target_os = "haiku",
- target_os = "illumos",
- target_os = "netbsd",
- target_os = "nto",
- target_os = "openbsd",
- target_os = "redox",
- target_os = "solaris",
- target_os = "vita",
-))]
-mod pipe;
-
-#[cfg(any(
- all(
- mio_unsupported_force_poll_poll,
- any(
- mio_unsupported_force_waker_pipe,
- target_os = "aix",
- target_os = "dragonfly",
- target_os = "illumos",
- target_os = "netbsd",
- target_os = "openbsd",
- target_os = "redox",
- )
- ),
- target_os = "haiku",
- target_os = "nto",
- target_os = "solaris",
- target_os = "vita",
-))]
-pub(crate) use self::pipe::Waker as WakerInternal;
-
-#[cfg(any(
- mio_unsupported_force_poll_poll,
- target_os = "espidf",
- target_os = "haiku",
- target_os = "hermit",
- target_os = "nto",
- target_os = "solaris",
- target_os = "vita",
-))]
-mod poll {
- use crate::sys::Selector;
- use crate::Token;
- use std::io;
-
- #[derive(Debug)]
- pub(crate) struct Waker {
- selector: Selector,
- token: Token,
- }
-
- impl Waker {
- pub(crate) fn new(selector: &Selector, token: Token) -> io::Result<Waker> {
- Ok(Waker {
- selector: selector.try_clone()?,
- token,
- })
- }
-
- pub(crate) fn wake(&self) -> io::Result<()> {
- self.selector.wake(self.token)
- }
- }
-}
-
-#[cfg(any(
- mio_unsupported_force_poll_poll,
- target_os = "espidf",
- target_os = "haiku",
- target_os = "hermit",
- target_os = "nto",
- target_os = "solaris",
- target_os = "vita",
-))]
-pub(crate) use self::poll::Waker;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment