Skip to content

Commit

Permalink
don't use event_fd to wake up the main thread
Browse files Browse the repository at this point in the history
We do not need this; instead, we can just poll for writes in the
wayland file descriptor. Then, we make sure to only try to dispatch
events if the revent was a POLLIN.
  • Loading branch information
LGFae committed Apr 27, 2024
1 parent cfd9cb8 commit d96705d
Show file tree
Hide file tree
Showing 3 changed files with 14 additions and 52 deletions.
1 change: 0 additions & 1 deletion daemon/src/animations/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,6 @@ impl Animator {

let timeout = duration.saturating_sub(now.elapsed());
spin_sleep::sleep(timeout);
crate::wake_poll();
now = std::time::Instant::now();
}
})
Expand Down
15 changes: 7 additions & 8 deletions daemon/src/animations/transitions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ impl Transition {
}
}

fn send_frame(&mut self, now: &mut Instant) {
fn updt_wallpapers(&mut self, now: &mut Instant) {
let fps = self.fps;
let mut i = 0;
while i < self.wallpapers.len() {
Expand All @@ -94,7 +94,6 @@ impl Transition {
}
let timeout = fps.saturating_sub(now.elapsed());
spin_sleep::sleep(timeout);
crate::wake_poll();
*now = Instant::now();
}

Expand Down Expand Up @@ -131,7 +130,7 @@ impl Transition {
wallpaper.draw();
}

self.send_frame(&mut now);
self.updt_wallpapers(&mut now);
}
}

Expand All @@ -149,7 +148,7 @@ impl Transition {
*old = (*old as f64 * (1.0 - step) + *new as f64 * step) as u8;
}
});
self.send_frame(&mut now);
self.updt_wallpapers(&mut now);
step = seq.now() as f64;
seq.advance_to(start.elapsed().as_secs_f64());
}
Expand Down Expand Up @@ -211,7 +210,7 @@ impl Transition {
change_byte(channels, step, old, new);
}
});
self.send_frame(&mut now);
self.updt_wallpapers(&mut now);

offset = seq.now() as f64;
seq.advance_to(start.elapsed().as_secs_f64());
Expand Down Expand Up @@ -263,7 +262,7 @@ impl Transition {
change_byte(channels, step, old, new);
}
});
self.send_frame(&mut now);
self.updt_wallpapers(&mut now);

offset = seq.now() as f64;
seq.advance_to(start.elapsed().as_secs_f64());
Expand Down Expand Up @@ -307,7 +306,7 @@ impl Transition {
change_byte(channels, step, old, new);
}
});
self.send_frame(&mut now);
self.updt_wallpapers(&mut now);

dist_center = seq.now();
seq.advance_to(start.elapsed().as_secs_f64());
Expand Down Expand Up @@ -349,7 +348,7 @@ impl Transition {
change_byte(channels, step, old, new);
}
});
self.send_frame(&mut now);
self.updt_wallpapers(&mut now);

