Refactor context list

This commit is contained in:
Jeremy Soller 2016-08-18 08:30:45 -06:00
parent 2de2d4cac4
commit 490dd16776
6 changed files with 89 additions and 34 deletions

View file

@ -4,14 +4,14 @@ static mut INTERRUPTS_ENABLED: bool = false;
/// Clear interrupts /// Clear interrupts
#[inline(always)] #[inline(always)]
pub unsafe fn disable_interrupts() { pub unsafe fn disable() {
println!("CLEAR INTERRUPTS"); println!("CLEAR INTERRUPTS");
INTERRUPTS_ENABLED = false; INTERRUPTS_ENABLED = false;
} }
/// Set interrupts /// Set interrupts
#[inline(always)] #[inline(always)]
pub unsafe fn enable_interrupts() { pub unsafe fn enable() {
println!("SET INTERRUPTS"); println!("SET INTERRUPTS");
INTERRUPTS_ENABLED = true; INTERRUPTS_ENABLED = true;
} }
@ -22,3 +22,10 @@ pub unsafe fn halt() {
assert!(INTERRUPTS_ENABLED); assert!(INTERRUPTS_ENABLED);
::std::thread::yield_now(); ::std::thread::yield_now();
} }
/// Set interrupts and halt
#[inline(always)]
pub unsafe fn enable_and_halt() {
enable();
halt();
}

View file

@ -1,22 +1,52 @@
//! Context management //! Context management
use alloc::arc::Arc;
use collections::{BTreeMap, Vec};
use spin::{Once, RwLock, RwLockReadGuard, RwLockWriteGuard};
/// File operations /// File operations
pub mod file; pub mod file;
/// Context list /// Maximum context files
pub static mut CONTEXT: Context = Context::new(); pub const CONTEXT_MAX_FILES: usize = 65536;
/// Context ID
pub type ContextId = u16;
/// Context list type
pub type ContextList = BTreeMap<ContextId, Arc<RwLock<Context>>>;
/// Contexts list
static CONTEXTS: Once<RwLock<ContextList>> = Once::new();
/// Initialize contexts, called if needed
fn init_contexts() -> RwLock<ContextList> {
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 /// A context, which identifies either a process or a thread
#[derive(Copy, Clone, Debug)] #[derive(Clone, Debug)]
pub struct Context { pub struct Context {
/// The open files in the scheme /// The open files in the scheme
pub files: [Option<file::File>; 32] pub files: Vec<Option<file::File>>
} }
impl Context { impl Context {
pub const fn new() -> Context { pub fn new() -> Context {
Context { Context {
files: [None; 32] files: Vec::new()
} }
} }
@ -29,6 +59,12 @@ impl Context {
return Some(i); return Some(i);
} }
} }
let len = self.files.len();
if len < CONTEXT_MAX_FILES {
self.files.push(Some(file));
Some(len)
} else {
None None
} }
}
} }

View file

@ -20,21 +20,25 @@ use self::debug::DebugScheme;
/// Debug scheme /// Debug scheme
pub mod debug; pub mod debug;
/// Scheme list type
pub type SchemeList = BTreeMap<Box<[u8]>, Arc<Mutex<Box<Scheme + Send>>>>; pub type SchemeList = BTreeMap<Box<[u8]>, Arc<Mutex<Box<Scheme + Send>>>>;
/// Schemes list /// Schemes list
static SCHEMES: Once<RwLock<SchemeList>> = Once::new(); static SCHEMES: Once<RwLock<SchemeList>> = Once::new();
/// Initialize schemes, called if needed
fn init_schemes() -> RwLock<SchemeList> { fn init_schemes() -> RwLock<SchemeList> {
let mut map: SchemeList = BTreeMap::new(); let mut map: SchemeList = BTreeMap::new();
map.insert(Box::new(*b"debug"), Arc::new(Mutex::new(Box::new(DebugScheme)))); map.insert(Box::new(*b"debug"), Arc::new(Mutex::new(Box::new(DebugScheme))));
RwLock::new(map) RwLock::new(map)
} }
/// Get the global schemes list, const
pub fn schemes() -> RwLockReadGuard<'static, SchemeList> { pub fn schemes() -> RwLockReadGuard<'static, SchemeList> {
SCHEMES.call_once(init_schemes).read() SCHEMES.call_once(init_schemes).read()
} }
/// Get the global schemes list, mutable
pub fn schemes_mut() -> RwLockWriteGuard<'static, SchemeList> { pub fn schemes_mut() -> RwLockWriteGuard<'static, SchemeList> {
SCHEMES.call_once(init_schemes).write() SCHEMES.call_once(init_schemes).write()
} }

