Event support - demonstration in example scheme

This commit is contained in:
Jeremy Soller 2016-09-23 17:54:39 -06:00
parent 616dfbc055
commit 0e8487cf83
12 changed files with 239 additions and 31 deletions

View file

@ -13,7 +13,7 @@ use std::fs::File;
use std::io::{Read, Write}; use std::io::{Read, Write};
use std::{slice, thread}; use std::{slice, thread};
use ransid::{Console, Event}; use ransid::{Console, Event};
use syscall::{physmap, physunmap, Packet, Result, Scheme, MAP_WRITE, MAP_WRITE_COMBINE}; use syscall::{physmap, physunmap, Packet, Result, Scheme, EVENT_READ, MAP_WRITE, MAP_WRITE_COMBINE};
use display::Display; use display::Display;
use mode_info::VBEModeInfo; use mode_info::VBEModeInfo;
@ -26,7 +26,8 @@ pub mod primitive;
struct DisplayScheme { struct DisplayScheme {
console: RefCell<Console>, console: RefCell<Console>,
display: RefCell<Display>, display: RefCell<Display>,
input: RefCell<VecDeque<u8>> input: RefCell<VecDeque<u8>>,
requested: RefCell<usize>
} }
impl Scheme for DisplayScheme { impl Scheme for DisplayScheme {
@ -43,6 +44,7 @@ impl Scheme for DisplayScheme {
} }
fn fevent(&self, _id: usize, flags: usize) -> Result<usize> { fn fevent(&self, _id: usize, flags: usize) -> Result<usize> {
*self.requested.borrow_mut() = flags;
println!("fevent {:X}", flags); println!("fevent {:X}", flags);
Ok(0) Ok(0)
} }
@ -126,7 +128,8 @@ fn main() {
unsafe { slice::from_raw_parts_mut(onscreen as *mut u32, size) }, unsafe { slice::from_raw_parts_mut(onscreen as *mut u32, size) },
unsafe { slice::from_raw_parts_mut(offscreen as *mut u32, size) } unsafe { slice::from_raw_parts_mut(offscreen as *mut u32, size) }
)), )),
input: RefCell::new(VecDeque::new()) input: RefCell::new(VecDeque::new()),
requested: RefCell::new(0)
}; };
let mut blocked = VecDeque::new(); let mut blocked = VecDeque::new();
@ -134,18 +137,36 @@ fn main() {
let mut packet = Packet::default(); let mut packet = Packet::default();
socket.read(&mut packet).expect("vesad: failed to read display scheme"); socket.read(&mut packet).expect("vesad: failed to read display scheme");
//println!("vesad: {:?}", packet); //println!("vesad: {:?}", packet);
// 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.input.borrow().is_empty() { if packet.a == syscall::number::SYS_READ && packet.d > 0 && scheme.input.borrow().is_empty() {
blocked.push_back(packet); blocked.push_back(packet);
} else { } else {
scheme.handle(&mut packet); scheme.handle(&mut packet);
socket.write(&packet).expect("vesad: failed to write display scheme"); socket.write(&packet).expect("vesad: failed to write display scheme");
} }
// If there are blocked readers, and data is available, handle them
while ! scheme.input.borrow().is_empty() { while ! scheme.input.borrow().is_empty() {
if let Some(mut packet) = blocked.pop_front() { if let Some(mut packet) = blocked.pop_front() {
scheme.handle(&mut packet); scheme.handle(&mut packet);
socket.write(&packet).expect("vesad: failed to write display scheme"); socket.write(&packet).expect("vesad: failed to write display scheme");
} else {
break;
} }
} }
// If there are requested events, and data is available, send a notification
if ! scheme.input.borrow().is_empty() && *scheme.requested.borrow() & EVENT_READ == EVENT_READ {
let event_packet = Packet {
id: 0,
a: syscall::number::SYS_FEVENT,
b: 0,
c: EVENT_READ,
d: scheme.input.borrow().len()
};
socket.write(&event_packet).expect("vesad: failed to write display scheme");
}
} }
}); });
} }