dist_center = seq.now();
seq.advance_to(start.elapsed().as_secs_f64());
Expand Down
50 changes: 7 additions & 43 deletions daemon/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,7 @@ use wayland_protocols::wp::{
use std::{
fs,
num::NonZeroI32,
os::{
fd::OwnedFd,
unix::net::{UnixListener, UnixStream},
},
os::unix::net::{UnixListener, UnixStream},
path::PathBuf,
sync::{
atomic::{AtomicBool, Ordering},
Expand Down Expand Up @@ -74,7 +71,6 @@ fn should_daemon_exit() -> bool {
EXIT.load(Ordering::Acquire)
}

static POLL_WAKER: OnceLock<OwnedFd> = OnceLock::new();
static PIXEL_FORMAT: OnceLock<PixelFormat> = OnceLock::new();

#[inline]
Expand All @@ -93,22 +89,6 @@ pub fn pixel_format() -> PixelFormat {
*PIXEL_FORMAT.get().unwrap_or(&PixelFormat::Xrgb)
}

#[inline]
pub fn wake_poll() {
debug_assert!(POLL_WAKER.get().is_some());

// SAFETY: POLL_WAKER is set up in setup_signals_and_pipe, which is called early in main
// and panics if it fails. By the time anyone calls this function, POLL_WAKER will certainly
// already have been initialized.

if let Err(e) = rustix::io::write(
unsafe { POLL_WAKER.get().unwrap_unchecked() },
&1u64.to_ne_bytes(), // eventfd demands we write 8 bytes at once
) {
error!("failed to write to eventfd file descriptor: {e}");
}
}

extern "C" fn signal_handler(_s: libc::c_int) {
exit_daemon();
}
Expand All @@ -129,7 +109,7 @@ fn main() -> Result<(), String> {
.expect("failed to configure rayon global thread pool");

let listener = SocketWrapper::new()?;
let wake = setup_signals_and_eventfd();
setup_signals();

let conn = Connection::connect_to_env().expect("failed to connect to the wayland server");
// Enumerate the list of globals to get the protocols the server implements.
Expand Down Expand Up @@ -173,9 +153,8 @@ fn main() -> Result<(), String> {
let events = {
let connection_fd = read_guard.connection_fd();
let mut fds = [
PollFd::new(&connection_fd, PollFlags::IN | PollFlags::OUT),
PollFd::new(&listener.0, PollFlags::IN),
PollFd::new(&connection_fd, PollFlags::IN | PollFlags::RDBAND),
PollFd::new(&wake, PollFlags::IN),
];

match poll(&mut fds, -1) {
Expand All @@ -186,10 +165,10 @@ fn main() -> Result<(), String> {
},
};

[fds[0].revents(), fds[1].revents(), fds[2].revents()]
[fds[0].revents(), fds[1].revents()]
};

if !events[1].is_empty() {
if events[0].contains(PollFlags::IN) {
match read_guard.read() {
Ok(_) => {
event_queue
Expand All @@ -212,7 +191,7 @@ fn main() -> Result<(), String> {
drop(read_guard);
}

if !events[0].is_empty() {
if !events[1].is_empty() {
match listener.0.accept() {
Ok((stream, _adr)) => daemon.recv_socket_msg(stream),
Err(e) => match e.kind() {
Expand All @@ -221,20 +200,13 @@ fn main() -> Result<(), String> {
},
}
}

if !events[2].is_empty() {
if let Err(e) = rustix::io::read(&wake, &mut buf) {
error!("error reading pipe file descriptor: {e}");
}
}
}

info!("Goodbye!");
Ok(())
}

/// Returns the file descriptor we should install in the poll handler
fn setup_signals_and_eventfd() -> OwnedFd {
fn setup_signals() {
// C data structure, expected to be zeroed out.
let mut sigaction: libc::sigaction = unsafe { std::mem::zeroed() };
unsafe { libc::sigemptyset(std::ptr::addr_of_mut!(sigaction.sa_mask)) };
Expand All @@ -255,13 +227,6 @@ fn setup_signals_and_eventfd() -> OwnedFd {
error!("Failed to install signal handler!")
}
}

let fd: OwnedFd = rustix::event::eventfd(0, rustix::event::EventfdFlags::empty())
.expect("failed to create event fd");
POLL_WAKER
.set(fd.try_clone().expect("failed to clone event fd"))
.expect("failed to set POLL_WAKER");
fd
}

/// This is a wrapper that makes sure to delete the socket when it is dropped
Expand Down Expand Up @@ -413,7 +378,6 @@ impl Daemon {
wallpaper.clear(color);
wallpaper.draw();
}
wake_poll();
}) {
Ok(_) => Answer::Ok,
Err(e) => Answer::Err(format!("failed to spawn `clear` thread: {e}")),
Expand Down

0 comments on commit d96705d

Please sign in to comment.