View file

@ -1,5 +1,6 @@
//! Filesystem syscalls //! Filesystem syscalls
use context;
use scheme; use scheme;
use super::{Error, Result}; use super::{Error, Result};
@ -7,23 +8,33 @@ use super::{Error, Result};
/// Read syscall /// Read syscall
pub fn read(fd: usize, buf: &mut [u8]) -> Result<usize> { pub fn read(fd: usize, buf: &mut [u8]) -> Result<usize> {
println!("Read {}: {}", fd, buf.len()); println!("Read {}: {}", fd, buf.len());
if let Some(file) = unsafe { &mut ::context::CONTEXT }.files.get(fd) { if let Some(context_lock) = context::contexts().get(&0) {
let context = context_lock.read();
if let Some(file) = context.files.get(fd) {
println!("{:?}", file); println!("{:?}", file);
Ok(0) Ok(0)
} else { } else {
Err(Error::BadFile) Err(Error::BadFile)
} }
} else {
Err(Error::NoProcess)
}
} }
/// Write syscall /// Write syscall
pub fn write(fd: usize, buf: &[u8]) -> Result<usize> { pub fn write(fd: usize, buf: &[u8]) -> Result<usize> {
println!("Write {}: {}", fd, buf.len()); println!("Write {}: {}", fd, buf.len());
if let Some(file) = unsafe { &mut ::context::CONTEXT }.files.get(fd) { 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)); println!("{:?}: {:?}", file, ::core::str::from_utf8(buf));
Ok(buf.len()) Ok(buf.len())
} else { } else {
Err(Error::BadFile) Err(Error::BadFile)
} }
} else {
Err(Error::NoProcess)
}
} }
/// Open syscall /// Open syscall
@ -46,7 +57,9 @@ pub fn open(path: &[u8], flags: usize) -> Result<usize> {
} }
}?; }?;
if let Some(fd) = unsafe { &mut ::context::CONTEXT }.add_file(::context::file::File { 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, scheme: 0,
number: file number: file
}) { }) {
@ -54,6 +67,9 @@ pub fn open(path: &[u8], flags: usize) -> Result<usize> {
} else { } else {
Err(Error::TooManyFiles) Err(Error::TooManyFiles)
} }
} else {
Err(Error::NoProcess)
}
} }
/// Close syscall /// Close syscall

View file

@ -53,6 +53,8 @@ pub enum Error {
NotPermitted, NotPermitted,
/// No such file or directory /// No such file or directory
NoEntry, NoEntry,
/// No such process
NoProcess,
/// Bad file number /// Bad file number
BadFile, BadFile,
/// Invalid argument /// Invalid argument
@ -70,6 +72,7 @@ impl From<Error> for usize {
match err { match err {
Error::NotPermitted => 1, Error::NotPermitted => 1,
Error::NoEntry => 2, Error::NoEntry => 2,
Error::NoProcess => 3,
Error::BadFile => 9, Error::BadFile => 9,
Error::InvalidValue => 22, Error::InvalidValue => 22,
Error::TooManyFiles => 24, Error::TooManyFiles => 24,

View file

@ -1,16 +1,5 @@
use arch::interrupt::{enable_interrupts, halt};
use syscall::{self, Error}; use syscall::{self, Error};
/// Test halting
#[test]
fn halt_with_interrupts() {
unsafe {
//enable_interrupts();
//halt();
}
}
/// Test stdio /// Test stdio
#[test] #[test]
fn stdio() { fn stdio() {