View file

@ -1,9 +1,10 @@
use alloc::arc::Arc; use alloc::arc::Arc;
use alloc::boxed::Box; use alloc::boxed::Box;
use collections::{BTreeMap, Vec}; use collections::{BTreeMap, Vec, VecDeque};
use spin::Mutex; use spin::Mutex;
use arch; use arch;
use syscall::data::Event;
use super::file::File; use super::file::File;
use super::memory::{Grant, Memory, SharedMemory}; use super::memory::{Grant, Memory, SharedMemory};
@ -39,6 +40,8 @@ pub struct Context {
pub grants: Arc<Mutex<Vec<Grant>>>, pub grants: Arc<Mutex<Vec<Grant>>>,
/// The current working directory /// The current working directory
pub cwd: Arc<Mutex<Vec<u8>>>, pub cwd: Arc<Mutex<Vec<u8>>>,
/// Kernel events
pub events: Arc<Mutex<VecDeque<Event>>>,
/// The process environment /// The process environment
pub env: Arc<Mutex<BTreeMap<Box<[u8]>, Arc<Mutex<Vec<u8>>>>>>, pub env: Arc<Mutex<BTreeMap<Box<[u8]>, Arc<Mutex<Vec<u8>>>>>>,
/// The open files in the scheme /// The open files in the scheme
@ -60,6 +63,7 @@ impl Context {
stack: None, stack: None,
grants: Arc::new(Mutex::new(Vec::new())), grants: Arc::new(Mutex::new(Vec::new())),
cwd: Arc::new(Mutex::new(Vec::new())), cwd: Arc::new(Mutex::new(Vec::new())),
events: Arc::new(Mutex::new(VecDeque::new())),
env: Arc::new(Mutex::new(BTreeMap::new())), env: Arc::new(Mutex::new(BTreeMap::new())),
files: Arc::new(Mutex::new(Vec::new())) files: Arc::new(Mutex::new(Vec::new()))
} }

80
kernel/context/event.rs Normal file
View file

@ -0,0 +1,80 @@
use alloc::arc::{Arc, Weak};
use collections::{BTreeMap, VecDeque};
use spin::{Mutex, Once, RwLock, RwLockReadGuard, RwLockWriteGuard};
use context;
use syscall::data::Event;
type EventList = Weak<Mutex<VecDeque<Event>>>;
type Registry = BTreeMap<(usize, usize), BTreeMap<(usize, usize), EventList>>;
static REGISTRY: Once<RwLock<Registry>> = Once::new();
/// Initialize registry, called if needed
fn init_registry() -> RwLock<Registry> {
RwLock::new(Registry::new())
}
/// Get the global schemes list, const
fn registry() -> RwLockReadGuard<'static, Registry> {
REGISTRY.call_once(init_registry).read()
}
/// Get the global schemes list, mutable
pub fn registry_mut() -> RwLockWriteGuard<'static, Registry> {
REGISTRY.call_once(init_registry).write()
}
pub fn register(fd: usize, scheme_id: usize, id: usize) -> bool {
let (context_id, events) = {
let contexts = context::contexts();
let context_lock = contexts.current().expect("event::register: No context");
let context = context_lock.read();
(context.id, Arc::downgrade(&context.events))
};
let mut registry = registry_mut();
let entry = registry.entry((scheme_id, id)).or_insert_with(|| {
BTreeMap::new()
});
if entry.contains_key(&(context_id, fd)) {
false
} else {
entry.insert((context_id, fd), events);
true
}
}
pub fn unregister(fd: usize, scheme_id: usize, id: usize) {
let mut registry = registry_mut();
let mut remove = false;
if let Some(entry) = registry.get_mut(&(scheme_id, id)) {
entry.remove(&(context::context_id(), fd));
if entry.is_empty() {
remove = true;
}
}
if remove {
registry.remove(&(scheme_id, id));
}
}
pub fn trigger(scheme_id: usize, id: usize, flags: usize, data: usize) {
let registry = registry();
if let Some(event_lists) = registry.get(&(scheme_id, id)) {
for entry in event_lists.iter() {
if let Some(event_list_lock) = entry.1.upgrade() {
let mut event_list = event_list_lock.lock();
event_list.push_back(Event {
id: (entry.0).1,
flags: flags,
data: data
});
}
}
}
}

