diff --git a/drivers/vesad/src/main.rs b/drivers/vesad/src/main.rs index f1e1519..e1db357 100644 --- a/drivers/vesad/src/main.rs +++ b/drivers/vesad/src/main.rs @@ -6,10 +6,10 @@ extern crate alloc; extern crate orbclient; extern crate syscall; -use std::{env, thread}; +use std::{env, mem, thread}; use std::fs::File; use std::io::{Read, Write}; -use syscall::{physmap, physunmap, Packet, Scheme, MAP_WRITE, MAP_WRITE_COMBINE}; +use syscall::{physmap, physunmap, Packet, Scheme, EVENT_READ, MAP_WRITE, MAP_WRITE_COMBINE}; use mode_info::VBEModeInfo; use primitive::fast_set64; @@ -87,22 +87,22 @@ fn main() { } } - // If there are requested events, and data is available, send a notification - /* TODO - if (! scheme.screen.borrow().input.is_empty() || scheme.screen.borrow().end_of_input) && scheme.screen.borrow().requested & EVENT_READ == EVENT_READ { - let event_packet = Packet { - id: 0, - pid: 0, - uid: 0, - gid: 0, - a: syscall::number::SYS_FEVENT, - b: 0, - c: EVENT_READ, - d: scheme.screen.borrow().input.len() - }; - socket.write(&event_packet).expect("vesad: failed to write display scheme"); + for (screen_id, screen) in scheme.screens.borrow().iter() { + if ! screen.will_block() { + let event_packet = Packet { + id: 0, + pid: 0, + uid: 0, + gid: 0, + a: syscall::number::SYS_FEVENT, + b: *screen_id, + c: EVENT_READ, + d: mem::size_of::() + }; + + socket.write(&event_packet).expect("vesad: failed to write display event"); + } } - */ } }); } diff --git a/drivers/vesad/src/scheme.rs b/drivers/vesad/src/scheme.rs index 91484a1..8ce9034 100644 --- a/drivers/vesad/src/scheme.rs +++ b/drivers/vesad/src/scheme.rs @@ -14,7 +14,7 @@ pub struct DisplayScheme { onscreen: usize, active: Cell, next_screen: Cell, - screens: RefCell>> + pub screens: RefCell>> } impl DisplayScheme { @@ -77,7 +77,7 @@ impl Scheme for DisplayScheme { fn fevent(&self, id: usize, flags: usize) -> Result { let mut screens = self.screens.borrow_mut(); if let Some(mut screen) = screens.get_mut(&id) { - screen.event(flags) + screen.event(flags).and(Ok(id)) } else { Err(Error::new(EBADF)) } diff --git a/kernel/context/event.rs b/kernel/context/event.rs index 19d119d..a42ecef 100644 --- a/kernel/context/event.rs +++ b/kernel/context/event.rs @@ -27,7 +27,7 @@ pub fn registry_mut() -> RwLockWriteGuard<'static, Registry> { REGISTRY.call_once(init_registry).write() } -pub fn register(fd: usize, scheme_id: usize, id: usize) -> bool { +pub fn register(fd: usize, scheme_id: usize, event_id: usize) -> bool { let (context_id, events) = { let contexts = context::contexts(); let context_lock = contexts.current().expect("event::register: No context"); @@ -36,7 +36,7 @@ pub fn register(fd: usize, scheme_id: usize, id: usize) -> bool { }; let mut registry = registry_mut(); - let entry = registry.entry((scheme_id, id)).or_insert_with(|| { + let entry = registry.entry((scheme_id, event_id)).or_insert_with(|| { BTreeMap::new() }); if entry.contains_key(&(context_id, fd)) { @@ -47,11 +47,11 @@ pub fn register(fd: usize, scheme_id: usize, id: usize) -> bool { } } -pub fn unregister(fd: usize, scheme_id: usize, id: usize) { +pub fn unregister(fd: usize, scheme_id: usize, event_id: usize) { let mut registry = registry_mut(); let mut remove = false; - if let Some(entry) = registry.get_mut(&(scheme_id, id)) { + if let Some(entry) = registry.get_mut(&(scheme_id, event_id)) { entry.remove(&(context::context_id(), fd)); if entry.is_empty() { @@ -60,13 +60,13 @@ pub fn unregister(fd: usize, scheme_id: usize, id: usize) { } if remove { - registry.remove(&(scheme_id, id)); + registry.remove(&(scheme_id, event_id)); } } -pub fn trigger(scheme_id: usize, id: usize, flags: usize, data: usize) { +pub fn trigger(scheme_id: usize, event_id: usize, flags: usize, data: usize) { let registry = registry(); - if let Some(event_lists) = registry.get(&(scheme_id, id)) { + if let Some(event_lists) = registry.get(&(scheme_id, event_id)) { for entry in event_lists.iter() { if let Some(event_list) = entry.1.upgrade() { event_list.send(Event { diff --git a/kernel/context/file.rs b/kernel/context/file.rs index 67a28eb..d9238d6 100644 --- a/kernel/context/file.rs +++ b/kernel/context/file.rs @@ -8,4 +8,6 @@ pub struct File { pub scheme: usize, /// The number the scheme uses to refer to this file pub number: usize, + /// If events are on, this is the event ID + pub event: Option, } diff --git a/kernel/scheme/irq.rs b/kernel/scheme/irq.rs index 2ed891e..ce99c42 100644 --- a/kernel/scheme/irq.rs +++ b/kernel/scheme/irq.rs @@ -93,8 +93,8 @@ impl Scheme for IrqScheme { } } - fn fevent(&self, _file: usize, _flags: usize) -> Result { - Ok(0) + fn fevent(&self, file: usize, _flags: usize) -> Result { + Ok(file) } fn fsync(&self, _file: usize) -> Result { diff --git a/kernel/scheme/root.rs b/kernel/scheme/root.rs index 1d4d4d0..57877bf 100644 --- a/kernel/scheme/root.rs +++ b/kernel/scheme/root.rs @@ -89,8 +89,8 @@ impl Scheme for RootScheme { inner.write(buf) } - fn fevent(&self, _file: usize, _flags: usize) -> Result { - Ok(0) + fn fevent(&self, file: usize, _flags: usize) -> Result { + Ok(file) } fn fsync(&self, _file: usize) -> Result { diff --git a/kernel/syscall/fs.rs b/kernel/syscall/fs.rs index fb06884..6c953e4 100644 --- a/kernel/syscall/fs.rs +++ b/kernel/syscall/fs.rs @@ -98,7 +98,8 @@ pub fn open(path: &[u8], flags: usize) -> Result { let context = context_lock.read(); context.add_file(::context::file::File { scheme: scheme_id, - number: file_id + number: file_id, + event: None, }).ok_or(Error::new(EMFILE)) } @@ -113,12 +114,14 @@ pub fn pipe2(fds: &mut [usize], flags: usize) -> Result { let read_fd = context.add_file(::context::file::File { scheme: scheme_id, - number: read_id + number: read_id, + event: None, }).ok_or(Error::new(EMFILE))?; let write_fd = context.add_file(::context::file::File { scheme: scheme_id, - number: write_id + number: write_id, + event: None, }).ok_or(Error::new(EMFILE))?; fds[0] = read_fd; @@ -206,7 +209,9 @@ pub fn close(fd: usize) -> Result { file }; - context::event::unregister(fd, file.scheme, file.number); + if let Some(event_id) = file.event { + context::event::unregister(fd, file.scheme, event_id); + } let scheme = { let schemes = scheme::schemes(); @@ -240,7 +245,8 @@ pub fn dup(fd: usize) -> Result { let context = context_lock.read(); context.add_file(::context::file::File { scheme: file.scheme, - number: new_id + number: new_id, + event: None, }).ok_or(Error::new(EMFILE)) } @@ -250,8 +256,13 @@ pub fn fevent(fd: usize, flags: usize) -> Result { let contexts = context::contexts(); let context_lock = contexts.current().ok_or(Error::new(ESRCH))?; let context = context_lock.read(); - let file = context.get_file(fd).ok_or(Error::new(EBADF))?; - file + let mut files = context.files.lock(); + let mut file = files.get_mut(fd).ok_or(Error::new(EBADF))?.ok_or(Error::new(EBADF))?; + if let Some(event_id) = file.event.take() { + println!("{}: {}:{}: events already registered: {}", fd, file.scheme, file.number, event_id); + context::event::unregister(fd, file.scheme, event_id); + } + file.clone() }; let scheme = { @@ -259,7 +270,15 @@ pub fn fevent(fd: usize, flags: usize) -> Result { let scheme = schemes.get(file.scheme).ok_or(Error::new(EBADF))?; scheme.clone() }; - scheme.fevent(file.number, flags)?; - context::event::register(fd, file.scheme, file.number); + let event_id = scheme.fevent(file.number, flags)?; + { + let contexts = context::contexts(); + let context_lock = contexts.current().ok_or(Error::new(ESRCH))?; + let context = context_lock.read(); + let mut files = context.files.lock(); + let mut file = files.get_mut(fd).ok_or(Error::new(EBADF))?.ok_or(Error::new(EBADF))?; + file.event = Some(event_id); + } + context::event::register(fd, file.scheme, event_id); Ok(0) } diff --git a/kernel/syscall/process.rs b/kernel/syscall/process.rs index 5763c89..ddd2cec 100644 --- a/kernel/syscall/process.rs +++ b/kernel/syscall/process.rs @@ -232,7 +232,11 @@ pub fn clone(flags: usize, stack_base: usize) -> Result { }; match result { Ok(new_number) => { - Some(context::file::File { scheme: file.scheme, number: new_number }) + Some(context::file::File { + scheme: file.scheme, + number: new_number, + event: None, + }) }, Err(err) => { println!("clone: failed to dup {}: {:?}", fd, err); @@ -616,7 +620,9 @@ pub fn exit(status: usize) -> ! { /// Files must be closed while context is valid so that messages can be passed for (fd, file_option) in close_files.drain(..).enumerate() { if let Some(file) = file_option { - context::event::unregister(fd, file.scheme, file.number); + if let Some(event_id) = file.event { + context::event::unregister(fd, file.scheme, event_id); + } let scheme_option = { let schemes = scheme::schemes(); diff --git a/schemes/orbital b/schemes/orbital index 3667b89..c21bd76 160000 --- a/schemes/orbital +++ b/schemes/orbital @@ -1 +1 @@ -Subproject commit 3667b8960255928363b88ac9ac5902f228823512 +Subproject commit c21bd7618907c5d146c947e9b38d64fdb7479528