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

@ -1,11 +1,15 @@
use collections::VecDeque;
use core::str;
use core::sync::atomic::{AtomicUsize, Ordering, ATOMIC_USIZE_INIT};
use spin::{Mutex, Once};
use context;
use syscall::error::*;
use syscall::flag::EVENT_READ;
use syscall::scheme::Scheme;
pub static DEBUG_SCHEME_ID: AtomicUsize = ATOMIC_USIZE_INIT;
/// Input
static INPUT: Once<Mutex<VecDeque<u8>>> = Once::new();
@ -17,7 +21,13 @@ fn init_input() -> Mutex<VecDeque<u8>> {
/// Get the global schemes list, const
#[no_mangle]
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;
@ -62,6 +72,10 @@ impl Scheme for DebugScheme {
Ok(buffer.len())
}
fn fevent(&self, _file: usize, flags: usize) -> Result<usize> {
Ok(0)
}
fn fsync(&self, _file: usize) -> Result<usize> {
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::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 {
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> {
Ok(file)
fn dup(&self, id: usize) -> 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 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> {
Ok(0)
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)
}
}
fn write(&self, file: usize, buffer: &[u8]) -> Result<usize> {
Ok(0)
fn fsync(&self, id: usize) -> Result<usize> {
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 fsync(&self, _file: usize) -> Result<usize> {
Ok(0)
}
fn close(&self, _file: usize) -> Result<usize> {
Ok(0)
fn close(&self, id: usize) -> Result<usize> {
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::boxed::Box;
use collections::BTreeMap;
use core::sync::atomic::Ordering;
use spin::{Once, RwLock, RwLockReadGuard, RwLockWriteGuard};
use syscall::error::*;
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::initfs::InitFsScheme;
use self::irq::IrqScheme;
@ -25,6 +25,9 @@ use self::root::RootScheme;
/// Debug scheme
pub mod debug;
/// Kernel events
pub mod event;
/// Environmental variables
pub mod env;
@ -74,7 +77,7 @@ impl SchemeList {
}
/// 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) {
return Err(Error::new(EEXIST));
}
@ -97,7 +100,7 @@ impl SchemeList {
assert!(self.map.insert(id, scheme).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> {
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"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"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");

View file

@ -38,7 +38,8 @@ impl Scheme for RootScheme {
return Err(Error::new(EEXIST));
}
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
};

View file

@ -15,6 +15,7 @@ use syscall::number::*;
use syscall::scheme::Scheme;
pub struct UserInner {
pub scheme_id: AtomicUsize,
next_id: AtomicUsize,
context: Weak<RwLock<Context>>,
todo: Mutex<VecDeque<Packet>>,
@ -24,7 +25,8 @@ pub struct UserInner {
impl UserInner {
pub fn new(context: Weak<RwLock<Context>>) -> UserInner {
UserInner {
next_id: AtomicUsize::new(0),
scheme_id: AtomicUsize::new(0),
next_id: AtomicUsize::new(1),
context: context,
todo: Mutex::new(VecDeque::new()),
done: Mutex::new(BTreeMap::new())
@ -177,7 +179,14 @@ impl UserInner {
let mut i = 0;
while i < len {
let packet = unsafe { *(buf.as_ptr() as *const Packet).offset(i as isize) };
self.done.lock().insert(packet.id, packet.a);
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);
}
i += 1;
}