diff --git a/graphics/fbcond/src/display.rs b/graphics/fbcond/src/display.rs index d7af9f1ab6..2cd4d897dd 100644 --- a/graphics/fbcond/src/display.rs +++ b/graphics/fbcond/src/display.rs @@ -1,18 +1,9 @@ -use inputd::Damage; +use inputd::{ConsumerHandle, Damage}; use libredox::flag; -use std::fs::OpenOptions; use std::mem; -use std::os::unix::fs::OpenOptionsExt; use std::sync::mpsc::{self, Sender}; use std::sync::{Arc, Mutex}; -use std::{ - fs::File, - io, - os::fd::RawFd, - os::unix::io::{AsRawFd, FromRawFd}, - slice, -}; -use syscall::{O_CLOEXEC, O_NONBLOCK, O_RDWR}; +use std::{fs::File, io, os::unix::io::AsRawFd, slice}; fn display_fd_map( width: usize, @@ -60,34 +51,30 @@ impl Drop for DisplayMap { enum DisplayCommand { Resize { width: usize, height: usize }, - ReopenForHandoff { display_path: String }, + ReopenForHandoff, SyncRects(Vec), } pub struct Display { - pub input_handle: File, + pub input_handle: Arc, cmd_tx: Sender, pub map: Arc>, } impl Display { pub fn open_vt(vt: usize) -> io::Result { - let mut input_handle = OpenOptions::new() - .read(true) - .custom_flags(O_NONBLOCK as i32) - .open(format!("/scheme/input/consumer/{vt}"))?; + let input_handle = Arc::new(ConsumerHandle::for_vt(vt)?); - let display_path = Self::display_path(&mut input_handle)?; - - let (mut display_file, width, height) = Self::open_display(&display_path)?; + let (mut display_file, width, height) = Self::open_display(&input_handle)?; let map = Arc::new(Mutex::new( display_fd_map(width, height, &mut display_file) - .unwrap_or_else(|e| panic!("failed to map display '{display_path}: {e}")), + .unwrap_or_else(|e| panic!("failed to map display for VT #{vt}: {e}")), )); let (cmd_tx, cmd_rx) = mpsc::channel(); + let input_handle_clone = input_handle.clone(); let map_clone = map.clone(); std::thread::spawn(move || { while let Ok(cmd) = cmd_rx.recv() { @@ -105,20 +92,20 @@ impl Display { } } } - DisplayCommand::ReopenForHandoff { display_path } => { - eprintln!("fbcond: Performing handoff for '{display_path}'"); + DisplayCommand::ReopenForHandoff => { + eprintln!("fbcond: Performing handoff"); let (mut new_display_file, width, height) = - Self::open_display(&display_path).unwrap(); + Self::open_display(&input_handle_clone).unwrap(); - eprintln!("fbcond: Opened new display '{display_path}'"); + eprintln!("fbcond: Opened new display for VT #{vt}"); match display_fd_map(width, height, &mut new_display_file) { Ok(ok) => { *map_clone.lock().unwrap() = ok; display_file = new_display_file; - eprintln!("fbcond: Mapped new display '{display_path}'"); + eprintln!("fbcond: Mapped new display for VT #{vt}"); } Err(err) => { eprintln!( @@ -156,33 +143,11 @@ impl Display { /// Warning: This must be called in a background thread to avoid a deadlock when the /// graphics driver (indirectly) writes logs to fbcond. pub fn reopen_for_handoff(&mut self) { - let display_path = Self::display_path(&mut self.input_handle).unwrap(); - - self.cmd_tx - .send(DisplayCommand::ReopenForHandoff { display_path }) - .unwrap(); + self.cmd_tx.send(DisplayCommand::ReopenForHandoff).unwrap(); } - fn display_path(input_handle: &mut File) -> io::Result { - let mut buffer = [0; 1024]; - let fd = input_handle.as_raw_fd(); - let written = libredox::call::fpath(fd as usize, &mut buffer) - .expect("init: failed to get the path to the display device"); - - assert!(written <= buffer.len()); - - Ok(std::str::from_utf8(&buffer[..written]) - .expect("init: display path UTF-8 check failed") - .to_owned()) - } - - fn open_display(display_path: &str) -> io::Result<(File, usize, usize)> { - let display_file = - libredox::call::open(&display_path, (O_CLOEXEC | O_NONBLOCK | O_RDWR) as _, 0) - .map(|socket| unsafe { File::from_raw_fd(socket as RawFd) }) - .unwrap_or_else(|err| { - panic!("failed to open display {}: {}", display_path, err); - }); + fn open_display(input_handle: &ConsumerHandle) -> io::Result<(File, usize, usize)> { + let display_file = input_handle.open_display()?; let mut buf: [u8; 4096] = [0; 4096]; let count = libredox::call::fpath(display_file.as_raw_fd() as usize, &mut buf) diff --git a/graphics/fbcond/src/main.rs b/graphics/fbcond/src/main.rs index f5d5b8d243..09c9a44478 100644 --- a/graphics/fbcond/src/main.rs +++ b/graphics/fbcond/src/main.rs @@ -1,12 +1,13 @@ #![feature(io_error_more)] use event::EventQueue; +use libredox::errno::ESTALE; use orbclient::Event; use std::fs::{File, OpenOptions}; use std::io::{ErrorKind, Read, Write}; -use std::os::fd::AsRawFd; +use std::os::fd::{AsRawFd, BorrowedFd}; use std::os::unix::fs::OpenOptionsExt; -use std::{env, io, mem, slice}; +use std::{env, mem, slice}; use syscall::{Packet, SchemeMut, EVENT_READ, O_NONBLOCK}; use crate::scheme::{FbconScheme, VtIndex}; @@ -15,12 +16,15 @@ mod display; mod scheme; mod text; -fn read_to_slice(mut r: R, buf: &mut [T]) -> io::Result { +fn read_to_slice( + file: BorrowedFd, + buf: &mut [T], +) -> Result { unsafe { - r.read(slice::from_raw_parts_mut( - buf.as_mut_ptr() as *mut u8, - buf.len() * mem::size_of::(), - )) + libredox::call::read( + file.as_raw_fd() as usize, + slice::from_raw_parts_mut(buf.as_mut_ptr() as *mut u8, buf.len() * mem::size_of::()), + ) .map(|count| count / mem::size_of::()) } } @@ -126,12 +130,9 @@ fn handle_event( let mut events = [Event::new(); 16]; loop { - match read_to_slice(&mut vt.display.input_handle, &mut events) { + match read_to_slice(vt.display.input_handle.inner(), &mut events) { Ok(0) => break, - Err(err) if err.kind() == ErrorKind::WouldBlock => { - break; - } - Err(err) if err.kind() == ErrorKind::StaleNetworkFileHandle => { + Err(err) if err.errno() == ESTALE => { vt.handle_handoff(); } diff --git a/graphics/fbcond/src/scheme.rs b/graphics/fbcond/src/scheme.rs index 9ff10d4dbe..4b8afe212e 100644 --- a/graphics/fbcond/src/scheme.rs +++ b/graphics/fbcond/src/scheme.rs @@ -46,7 +46,7 @@ impl FbconScheme { let display = Display::open_vt(vt_i).expect("Failed to open display for vt"); event_queue .subscribe( - display.input_handle.as_raw_fd().as_raw_fd() as usize, + display.input_handle.inner().as_raw_fd() as usize, VtIndex(vt_i), event::EventFlags::READ, ) diff --git a/graphics/vesad/src/main.rs b/graphics/vesad/src/main.rs index b028a9ba84..20bd314650 100644 --- a/graphics/vesad/src/main.rs +++ b/graphics/vesad/src/main.rs @@ -3,12 +3,11 @@ extern crate orbclient; extern crate syscall; use event::{user_data, EventQueue}; -use libredox::errno::{EAGAIN, EINTR}; -use redox_scheme::{RequestKind, Response, SignalBehavior, Socket, V2}; +use libredox::errno::EAGAIN; +use redox_scheme::{RequestKind, SignalBehavior, Socket, V2}; use std::env; use std::fs::File; use std::os::fd::AsRawFd; -use syscall::EVENT_READ; use crate::{framebuffer::FrameBuffer, scheme::DisplayScheme}; @@ -118,7 +117,6 @@ fn inner(daemon: redox_daemon::Daemon, framebuffers: Vec, spec: &[( inputd_control_handle.activate_vt(1).unwrap(); - let mut blocked = Vec::new(); let all = [Source::Input, Source::Scheme]; for event in all .into_iter() @@ -148,66 +146,18 @@ fn inner(daemon: redox_daemon::Daemon, framebuffers: Vec, spec: &[( match request.kind() { RequestKind::Call(call_request) => { - if let Some(resp) = call_request.handle_scheme_block_mut(&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"); - } + socket + .write_response( + call_request.handle_scheme_mut(&mut scheme), + SignalBehavior::Restart, + ) + .expect("vesad: failed to write display scheme"); } + RequestKind::Cancellation(_cancellation_request) => {} RequestKind::MsyncMsg | RequestKind::MunmapMsg | RequestKind::MmapMsg => { unreachable!() } } - - // If there are blocked readers, try to handle them. - { - let mut i = 0; - while i < blocked.len() { - if let Some(resp) = blocked[i].handle_scheme_block_mut(&mut scheme) { - socket - .write_response(resp, SignalBehavior::Restart) - .expect("vesad: failed to write display scheme"); - blocked.remove(i); - } else { - i += 1; - } - } - } - - for (handle_id, handle) in scheme.handles.iter_mut() { - if handle.notified_read || !handle.events.contains(EVENT_READ) { - continue; - } - - let can_read = scheme - .vts - .get(&handle.vt) - .and_then(|screens| screens.get(&handle.screen)) - .map_or(false, |screen| screen.can_read()); - - if can_read { - handle.notified_read = true; - socket - .post_fevent(*handle_id, EVENT_READ.bits()) - .expect("vesad: failed to write display event"); - } else { - handle.notified_read = false; - } - } } } } diff --git a/graphics/vesad/src/scheme.rs b/graphics/vesad/src/scheme.rs index d2127e3a68..19ac71782d 100644 --- a/graphics/vesad/src/scheme.rs +++ b/graphics/vesad/src/scheme.rs @@ -2,8 +2,8 @@ use std::collections::BTreeMap; use std::str; use inputd::{VtEvent, VtEventKind}; -use redox_scheme::SchemeBlockMut; -use syscall::{Error, EventFlags, MapFlags, Result, EBADF, EINVAL, ENOENT, O_NONBLOCK}; +use redox_scheme::SchemeMut; +use syscall::{Error, MapFlags, Result, EBADF, EINVAL, ENOENT}; use crate::{framebuffer::FrameBuffer, screen::GraphicScreen}; @@ -17,10 +17,6 @@ pub struct ScreenIndex(usize); pub struct Handle { pub vt: VtIndex, pub screen: ScreenIndex, - - pub flags: usize, - pub events: EventFlags, - pub notified_read: bool, } pub struct DisplayScheme { @@ -109,14 +105,8 @@ impl DisplayScheme { } } -impl SchemeBlockMut for DisplayScheme { - fn open( - &mut self, - path_str: &str, - flags: usize, - _uid: u32, - _gid: u32, - ) -> Result> { +impl SchemeMut for DisplayScheme { + fn open(&mut self, path_str: &str, _flags: usize, _uid: u32, _gid: u32) -> Result { let mut parts = path_str.split('/'); let mut vt_screen = parts.next().unwrap_or("").split('.'); let vt_i = VtIndex(vt_screen.next().unwrap_or("").parse::().unwrap_or(1)); @@ -131,14 +121,10 @@ impl SchemeBlockMut for DisplayScheme { Handle { vt: vt_i, screen: screen_i, - - flags, - events: EventFlags::empty(), - notified_read: false, }, ); - Ok(Some(id)) + Ok(id) } else { Err(Error::new(ENOENT)) } @@ -147,7 +133,7 @@ impl SchemeBlockMut for DisplayScheme { } } - 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)); } @@ -163,22 +149,10 @@ impl SchemeBlockMut for DisplayScheme { self.handles.insert(new_id, handle.clone()); - Ok(Some(new_id)) + Ok(new_id) } - 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(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 = { @@ -204,10 +178,10 @@ impl SchemeBlockMut for DisplayScheme { i += 1; } - Ok(Some(i)) + Ok(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))?; if let Some(screens) = self.vts.get_mut(&handle.vt) { @@ -215,7 +189,7 @@ impl SchemeBlockMut for DisplayScheme { if handle.vt == self.active { screen.redraw(&mut self.framebuffers[handle.screen.0]); } - return Ok(Some(0)); + return Ok(0); } } @@ -225,47 +199,24 @@ impl SchemeBlockMut for DisplayScheme { fn read( &mut self, id: usize, - buf: &mut [u8], + _buf: &mut [u8], _offset: u64, _fcntl_flags: u32, - ) -> Result> { - let handle = self.handles.get(&id).ok_or(Error::new(EBADF))?; + ) -> Result { + let _handle = self.handles.get(&id).ok_or(Error::new(EBADF))?; - if let Some(screens) = self.vts.get_mut(&handle.vt) { - if let Some(screen) = screens.get_mut(&handle.screen) { - let nread = screen.read(buf)?; - if nread != 0 { - return Ok(Some(nread)); - } else { - if handle.flags & O_NONBLOCK == O_NONBLOCK { - return Ok(Some(0)); - } else { - return Ok(None); - } - } - } - } - - Err(Error::new(EBADF)) + Err(Error::new(EINVAL)) } - fn write( - &mut self, - id: usize, - buf: &[u8], - _offset: u64, - _fcntl_flags: u32, - ) -> 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(screens) = self.vts.get_mut(&handle.vt) { if let Some(screen) = screens.get_mut(&handle.screen) { if handle.vt == self.active { - screen - .write(buf, Some(&mut self.framebuffers[handle.screen.0])) - .map(|count| Some(count)) + screen.write(buf, Some(&mut self.framebuffers[handle.screen.0])) } else { - screen.write(buf, None).map(|count| Some(count)) + screen.write(buf, None) } } else { Err(Error::new(EBADF)) @@ -275,23 +226,17 @@ impl SchemeBlockMut for DisplayScheme { } } - fn close(&mut self, id: usize) -> Result> { + fn close(&mut self, id: usize) -> Result { self.handles.remove(&id).ok_or(Error::new(EBADF))?; - Ok(Some(0)) + Ok(0) } - fn mmap_prep( - &mut self, - id: usize, - off: u64, - size: usize, - _flags: MapFlags, - ) -> Result> { + fn mmap_prep(&mut self, id: usize, off: u64, size: usize, _flags: MapFlags) -> Result { let handle = self.handles.get(&id).ok_or(Error::new(EBADF))?; if let Some(screens) = self.vts.get(&handle.vt) { if let Some(screen) = screens.get(&handle.screen) { if off as usize + size <= screen.offscreen.len() * 4 { - return Ok(Some(screen.offscreen.as_ptr() as usize + off as usize)); + return Ok(screen.offscreen.as_ptr() as usize + off as usize); } else { return Err(Error::new(EINVAL)); } diff --git a/graphics/vesad/src/screen.rs b/graphics/vesad/src/screen.rs index 3f6612b20a..a50518ae4c 100644 --- a/graphics/vesad/src/screen.rs +++ b/graphics/vesad/src/screen.rs @@ -1,9 +1,7 @@ -use std::collections::VecDeque; use std::convert::TryInto; use std::{cmp, mem, ptr, slice}; use inputd::Damage; -use orbclient::{Event, ResizeEvent}; use syscall::error::*; use crate::display::OffscreenBuffer; @@ -13,7 +11,6 @@ pub struct GraphicScreen { pub width: usize, pub height: usize, pub offscreen: OffscreenBuffer, - pub input: VecDeque, } impl GraphicScreen { @@ -22,7 +19,6 @@ impl GraphicScreen { width, height, offscreen: OffscreenBuffer::new(width * height), - input: VecDeque::new(), } } } @@ -71,36 +67,6 @@ impl GraphicScreen { } else { println!("Display is already {}, {}", width, height); }; - - self.input.push_back( - ResizeEvent { - width: width as u32, - height: height as u32, - } - .to_event(), - ); - } - - pub fn read(&mut self, buf: &mut [u8]) -> Result { - let mut i = 0; - - let event_buf = unsafe { - slice::from_raw_parts_mut( - buf.as_mut_ptr() as *mut Event, - buf.len() / mem::size_of::(), - ) - }; - - while i < event_buf.len() && !self.input.is_empty() { - event_buf[i] = self.input.pop_front().unwrap(); - i += 1; - } - - Ok(i * mem::size_of::()) - } - - pub fn can_read(&self) -> bool { - !self.input.is_empty() } pub fn write(&mut self, buf: &[u8], framebuffer: Option<&mut FrameBuffer>) -> Result { @@ -117,7 +83,6 @@ impl GraphicScreen { Ok(sync_rects.len() * mem::size_of::()) } - pub fn sync(&mut self, framebuffer: &mut FrameBuffer, sync_rects: &[Damage]) { for sync_rect in sync_rects { let sync_rect = sync_rect.clip( diff --git a/inputd/src/lib.rs b/inputd/src/lib.rs index d73cc62d28..8956964ed6 100644 --- a/inputd/src/lib.rs +++ b/inputd/src/lib.rs @@ -1,10 +1,13 @@ #![feature(iter_next_chunk)] use std::cmp; -use std::fs::File; +use std::fs::{File, OpenOptions}; use std::io::{Error, Read, Write}; use std::mem::size_of; -use std::os::fd::{AsFd, BorrowedFd}; +use std::os::fd::{AsFd, AsRawFd, BorrowedFd, FromRawFd, RawFd}; +use std::os::unix::fs::OpenOptionsExt; + +use libredox::flag::{O_CLOEXEC, O_NONBLOCK, O_RDWR}; unsafe fn any_as_u8_slice(p: &T) -> &[u8] { std::slice::from_raw_parts((p as *const T) as *const u8, size_of::()) @@ -14,6 +17,44 @@ unsafe fn any_as_u8_slice_mut(p: &mut T) -> &mut [u8] { std::slice::from_raw_parts_mut((p as *mut T) as *mut u8, size_of::()) } +pub struct ConsumerHandle(File); + +impl ConsumerHandle { + pub fn for_vt(vt: usize) -> Result { + let file = OpenOptions::new() + .read(true) + .custom_flags(O_NONBLOCK as i32) + .open(format!("/scheme/input/consumer/{vt}"))?; + Ok(Self(file)) + } + + pub fn inner(&self) -> BorrowedFd<'_> { + self.0.as_fd() + } + + pub fn open_display(&self) -> Result { + let mut buffer = [0; 1024]; + let fd = self.0.as_raw_fd(); + let written = libredox::call::fpath(fd as usize, &mut buffer) + .expect("init: failed to get the path to the display device"); + + assert!(written <= buffer.len()); + + let display_path = std::str::from_utf8(&buffer[..written]) + .expect("init: display path UTF-8 check failed") + .to_owned(); + + let display_file = + libredox::call::open(&display_path, (O_CLOEXEC | O_NONBLOCK | O_RDWR) as _, 0) + .map(|socket| unsafe { File::from_raw_fd(socket as RawFd) }) + .unwrap_or_else(|err| { + panic!("failed to open display {}: {}", display_path, err); + }); + + Ok(display_file) + } +} + #[derive(Debug, Clone)] #[repr(C)] pub struct VtActivate {