View file

@ -16,6 +16,9 @@ mod list;
/// Context switch function /// Context switch function
mod switch; mod switch;
/// Event handling
pub mod event;
/// File struct - defines a scheme and a file number /// File struct - defines a scheme and a file number
pub mod file; pub mod file;

View file

@ -1,11 +1,15 @@
use collections::VecDeque; use collections::VecDeque;
use core::str; use core::str;
use core::sync::atomic::{AtomicUsize, Ordering, ATOMIC_USIZE_INIT};
use spin::{Mutex, Once}; use spin::{Mutex, Once};
use context; use context;
use syscall::error::*; use syscall::error::*;
use syscall::flag::EVENT_READ;
use syscall::scheme::Scheme; use syscall::scheme::Scheme;
pub static DEBUG_SCHEME_ID: AtomicUsize = ATOMIC_USIZE_INIT;
/// Input /// Input
static INPUT: Once<Mutex<VecDeque<u8>>> = Once::new(); static INPUT: Once<Mutex<VecDeque<u8>>> = Once::new();
@ -17,7 +21,13 @@ fn init_input() -> Mutex<VecDeque<u8>> {
/// Get the global schemes list, const /// Get the global schemes list, const
#[no_mangle] #[no_mangle]
pub extern fn debug_input(b: u8) { pub extern fn debug_input(b: u8) {
INPUT.call_once(init_input).lock().push_back(b) let len = {
let mut input = INPUT.call_once(init_input).lock();
input.push_back(b);
input.len()
};
context::event::trigger(DEBUG_SCHEME_ID.load(Ordering::SeqCst), 0, EVENT_READ, len);
} }
pub struct DebugScheme; pub struct DebugScheme;
@ -62,6 +72,10 @@ impl Scheme for DebugScheme {
Ok(buffer.len()) Ok(buffer.len())
} }
fn fevent(&self, _file: usize, flags: usize) -> Result<usize> {
Ok(0)
}
fn fsync(&self, _file: usize) -> Result<usize> { fn fsync(&self, _file: usize) -> Result<usize> {
Ok(0) Ok(0)
} }

View file

