Lazy static init of schemes

This commit is contained in:
Jeremy Soller 2016-08-16 11:04:14 -06:00
parent 7a1c263bc1
commit d383cfb595
4 changed files with 40 additions and 8 deletions

View file

@ -9,6 +9,8 @@ crate-type = ["staticlib"]
[dependencies] [dependencies]
bitflags = "*" bitflags = "*"
lazy_static = "*"
spin = "*"
[dev-dependencies] [dev-dependencies]
arch_test = { path = "arch/test" } arch_test = { path = "arch/test" }

View file

@ -70,9 +70,6 @@
#![feature(question_mark)] #![feature(question_mark)]
#![no_std] #![no_std]
#[macro_use]
extern crate bitflags;
use arch::interrupt::{enable_interrupts, halt}; use arch::interrupt::{enable_interrupts, halt};
/// Architecture specific items (test) /// Architecture specific items (test)
@ -89,6 +86,12 @@ extern crate alloc;
#[macro_use] #[macro_use]
extern crate collections; extern crate collections;
#[macro_use]
extern crate bitflags;
#[macro_use]
extern crate lazy_static;
extern crate spin;
/// Context management /// Context management
pub mod context; pub mod context;

View file

@ -6,6 +6,13 @@
//! The kernel validates paths and file descriptors before they are passed to schemes, //! The kernel validates paths and file descriptors before they are passed to schemes,
//! also stripping the scheme identifier of paths if necessary. //! also stripping the scheme identifier of paths if necessary.
use alloc::arc::Arc;
use alloc::boxed::Box;
use collections::BTreeMap;
use spin::{Mutex, RwLock};
use syscall::Result; use syscall::Result;
use self::debug::DebugScheme; use self::debug::DebugScheme;
@ -14,7 +21,13 @@ use self::debug::DebugScheme;
pub mod debug; pub mod debug;
/// Schemes list /// Schemes list
pub static mut SCHEME: DebugScheme = DebugScheme; lazy_static! {
pub static ref SCHEMES: RwLock<BTreeMap<Box<[u8]>, Arc<Mutex<Box<Scheme + Send>>>>> = {
let mut map: BTreeMap<Box<[u8]>, Arc<Mutex<Box<Scheme + Send>>>> = BTreeMap::new();
map.insert(Box::new(*b"debug"), Arc::new(Mutex::new(Box::new(DebugScheme))));
RwLock::new(map)
};
}
/// A scheme trait, implemented by a scheme handler /// A scheme trait, implemented by a scheme handler
pub trait Scheme { pub trait Scheme {

View file

@ -1,7 +1,5 @@
//! Filesystem syscalls //! Filesystem syscalls
use scheme::Scheme;
use super::{Error, Result}; use super::{Error, Result};
/// Read syscall /// Read syscall
@ -28,8 +26,24 @@ pub fn write(fd: usize, buf: &[u8]) -> Result<usize> {
/// Open syscall /// Open syscall
pub fn open(path: &[u8], flags: usize) -> Result<usize> { pub fn open(path: &[u8], flags: usize) -> Result<usize> {
println!("Open {:?}: {:X}", ::core::str::from_utf8(path), flags); let mut parts = path.splitn(2, |&b| b == b':');
let file = unsafe { &mut ::scheme::SCHEME }.open(path, flags)?; let namespace_opt = parts.next();
let reference_opt = parts.next();
println!("Open namespace {:?} reference {:?}: {:X}", namespace_opt.map(::core::str::from_utf8), reference_opt.map(::core::str::from_utf8), flags);
let file = {
if let Some(namespace) = namespace_opt {
let schemes = ::scheme::SCHEMES.read();
if let Some(scheme_mutex) = schemes.get(namespace) {
scheme_mutex.lock().open(reference_opt.unwrap_or(b""), flags)
} else {
Err(Error::NoEntry)
}
} else {
Err(Error::NoEntry)
}
}?;
if let Some(fd) = unsafe { &mut ::context::CONTEXT }.add_file(::context::file::File { if let Some(fd) = unsafe { &mut ::context::CONTEXT }.add_file(::context::file::File {
scheme: 0, scheme: 0,
number: file number: file