diff --git a/arch/test/src/interrupt.rs b/arch/test/src/interrupt.rs index ffe24cc..723490d 100644 --- a/arch/test/src/interrupt.rs +++ b/arch/test/src/interrupt.rs @@ -4,14 +4,14 @@ static mut INTERRUPTS_ENABLED: bool = false; /// Clear interrupts #[inline(always)] -pub unsafe fn disable_interrupts() { +pub unsafe fn disable() { println!("CLEAR INTERRUPTS"); INTERRUPTS_ENABLED = false; } /// Set interrupts #[inline(always)] -pub unsafe fn enable_interrupts() { +pub unsafe fn enable() { println!("SET INTERRUPTS"); INTERRUPTS_ENABLED = true; } @@ -22,3 +22,10 @@ pub unsafe fn halt() { assert!(INTERRUPTS_ENABLED); ::std::thread::yield_now(); } + +/// Set interrupts and halt +#[inline(always)] +pub unsafe fn enable_and_halt() { + enable(); + halt(); +} diff --git a/kernel/context/mod.rs b/kernel/context/mod.rs index 8e4f37d..1dde2eb 100644 --- a/kernel/context/mod.rs +++ b/kernel/context/mod.rs @@ -1,22 +1,52 @@ //! Context management +use alloc::arc::Arc; +use collections::{BTreeMap, Vec}; +use spin::{Once, RwLock, RwLockReadGuard, RwLockWriteGuard}; + /// File operations pub mod file; -/// Context list -pub static mut CONTEXT: Context = Context::new(); +/// Maximum context files +pub const CONTEXT_MAX_FILES: usize = 65536; + +/// Context ID +pub type ContextId = u16; + +/// Context list type +pub type ContextList = BTreeMap>>; + +/// Contexts list +static CONTEXTS: Once> = Once::new(); + +/// Initialize contexts, called if needed +fn init_contexts() -> RwLock { + let mut map: ContextList = BTreeMap::new(); + map.insert(0, Arc::new(RwLock::new(Context::new()))); + RwLock::new(map) +} + +/// Get the global schemes list, const +pub fn contexts() -> RwLockReadGuard<'static, ContextList> { + CONTEXTS.call_once(init_contexts).read() +} + +/// Get the global schemes list, mutable +pub fn contexts_mut() -> RwLockWriteGuard<'static, ContextList> { + CONTEXTS.call_once(init_contexts).write() +} /// A context, which identifies either a process or a thread -#[derive(Copy, Clone, Debug)] +#[derive(Clone, Debug)] pub struct Context { /// The open files in the scheme - pub files: [Option; 32] + pub files: Vec> } impl Context { - pub const fn new() -> Context { + pub fn new() -> Context { Context { - files: [None; 32] + files: Vec::new() } } @@ -29,6 +59,12 @@ impl Context { return Some(i); } } - None + let len = self.files.len(); + if len < CONTEXT_MAX_FILES { + self.files.push(Some(file)); + Some(len) + } else { + None + } } } diff --git a/kernel/scheme/mod.rs b/kernel/scheme/mod.rs index 75b3eb6..d01931c 100644 --- a/kernel/scheme/mod.rs +++ b/kernel/scheme/mod.rs @@ -20,21 +20,25 @@ use self::debug::DebugScheme; /// Debug scheme pub mod debug; +/// Scheme list type pub type SchemeList = BTreeMap, Arc>>>; /// Schemes list static SCHEMES: Once> = Once::new(); +/// Initialize schemes, called if needed fn init_schemes() -> RwLock { let mut map: SchemeList = BTreeMap::new(); map.insert(Box::new(*b"debug"), Arc::new(Mutex::new(Box::new(DebugScheme)))); RwLock::new(map) } +/// Get the global schemes list, const pub fn schemes() -> RwLockReadGuard<'static, SchemeList> { SCHEMES.call_once(init_schemes).read() } +/// Get the global schemes list, mutable pub fn schemes_mut() -> RwLockWriteGuard<'static, SchemeList> { SCHEMES.call_once(init_schemes).write() } diff --git a/kernel/syscall/fs.rs b/kernel/syscall/fs.rs index 2ded858..e0e4a64 100644 --- a/kernel/syscall/fs.rs +++ b/kernel/syscall/fs.rs @@ -1,5 +1,6 @@ //! Filesystem syscalls +use context; use scheme; use super::{Error, Result}; @@ -7,22 +8,32 @@ use super::{Error, Result}; /// Read syscall pub fn read(fd: usize, buf: &mut [u8]) -> Result { println!("Read {}: {}", fd, buf.len()); - if let Some(file) = unsafe { &mut ::context::CONTEXT }.files.get(fd) { - println!("{:?}", file); - Ok(0) + if let Some(context_lock) = context::contexts().get(&0) { + let context = context_lock.read(); + if let Some(file) = context.files.get(fd) { + println!("{:?}", file); + Ok(0) + } else { + Err(Error::BadFile) + } } else { - Err(Error::BadFile) + Err(Error::NoProcess) } } /// Write syscall pub fn write(fd: usize, buf: &[u8]) -> Result { println!("Write {}: {}", fd, buf.len()); - if let Some(file) = unsafe { &mut ::context::CONTEXT }.files.get(fd) { - println!("{:?}: {:?}", file, ::core::str::from_utf8(buf)); - Ok(buf.len()) + if let Some(context_lock) = context::contexts().get(&0) { + let context = context_lock.read(); + if let Some(file) = context.files.get(fd) { + println!("{:?}: {:?}", file, ::core::str::from_utf8(buf)); + Ok(buf.len()) + } else { + Err(Error::BadFile) + } } else { - Err(Error::BadFile) + Err(Error::NoProcess) } } @@ -46,13 +57,18 @@ pub fn open(path: &[u8], flags: usize) -> Result { } }?; - if let Some(fd) = unsafe { &mut ::context::CONTEXT }.add_file(::context::file::File { - scheme: 0, - number: file - }) { - Ok(fd) + if let Some(context_lock) = context::contexts().get(&0) { + let mut context = context_lock.write(); + if let Some(fd) = context.add_file(::context::file::File { + scheme: 0, + number: file + }) { + Ok(fd) + } else { + Err(Error::TooManyFiles) + } } else { - Err(Error::TooManyFiles) + Err(Error::NoProcess) } } diff --git a/kernel/syscall/mod.rs b/kernel/syscall/mod.rs index 1cf0f58..df9b6d3 100644 --- a/kernel/syscall/mod.rs +++ b/kernel/syscall/mod.rs @@ -53,6 +53,8 @@ pub enum Error { NotPermitted, /// No such file or directory NoEntry, + /// No such process + NoProcess, /// Bad file number BadFile, /// Invalid argument @@ -70,6 +72,7 @@ impl From for usize { match err { Error::NotPermitted => 1, Error::NoEntry => 2, + Error::NoProcess => 3, Error::BadFile => 9, Error::InvalidValue => 22, Error::TooManyFiles => 24, diff --git a/kernel/tests/mod.rs b/kernel/tests/mod.rs index 67e13c9..3b92c18 100644 --- a/kernel/tests/mod.rs +++ b/kernel/tests/mod.rs @@ -1,16 +1,5 @@ -use arch::interrupt::{enable_interrupts, halt}; - use syscall::{self, Error}; -/// Test halting -#[test] -fn halt_with_interrupts() { - unsafe { - //enable_interrupts(); - //halt(); - } -} - /// Test stdio #[test] fn stdio() {