@ -1,33 +1,94 @@
use core::{mem, str}; use alloc::arc::{Arc, Weak};
use collections::{BTreeMap, VecDeque};
use core::mem;
use core::sync::atomic::{AtomicUsize, Ordering};
use spin::{Mutex, RwLock};
use arch::interrupt::irq::{ACKS, COUNTS, acknowledge}; use context;
use syscall::data::Event;
use syscall::error::*; use syscall::error::*;
use syscall::scheme::Scheme; use syscall::scheme::Scheme;
pub struct EventScheme; pub struct EventScheme {
next_id: AtomicUsize,
handles: RwLock<BTreeMap<usize, Weak<Mutex<VecDeque<Event>>>>>
}
impl EventScheme {
pub fn new() -> EventScheme {
EventScheme {
next_id: AtomicUsize::new(0),
handles: RwLock::new(BTreeMap::new())
}
}
}
impl Scheme for EventScheme { impl Scheme for EventScheme {
fn open(&self, _path: &[u8], _flags: usize) -> Result<usize> { fn open(&self, _path: &[u8], _flags: usize) -> Result<usize> {
Ok( let handle = {
let contexts = context::contexts();
let context_lock = contexts.current().ok_or(Error::new(ESRCH))?;
let context = context_lock.read();
context.events.clone()
};
let id = self.next_id.fetch_add(1, Ordering::SeqCst);
self.handles.write().insert(id, Arc::downgrade(&handle));
Ok(id)
} }
fn dup(&self, file: usize) -> Result<usize> { fn dup(&self, id: usize) -> Result<usize> {
Ok(file) let handle = {
let handles = self.handles.read();
let handle_weak = handles.get(&id).ok_or(Error::new(EBADF))?;
handle_weak.upgrade().ok_or(Error::new(EBADF))?
};
let new_id = self.next_id.fetch_add(1, Ordering::SeqCst);
self.handles.write().insert(new_id, Arc::downgrade(&handle));
Ok(new_id)
} }
fn read(&self, file: usize, buffer: &mut [u8]) -> Result<usize> { fn read(&self, id: usize, buf: &mut [u8]) -> Result<usize> {
let handle = {
let handles = self.handles.read();
let handle_weak = handles.get(&id).ok_or(Error::new(EBADF))?;
handle_weak.upgrade().ok_or(Error::new(EBADF))?
};
let event_size = mem::size_of::<Event>();
let len = buf.len()/event_size;
if len > 0 {
loop {
let mut i = 0;
{
let mut events = handle.lock();
while ! events.is_empty() && i < len {
let event = events.pop_front().unwrap();
unsafe { *(buf.as_mut_ptr() as *mut Event).offset(i as isize) = event; }
i += 1;
}
}
if i > 0 {
return Ok(i * event_size);
} else {
unsafe { context::switch(); } //TODO: Block
}
}
} else {
Ok(0) Ok(0)
} }
fn write(&self, file: usize, buffer: &[u8]) -> Result<usize> {
Ok(0)
} }
fn fsync(&self, _file: usize) -> Result<usize> { fn fsync(&self, id: usize) -> Result<usize> {
Ok(0) let handles = self.handles.read();
let handle_weak = handles.get(&id).ok_or(Error::new(EBADF))?;
handle_weak.upgrade().ok_or(Error::new(EBADF)).and(Ok(0))
} }
fn close(&self, _file: usize) -> Result<usize> { fn close(&self, id: usize) -> Result<usize> {
Ok(0) self.handles.write().remove(&id).ok_or(Error::new(EBADF)).and(Ok(0))
} }
} }

View file

@ -8,15 +8,15 @@
use alloc::arc::Arc; use alloc::arc::Arc;
use alloc::boxed::Box; use alloc::boxed::Box;
use collections::BTreeMap; use collections::BTreeMap;
use core::sync::atomic::Ordering;
use spin::{Once, RwLock, RwLockReadGuard, RwLockWriteGuard}; use spin::{Once, RwLock, RwLockReadGuard, RwLockWriteGuard};
use syscall::error::*; use syscall::error::*;
use syscall::scheme::Scheme; use syscall::scheme::Scheme;
use self::debug::DebugScheme; use self::debug::{DEBUG_SCHEME_ID, DebugScheme};
use self::event::EventScheme;
use self::env::EnvScheme; use self::env::EnvScheme;
use self::initfs::InitFsScheme; use self::initfs::InitFsScheme;
use self::irq::IrqScheme; use self::irq::IrqScheme;
@ -25,6 +25,9 @@ use self::root::RootScheme;
/// Debug scheme /// Debug scheme
pub mod debug; pub mod debug;
/// Kernel events
pub mod event;
/// Environmental variables /// Environmental variables
pub mod env; pub mod env;
@ -74,7 +77,7 @@ impl SchemeList {
} }
/// Create a new scheme. /// Create a new scheme.
pub fn insert(&mut self, name: Box<[u8]>, scheme: Arc<Box<Scheme + Send + Sync>>) -> Result<&Arc<Box<Scheme + Send + Sync>>> { pub fn insert(&mut self, name: Box<[u8]>, scheme: Arc<Box<Scheme + Send + Sync>>) -> Result<usize> {
if self.names.contains_key(&name) { if self.names.contains_key(&name) {
return Err(Error::new(EEXIST)); return Err(Error::new(EEXIST));
} }
@ -97,7 +100,7 @@ impl SchemeList {
assert!(self.map.insert(id, scheme).is_none()); assert!(self.map.insert(id, scheme).is_none());
assert!(self.names.insert(name, id).is_none()); assert!(self.names.insert(name, id).is_none());
Ok(self.map.get(&id).expect("Failed to insert new scheme. ID is out of bounds.")) Ok(id)
} }
} }
@ -108,7 +111,8 @@ static SCHEMES: Once<RwLock<SchemeList>> = Once::new();
fn init_schemes() -> RwLock<SchemeList> { fn init_schemes() -> RwLock<SchemeList> {
let mut list: SchemeList = SchemeList::new(); let mut list: SchemeList = SchemeList::new();
list.insert(Box::new(*b""), Arc::new(Box::new(RootScheme::new()))).expect("failed to insert root scheme"); list.insert(Box::new(*b""), Arc::new(Box::new(RootScheme::new()))).expect("failed to insert root scheme");
list.insert(Box::new(*b"debug"), Arc::new(Box::new(DebugScheme))).expect("failed to insert debug scheme"); DEBUG_SCHEME_ID.store(list.insert(Box::new(*b"debug"), Arc::new(Box::new(DebugScheme))).expect("failed to insert debug scheme"), Ordering::SeqCst);
list.insert(Box::new(*b"event"), Arc::new(Box::new(EventScheme::new()))).expect("failed to insert event scheme");
list.insert(Box::new(*b"env"), Arc::new(Box::new(EnvScheme::new()))).expect("failed to insert env scheme"); list.insert(Box::new(*b"env"), Arc::new(Box::new(EnvScheme::new()))).expect("failed to insert env scheme");
list.insert(Box::new(*b"initfs"), Arc::new(Box::new(InitFsScheme::new()))).expect("failed to insert initfs scheme"); list.insert(Box::new(*b"initfs"), Arc::new(Box::new(InitFsScheme::new()))).expect("failed to insert initfs scheme");
list.insert(Box::new(*b"irq"), Arc::new(Box::new(IrqScheme))).expect("failed to insert irq scheme"); list.insert(Box::new(*b"irq"), Arc::new(Box::new(IrqScheme))).expect("failed to insert irq scheme");

View file

@ -38,7 +38,8 @@ impl Scheme for RootScheme {
return Err(Error::new(EEXIST)); return Err(Error::new(EEXIST));
} }
let inner = Arc::new(UserInner::new(context)); let inner = Arc::new(UserInner::new(context));
schemes.insert(path.to_vec().into_boxed_slice(), Arc::new(Box::new(UserScheme::new(Arc::downgrade(&inner))))).expect("failed to insert user scheme"); let id = schemes.insert(path.to_vec().into_boxed_slice(), Arc::new(Box::new(UserScheme::new(Arc::downgrade(&inner))))).expect("failed to insert user scheme");
inner.scheme_id.store(id, Ordering::SeqCst);
inner inner
}; };

