Refactor context list
This commit is contained in:
		
							parent
							
								
									2de2d4cac4
								
							
						
					
					
						commit
						490dd16776
					
				
					 6 changed files with 89 additions and 34 deletions
				
			
		| 
						 | 
				
			
			@ -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();
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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<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
 | 
			
		||||
#[derive(Copy, Clone, Debug)]
 | 
			
		||||
#[derive(Clone, Debug)]
 | 
			
		||||
pub struct Context {
 | 
			
		||||
    /// The open files in the scheme
 | 
			
		||||
    pub files: [Option<file::File>; 32]
 | 
			
		||||
    pub files: Vec<Option<file::File>>
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        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
 | 
			
		||||
pub mod debug;
 | 
			
		||||
 | 
			
		||||
/// Scheme list type
 | 
			
		||||
pub type SchemeList = BTreeMap<Box<[u8]>, Arc<Mutex<Box<Scheme + Send>>>>;
 | 
			
		||||
 | 
			
		||||
/// Schemes list
 | 
			
		||||
static SCHEMES: Once<RwLock<SchemeList>> = Once::new();
 | 
			
		||||
 | 
			
		||||
/// Initialize schemes, called if needed
 | 
			
		||||
fn init_schemes() -> RwLock<SchemeList> {
 | 
			
		||||
    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()
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,5 +1,6 @@
 | 
			
		|||
//! Filesystem syscalls
 | 
			
		||||
 | 
			
		||||
use context;
 | 
			
		||||
use scheme;
 | 
			
		||||
 | 
			
		||||
use super::{Error, Result};
 | 
			
		||||
| 
						 | 
				
			
			@ -7,23 +8,33 @@ use super::{Error, Result};
 | 
			
		|||
/// Read syscall
 | 
			
		||||
pub fn read(fd: usize, buf: &mut [u8]) -> Result<usize> {
 | 
			
		||||
    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);
 | 
			
		||||
            Ok(0)
 | 
			
		||||
        } else {
 | 
			
		||||
            Err(Error::BadFile)
 | 
			
		||||
        }
 | 
			
		||||
    } else {
 | 
			
		||||
        Err(Error::NoProcess)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Write syscall
 | 
			
		||||
pub fn write(fd: usize, buf: &[u8]) -> Result<usize> {
 | 
			
		||||
    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));
 | 
			
		||||
            Ok(buf.len())
 | 
			
		||||
        } else {
 | 
			
		||||
            Err(Error::BadFile)
 | 
			
		||||
        }
 | 
			
		||||
    } else {
 | 
			
		||||
        Err(Error::NoProcess)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// 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,
 | 
			
		||||
            number: file
 | 
			
		||||
        }) {
 | 
			
		||||
| 
						 | 
				
			
			@ -54,6 +67,9 @@ pub fn open(path: &[u8], flags: usize) -> Result<usize> {
 | 
			
		|||
        } else {
 | 
			
		||||
            Err(Error::TooManyFiles)
 | 
			
		||||
        }
 | 
			
		||||
    } else {
 | 
			
		||||
        Err(Error::NoProcess)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Close syscall
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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<Error> for usize {
 | 
			
		|||
        match err {
 | 
			
		||||
            Error::NotPermitted => 1,
 | 
			
		||||
            Error::NoEntry => 2,
 | 
			
		||||
            Error::NoProcess => 3,
 | 
			
		||||
            Error::BadFile => 9,
 | 
			
		||||
            Error::InvalidValue => 22,
 | 
			
		||||
            Error::TooManyFiles => 24,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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() {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue