Refactor context list
This commit is contained in:
parent
2de2d4cac4
commit
490dd16776
|
@ -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();
|
||||||
|
}
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
None
|
let len = self.files.len();
|
||||||
|
if len < CONTEXT_MAX_FILES {
|
||||||
|
self.files.push(Some(file));
|
||||||
|
Some(len)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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()
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
//! Filesystem syscalls
|
//! Filesystem syscalls
|
||||||
|
|
||||||
|
use context;
|
||||||
use scheme;
|
use scheme;
|
||||||
|
|
||||||
use super::{Error, Result};
|
use super::{Error, Result};
|
||||||
|
@ -7,22 +8,32 @@ 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) {
|
||||||
println!("{:?}", file);
|
let context = context_lock.read();
|
||||||
Ok(0)
|
if let Some(file) = context.files.get(fd) {
|
||||||
|
println!("{:?}", file);
|
||||||
|
Ok(0)
|
||||||
|
} else {
|
||||||
|
Err(Error::BadFile)
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
Err(Error::BadFile)
|
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) {
|
||||||
println!("{:?}: {:?}", file, ::core::str::from_utf8(buf));
|
let context = context_lock.read();
|
||||||
Ok(buf.len())
|
if let Some(file) = context.files.get(fd) {
|
||||||
|
println!("{:?}: {:?}", file, ::core::str::from_utf8(buf));
|
||||||
|
Ok(buf.len())
|
||||||
|
} else {
|
||||||
|
Err(Error::BadFile)
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
Err(Error::BadFile)
|
Err(Error::NoProcess)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -46,13 +57,18 @@ 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) {
|
||||||
scheme: 0,
|
let mut context = context_lock.write();
|
||||||
number: file
|
if let Some(fd) = context.add_file(::context::file::File {
|
||||||
}) {
|
scheme: 0,
|
||||||
Ok(fd)
|
number: file
|
||||||
|
}) {
|
||||||
|
Ok(fd)
|
||||||
|
} else {
|
||||||
|
Err(Error::TooManyFiles)
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
Err(Error::TooManyFiles)
|
Err(Error::NoProcess)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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() {
|
||||||
|
|
Loading…
Reference in a new issue