View file

@ -15,6 +15,7 @@ use syscall::number::*;
use syscall::scheme::Scheme; use syscall::scheme::Scheme;
pub struct UserInner { pub struct UserInner {
pub scheme_id: AtomicUsize,
next_id: AtomicUsize, next_id: AtomicUsize,
context: Weak<RwLock<Context>>, context: Weak<RwLock<Context>>,
todo: Mutex<VecDeque<Packet>>, todo: Mutex<VecDeque<Packet>>,
@ -24,7 +25,8 @@ pub struct UserInner {
impl UserInner { impl UserInner {
pub fn new(context: Weak<RwLock<Context>>) -> UserInner { pub fn new(context: Weak<RwLock<Context>>) -> UserInner {
UserInner { UserInner {
next_id: AtomicUsize::new(0), scheme_id: AtomicUsize::new(0),
next_id: AtomicUsize::new(1),
context: context, context: context,
todo: Mutex::new(VecDeque::new()), todo: Mutex::new(VecDeque::new()),
done: Mutex::new(BTreeMap::new()) done: Mutex::new(BTreeMap::new())
@ -177,7 +179,14 @@ impl UserInner {
let mut i = 0; let mut i = 0;
while i < len { while i < len {
let packet = unsafe { *(buf.as_ptr() as *const Packet).offset(i as isize) }; let packet = unsafe { *(buf.as_ptr() as *const Packet).offset(i as isize) };
if packet.id == 0 {
match packet.a {
SYS_FEVENT => context::event::trigger(self.scheme_id.load(Ordering::SeqCst), packet.b, packet.c, packet.d),
_ => println!("Unknown scheme -> kernel message {}", packet.a)
}
} else {
self.done.lock().insert(packet.id, packet.a); self.done.lock().insert(packet.id, packet.a);
}
i += 1; i += 1;
} }

View file

@ -72,6 +72,8 @@ pub fn close(fd: usize) -> Result<usize> {
file file
}; };
context::event::unregister(fd, file.scheme, file.number);
let scheme = { let scheme = {
let schemes = scheme::schemes(); let schemes = scheme::schemes();
let scheme = schemes.get(file.scheme).ok_or(Error::new(EBADF))?; let scheme = schemes.get(file.scheme).ok_or(Error::new(EBADF))?;
@ -113,7 +115,9 @@ pub fn fevent(fd: usize, flags: usize) -> Result<usize> {
let scheme = schemes.get(file.scheme).ok_or(Error::new(EBADF))?; let scheme = schemes.get(file.scheme).ok_or(Error::new(EBADF))?;
scheme.clone() scheme.clone()
}; };
scheme.fevent(file.number, flags) scheme.fevent(file.number, flags)?;
context::event::register(fd, file.scheme, file.number);
Ok(0)
} }
/// Get the canonical path of the file /// Get the canonical path of the file

View file

@ -30,11 +30,17 @@ fn main(){
let a = syscall::open("display:", 0).unwrap(); let a = syscall::open("display:", 0).unwrap();
syscall::fevent(a, syscall::EVENT_READ).unwrap(); syscall::fevent(a, syscall::EVENT_READ).unwrap();
let b = syscall::open("debug:", 0).unwrap();
syscall::fevent(b, syscall::EVENT_READ).unwrap();
loop { loop {
let mut event = syscall::Event::default(); let mut event = syscall::Event::default();
syscall::read(events, &mut event).unwrap(); syscall::read(events, &mut event).unwrap();
println!("{:?}", event); println!("{:?}", event);
let mut buf = vec![0; event.data];
syscall::read(event.id, &mut buf).unwrap();
println!("{}", unsafe { ::std::str::from_utf8_unchecked(&buf) });
} }
let _ = syscall::close(events); let _ = syscall::close(events);

View file

@ -14,6 +14,7 @@ pub trait Scheme {
SYS_READ => self.read(packet.b, unsafe { slice::from_raw_parts_mut(packet.c as *mut u8, packet.d) }), SYS_READ => self.read(packet.b, unsafe { slice::from_raw_parts_mut(packet.c as *mut u8, packet.d) }),
SYS_WRITE => self.write(packet.b, unsafe { slice::from_raw_parts(packet.c as *const u8, packet.d) }), SYS_WRITE => self.write(packet.b, unsafe { slice::from_raw_parts(packet.c as *const u8, packet.d) }),
SYS_LSEEK => self.seek(packet.b, packet.c, packet.d), SYS_LSEEK => self.seek(packet.b, packet.c, packet.d),
SYS_FEVENT => self.fevent(packet.b, packet.c),
SYS_FPATH => self.fpath(packet.b, unsafe { slice::from_raw_parts_mut(packet.c as *mut u8, packet.d) }), SYS_FPATH => self.fpath(packet.b, unsafe { slice::from_raw_parts_mut(packet.c as *mut u8, packet.d) }),
SYS_FSTAT => self.fstat(packet.b, unsafe { &mut *(packet.c as *mut Stat) }), SYS_FSTAT => self.fstat(packet.b, unsafe { &mut *(packet.c as *mut Stat) }),
SYS_FSYNC => self.fsync(packet.b), SYS_FSYNC => self.fsync(packet.b),