From 5a1648fdca13d5f7fa656fee98d01a55d1daa31e Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Tue, 24 Dec 2024 16:56:11 +0100 Subject: [PATCH] graphics/fbcond: Migrate to redox-scheme --- Cargo.lock | 1 + graphics/fbcond/Cargo.toml | 1 + graphics/fbcond/src/main.rs | 109 +++++++++++++++------------------- graphics/fbcond/src/scheme.rs | 79 +++++++++++++----------- graphics/fbcond/src/text.rs | 8 +-- 5 files changed, 98 insertions(+), 100 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a56be31c9d..fc46dcb053 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -424,6 +424,7 @@ dependencies = [ "orbclient", "ransid", "redox-daemon", + "redox-scheme", "redox_event", "redox_syscall", ] diff --git a/graphics/fbcond/Cargo.toml b/graphics/fbcond/Cargo.toml index 42e155eaac..a22c102f40 100644 --- a/graphics/fbcond/Cargo.toml +++ b/graphics/fbcond/Cargo.toml @@ -9,6 +9,7 @@ ransid = "0.4" redox_event = "0.4" redox_syscall = "0.5" redox-daemon = "0.1" +redox-scheme = { git = "https://gitlab.redox-os.org/redox-os/redox-scheme.git" } inputd = { path = "../../inputd" } libredox = "0.1.3" diff --git a/graphics/fbcond/src/main.rs b/graphics/fbcond/src/main.rs index 09c9a44478..11ac25cec2 100644 --- a/graphics/fbcond/src/main.rs +++ b/graphics/fbcond/src/main.rs @@ -1,14 +1,12 @@ #![feature(io_error_more)] use event::EventQueue; -use libredox::errno::ESTALE; +use libredox::errno::{EAGAIN, EINTR, ESTALE}; use orbclient::Event; -use std::fs::{File, OpenOptions}; -use std::io::{ErrorKind, Read, Write}; +use redox_scheme::{CallRequest, RequestKind, Response, SignalBehavior, Socket}; use std::os::fd::{AsRawFd, BorrowedFd}; -use std::os::unix::fs::OpenOptionsExt; use std::{env, mem, slice}; -use syscall::{Packet, SchemeMut, EVENT_READ, O_NONBLOCK}; +use syscall::EVENT_READ; use crate::scheme::{FbconScheme, VtIndex}; @@ -42,16 +40,10 @@ fn inner(daemon: redox_daemon::Daemon, vt_ids: &[usize]) -> ! { // FIXME listen for resize events from inputd and handle them - let mut socket = OpenOptions::new() - .write(true) - .create(true) - .truncate(true) - .custom_flags(O_NONBLOCK as i32) - .open(":fbcon") - .expect("fbcond: failed to create fbcon scheme"); + let mut socket = Socket::nonblock("fbcon").expect("fbcond: failed to create fbcon scheme"); event_queue .subscribe( - socket.as_raw_fd().as_raw_fd() as usize, + socket.inner().raw(), VtIndex::SCHEMA_SENTINEL, event::EventFlags::READ, ) @@ -91,37 +83,49 @@ fn inner(daemon: redox_daemon::Daemon, vt_ids: &[usize]) -> ! { } fn handle_event( - socket: &mut File, + socket: &mut Socket, scheme: &mut FbconScheme, - blocked: &mut Vec, + blocked: &mut Vec, event: VtIndex, ) { match event { VtIndex::SCHEMA_SENTINEL => { loop { - let mut packet = Packet::default(); - match socket.read(&mut packet) { - Ok(0) => break, - Err(err) if err.kind() == ErrorKind::WouldBlock => { - break; + let request = match socket.next_request(SignalBehavior::Restart) { + Ok(Some(request)) => request, + Ok(None) => { + // Scheme likely got unmounted + std::process::exit(0); } - Ok(_) => {} - Err(err) => { - panic!("fbcond: failed to read display scheme: {err}"); - } - } + Err(err) if err.errno == EAGAIN => break, + Err(err) => panic!("vesad: failed to read display scheme: {err}"), + }; - // If it is a read packet, and there is no data, block it. Otherwise, handle packet - if packet.a == syscall::number::SYS_READ - && packet.d > 0 - && scheme.can_read(packet.b).is_none() - { - blocked.push(packet); - } else { - scheme.handle(&mut packet); - socket - .write(&packet) - .expect("fbcond: failed to write display scheme"); + match request.kind() { + RequestKind::Call(call_request) => { + if let Some(resp) = call_request.handle_scheme_block_mut(scheme) { + socket + .write_response(resp, SignalBehavior::Restart) + .expect("vesad: failed to write display scheme"); + } else { + blocked.push(call_request); + } + } + RequestKind::Cancellation(cancellation_request) => { + if let Some(i) = blocked + .iter() + .position(|req| req.request().request_id() == cancellation_request.id) + { + let blocked_req = blocked.remove(i); + let resp = Response::new(&blocked_req, Err(syscall::Error::new(EINTR))); + socket + .write_response(resp, SignalBehavior::Restart) + .expect("vesad: failed to write display scheme"); + } + } + RequestKind::MsyncMsg | RequestKind::MunmapMsg | RequestKind::MmapMsg => { + unreachable!() + } } } } @@ -150,16 +154,15 @@ fn handle_event( } } - // If there are blocked readers, and data is available, handle them + // If there are blocked readers, try to handle them. { let mut i = 0; while i < blocked.len() { - if scheme.can_read(blocked[i].b).is_some() { - let mut packet = blocked.remove(i); - scheme.handle(&mut packet); + if let Some(resp) = blocked[i].handle_scheme_block_mut(scheme) { socket - .write(&packet) - .expect("fbcond: failed to write display scheme"); + .write_response(resp, SignalBehavior::Restart) + .expect("vesad: failed to write display scheme"); + blocked.remove(i); } else { i += 1; } @@ -171,30 +174,16 @@ fn handle_event( continue; } - // Can't use scheme.can_read() because we borrow handles as mutable. - // (and because it'd treat O_NONBLOCK sockets differently) - let count = scheme + let can_read = scheme .vts .get(&handle.vt_i) - .and_then(|console| console.can_read()) - .unwrap_or(0); + .map_or(false, |console| console.can_read()); - if count > 0 { + if can_read { if !handle.notified_read { handle.notified_read = true; - let event_packet = Packet { - id: 0, - pid: 0, - uid: 0, - gid: 0, - a: syscall::number::SYS_FEVENT, - b: *handle_id, - c: EVENT_READ.bits(), - d: count, - }; - socket - .write(&event_packet) + .post_fevent(*handle_id, EVENT_READ.bits()) .expect("fbcond: failed to write display event"); } } else { diff --git a/graphics/fbcond/src/scheme.rs b/graphics/fbcond/src/scheme.rs index 4b8afe212e..1b37b6674c 100644 --- a/graphics/fbcond/src/scheme.rs +++ b/graphics/fbcond/src/scheme.rs @@ -2,7 +2,8 @@ use std::collections::BTreeMap; use std::os::fd::AsRawFd; use event::{EventQueue, UserData}; -use syscall::{Error, EventFlags, Result, SchemeMut, EBADF, EINVAL, ENOENT, O_NONBLOCK}; +use redox_scheme::SchemeBlockMut; +use syscall::{Error, EventFlags, Result, EBADF, EINVAL, ENOENT, O_NONBLOCK}; use crate::display::Display; use crate::text::TextScreen; @@ -61,22 +62,6 @@ impl FbconScheme { } } - pub fn can_read(&self, id: usize) -> Option { - if let Some(handle) = self.handles.get(&id) { - if let Some(console) = self.vts.get(&handle.vt_i) { - console - .can_read() - .or(if handle.flags & O_NONBLOCK == O_NONBLOCK { - Some(0) - } else { - None - }); - } - } - - Some(0) - } - fn resize(&mut self, width: usize, height: usize, stride: usize) { for console in self.vts.values_mut() { console.resize(width, height); @@ -84,8 +69,14 @@ impl FbconScheme { } } -impl SchemeMut for FbconScheme { - fn open(&mut self, path_str: &str, flags: usize, _uid: u32, _gid: u32) -> Result { +impl SchemeBlockMut for FbconScheme { + fn open( + &mut self, + path_str: &str, + flags: usize, + _uid: u32, + _gid: u32, + ) -> Result> { let vt_i = VtIndex(path_str.parse::().map_err(|_| Error::new(ENOENT))?); if let Some(_console) = self.vts.get_mut(&vt_i) { let id = self.next_id; @@ -101,13 +92,13 @@ impl SchemeMut for FbconScheme { }, ); - Ok(id) + Ok(Some(id)) } else { Err(Error::new(ENOENT)) } } - fn dup(&mut self, id: usize, buf: &[u8]) -> Result { + fn dup(&mut self, id: usize, buf: &[u8]) -> Result> { if !buf.is_empty() { return Err(Error::new(EINVAL)); } @@ -123,19 +114,23 @@ impl SchemeMut for FbconScheme { self.handles.insert(new_id, handle); - Ok(new_id) + Ok(Some(new_id)) } - fn fevent(&mut self, id: usize, flags: syscall::EventFlags) -> Result { + fn fevent( + &mut self, + id: usize, + flags: syscall::EventFlags, + ) -> Result> { let handle = self.handles.get_mut(&id).ok_or(Error::new(EBADF))?; handle.notified_read = false; handle.events = flags; - Ok(syscall::EventFlags::empty()) + Ok(Some(syscall::EventFlags::empty())) } - fn fpath(&mut self, id: usize, buf: &mut [u8]) -> Result { + fn fpath(&mut self, id: usize, buf: &mut [u8]) -> Result> { let handle = self.handles.get(&id).ok_or(Error::new(EBADF))?; let path_str = format!("fbcon:{}", handle.vt_i.0); @@ -148,37 +143,53 @@ impl SchemeMut for FbconScheme { i += 1; } - Ok(i) + Ok(Some(i)) } - fn fsync(&mut self, id: usize) -> Result { + fn fsync(&mut self, id: usize) -> Result> { let _handle = self.handles.get(&id).ok_or(Error::new(EBADF))?; - return Ok(0); + return Ok(Some(0)); } - fn read(&mut self, id: usize, buf: &mut [u8]) -> Result { + fn read( + &mut self, + id: usize, + buf: &mut [u8], + _offset: u64, + _fcntl_flags: u32, + ) -> Result> { let handle = self.handles.get(&id).ok_or(Error::new(EBADF))?; if let Some(screen) = self.vts.get_mut(&handle.vt_i) { - return screen.read(buf); + if !screen.can_read() && handle.flags & O_NONBLOCK != O_NONBLOCK { + return Ok(None); + } else { + return screen.read(buf).map(Some); + } } Err(Error::new(EBADF)) } - fn write(&mut self, id: usize, buf: &[u8]) -> Result { + fn write( + &mut self, + id: usize, + buf: &[u8], + _offset: u64, + _fcntl_flags: u32, + ) -> Result> { let handle = self.handles.get(&id).ok_or(Error::new(EBADF))?; if let Some(console) = self.vts.get_mut(&handle.vt_i) { - console.write(buf) + console.write(buf).map(Some) } else { Err(Error::new(EBADF)) } } - fn close(&mut self, id: usize) -> Result { + fn close(&mut self, id: usize) -> Result> { self.handles.remove(&id).ok_or(Error::new(EBADF))?; - Ok(0) + Ok(Some(0)) } } diff --git a/graphics/fbcond/src/text.rs b/graphics/fbcond/src/text.rs index d62b15f502..bbe519b117 100644 --- a/graphics/fbcond/src/text.rs +++ b/graphics/fbcond/src/text.rs @@ -204,12 +204,8 @@ impl TextScreen { } } - pub fn can_read(&self) -> Option { - if self.input.is_empty() { - None - } else { - Some(self.input.len()) - } + pub fn can_read(&self) -> bool { + !self.input.is_empty() } }