From 56808dbfb14babd9a98ba912e8ce99f34571a551 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Sat, 15 Mar 2025 16:50:29 +0100 Subject: [PATCH] graphics/fbbootlogd: Remove input events background thread --- graphics/fbbootlogd/src/display.rs | 56 +++++++-------------- graphics/fbbootlogd/src/main.rs | 81 ++++++++++++++++++++++-------- graphics/fbbootlogd/src/scheme.rs | 6 +-- 3 files changed, 79 insertions(+), 64 deletions(-) diff --git a/graphics/fbbootlogd/src/display.rs b/graphics/fbbootlogd/src/display.rs index a26f0fc578..430bff7c12 100644 --- a/graphics/fbbootlogd/src/display.rs +++ b/graphics/fbbootlogd/src/display.rs @@ -1,12 +1,11 @@ -use event::{user_data, EventQueue}; use graphics_ipc::v1::{Damage, V1GraphicsHandle}; use inputd::ConsumerHandle; use libredox::errno::ESTALE; use orbclient::Event; use std::mem; use std::os::fd::BorrowedFd; -use std::sync::{Arc, Mutex}; -use std::{io, os::unix::io::AsRawFd, slice}; +use std::os::unix::io::AsRawFd; +use std::{io, slice}; fn read_to_slice( file: BorrowedFd, @@ -24,18 +23,19 @@ fn read_to_slice( fn display_fd_map(display_handle: V1GraphicsHandle) -> io::Result { let display_map = display_handle.map_display()?; Ok(DisplayMap { - display_handle: Arc::new(display_handle), + display_handle, inner: display_map, }) } pub struct DisplayMap { - display_handle: Arc, + display_handle: V1GraphicsHandle, pub inner: graphics_ipc::v1::DisplayMap, } pub struct Display { - pub map: Arc>>, + pub input_handle: ConsumerHandle, + pub map: Option, } impl Display { @@ -45,51 +45,28 @@ impl Display { let map = match input_handle.open_display() { Ok(display) => { let display_handle = V1GraphicsHandle::from_file(display)?; - Arc::new(Mutex::new(Some( + Some( display_fd_map(display_handle) .unwrap_or_else(|e| panic!("failed to map display: {e}")), - ))) + ) } Err(err) => { println!("fbbootlogd: No display present yet: {err}"); - Arc::new(Mutex::new(None)) + None } }; - let map_clone = map.clone(); - std::thread::spawn(move || { - Self::handle_input_events(map_clone, input_handle); - }); - - Ok(Self { map }) + Ok(Self { input_handle, map }) } - fn handle_input_events(map: Arc>>, input_handle: ConsumerHandle) { - let event_queue = EventQueue::new().expect("fbbootlogd: failed to create event queue"); - - user_data! { - enum Source { - Input, - } - } - - // FIXME listen for resize events from inputd and handle them - - event_queue - .subscribe( - input_handle.inner().as_raw_fd() as usize, - Source::Input, - event::EventFlags::READ, - ) - .expect("fbbootlogd: failed to subscribe to scheme events"); - + pub fn handle_input_events(&mut self) { let mut events = [Event::new(); 16]; - for Source::Input in event_queue.map(|event| event.unwrap().user_data) { - match read_to_slice(input_handle.inner(), &mut events) { + loop { + match read_to_slice(self.input_handle.inner(), &mut events) { Err(err) if err.errno() == ESTALE => { eprintln!("fbbootlogd: handoff requested"); - let new_display_handle = match input_handle.open_display() { + let new_display_handle = match self.input_handle.open_display() { Ok(display) => V1GraphicsHandle::from_file(display).unwrap(), Err(err) => { println!("fbbootlogd: No display present yet: {err}"); @@ -99,7 +76,7 @@ impl Display { match display_fd_map(new_display_handle) { Ok(ok) => { - *map.lock().unwrap() = Some(ok); + self.map = Some(ok); eprintln!("fbbootlogd: handoff finished"); } @@ -109,6 +86,7 @@ impl Display { } } + Ok(0) => break, Ok(_count) => {} Err(err) => { panic!("fbbootlogd: error while reading events: {err}"); @@ -118,7 +96,7 @@ impl Display { } pub fn sync_rects(&mut self, sync_rects: Vec) { - if let Some(map) = &*self.map.lock().unwrap() { + if let Some(map) = &self.map { map.display_handle.sync_rects(&sync_rects).unwrap(); } } diff --git a/graphics/fbbootlogd/src/main.rs b/graphics/fbbootlogd/src/main.rs index b566a76df4..30e99c9ea0 100644 --- a/graphics/fbbootlogd/src/main.rs +++ b/graphics/fbbootlogd/src/main.rs @@ -7,6 +7,10 @@ //! In the future fbbootlogd may also pull from logd as opposed to have logd push logs to it. And it //! it could display a boot splash like plymouth instead of a boot log when booting in quiet mode. +use std::os::fd::AsRawFd; + +use event::EventQueue; +use libredox::errno::EAGAIN; use redox_scheme::{RequestKind, SignalBehavior, Socket}; use crate::scheme::FbbootlogScheme; @@ -18,41 +22,76 @@ fn main() { redox_daemon::Daemon::new(|daemon| inner(daemon)).expect("failed to create daemon"); } fn inner(daemon: redox_daemon::Daemon) -> ! { + let event_queue = EventQueue::new().expect("fbbootlogd: failed to create event queue"); + + event::user_data! { + enum Source { + Scheme, + Input, + } + } + let socket = - Socket::create("fbbootlog").expect("fbbootlogd: failed to create fbbootlog scheme"); + Socket::nonblock("fbbootlog").expect("fbbootlogd: failed to create fbbootlog scheme"); + + event_queue + .subscribe( + socket.inner().raw(), + Source::Scheme, + event::EventFlags::READ, + ) + .expect("fbcond: failed to subscribe to scheme events"); let mut scheme = FbbootlogScheme::new(); + event_queue + .subscribe( + scheme.display.input_handle.inner().as_raw_fd() as usize, + Source::Input, + event::EventFlags::READ, + ) + .expect("fbbootlogd: failed to subscribe to scheme events"); + // This is not possible for now as fbbootlogd needs to open new displays at runtime for graphics // driver handoff. In the future inputd may directly pass a handle to the display instead. //libredox::call::setrens(0, 0).expect("fbbootlogd: failed to enter null namespace"); daemon.ready().expect("failed to notify parent"); - loop { - let request = match socket - .next_request(SignalBehavior::Restart) - .expect("fbbootlogd: failed to read display scheme") - { - Some(request) => request, - None => { - // Scheme likely got unmounted - std::process::exit(0); - } - }; + for event in event_queue { + match event.expect("fbbootlogd: failed to get event").user_data { + Source::Scheme => { + loop { + let request = match socket.next_request(SignalBehavior::Restart) { + Ok(Some(request)) => request, + Ok(None) => { + // Scheme likely got unmounted + std::process::exit(0); + } + Err(err) if err.errno == EAGAIN => break, + Err(err) => panic!("fbbootlogd: failed to read display scheme: {err:?}"), + }; - match request.kind() { - RequestKind::Call(call) => { - let response = call.handle_scheme(&mut scheme); + match request.kind() { + RequestKind::Call(call) => { + let response = call.handle_scheme(&mut scheme); - socket - .write_responses(&[response], SignalBehavior::Restart) - .expect("pcid: failed to write next scheme response"); + socket + .write_responses(&[response], SignalBehavior::Restart) + .expect("pcid: failed to write next scheme response"); + } + RequestKind::OnClose { id } => { + scheme.on_close(id); + } + _ => (), + } + } } - RequestKind::OnClose { id } => { - scheme.on_close(id); + Source::Input => { + scheme.display.handle_input_events(); } - _ => (), } } + + std::process::exit(0); } diff --git a/graphics/fbbootlogd/src/scheme.rs b/graphics/fbbootlogd/src/scheme.rs index 9fa087f0fa..d4b21ef06c 100644 --- a/graphics/fbbootlogd/src/scheme.rs +++ b/graphics/fbbootlogd/src/scheme.rs @@ -6,7 +6,7 @@ use syscall::{Error, Result, EINVAL, ENOENT}; use crate::display::Display; pub struct FbbootlogScheme { - display: Display, + pub display: Display, text_screen: console_draw::TextScreen, } @@ -55,8 +55,7 @@ impl Scheme for FbbootlogScheme { } fn write(&mut self, _id: usize, buf: &[u8], _offset: u64, _fcntl_flags: u32) -> Result { - let mut map_guard = self.display.map.lock().unwrap(); - if let Some(map) = &mut *map_guard { + if let Some(map) = &mut self.display.map { let damage = self.text_screen.write( &mut console_draw::DisplayMap { offscreen: map.inner.ptr_mut(), @@ -66,7 +65,6 @@ impl Scheme for FbbootlogScheme { buf, &mut VecDeque::new(), ); - drop(map_guard); self.display.sync_rects(damage); }