Add fsync. Add env scheme, currently hardcoded to get ion to launch. Make serial IRQ send data to debug scheme

This commit is contained in:
Jeremy Soller 2016-09-18 17:55:35 -06:00
parent 1b056395bb
commit 483d466b1a
8 changed files with 164 additions and 4 deletions

View file

@ -102,7 +102,12 @@ impl SerialPort {
pub fn on_receive(&mut self) { pub fn on_receive(&mut self) {
let data = self.data.read(); let data = self.data.read();
self.write_translate(data);
extern {
fn debug_input(byte: u8);
}
unsafe { debug_input(data) };
} }
} }

View file

@ -1,8 +1,25 @@
use collections::VecDeque;
use core::str; use core::str;
use spin::{Mutex, MutexGuard, Once};
use context;
use syscall::Result; use syscall::Result;
use super::Scheme; use super::Scheme;
/// Input
static INPUT: Once<Mutex<VecDeque<u8>>> = Once::new();
/// Initialize contexts, called if needed
fn init_input() -> Mutex<VecDeque<u8>> {
Mutex::new(VecDeque::new())
}
/// Get the global schemes list, const
#[no_mangle]
pub extern fn debug_input(b: u8) {
INPUT.call_once(init_input).lock().push_back(b)
}
pub struct DebugScheme; pub struct DebugScheme;
impl Scheme for DebugScheme { impl Scheme for DebugScheme {
@ -17,8 +34,23 @@ impl Scheme for DebugScheme {
/// Read the file `number` into the `buffer` /// Read the file `number` into the `buffer`
/// ///
/// Returns the number of bytes read /// Returns the number of bytes read
fn read(&mut self, _file: usize, _buffer: &mut [u8]) -> Result<usize> { fn read(&mut self, _file: usize, buf: &mut [u8]) -> Result<usize> {
Ok(0) loop {
let mut i = 0;
{
let mut input = INPUT.call_once(init_input).lock();
while i < buf.len() && ! input.is_empty() {
buf[i] = input.pop_front().expect("debug_input lost byte");
i += 1;
}
}
if i > 0 {
return Ok(i);
} else {
unsafe { context::switch(); }
}
}
} }
/// Write the `buffer` to the `file` /// Write the `buffer` to the `file`
@ -30,6 +62,10 @@ impl Scheme for DebugScheme {
Ok(buffer.len()) Ok(buffer.len())
} }
fn fsync(&mut self, file: usize) -> Result<()> {
Ok(())
}
/// Close the file `number` /// Close the file `number`
fn close(&mut self, _file: usize) -> Result<()> { fn close(&mut self, _file: usize) -> Result<()> {
Ok(()) Ok(())

88
kernel/scheme/env.rs Normal file
View file

@ -0,0 +1,88 @@
use collections::BTreeMap;
use syscall::{Error, Result};
use super::Scheme;
struct Handle {
data: &'static [u8],
seek: usize
}
pub struct EnvScheme {
next_id: usize,
files: BTreeMap<&'static [u8], &'static [u8]>,
handles: BTreeMap<usize, Handle>
}
impl EnvScheme {
pub fn new() -> EnvScheme {
let mut files: BTreeMap<&'static [u8], &'static [u8]> = BTreeMap::new();
files.insert(b"HOME", b"initfs:");
files.insert(b"PWD", b"initfs:");
files.insert(b"COLUMNS", b"80");
files.insert(b"LINES", b"30");
EnvScheme {
next_id: 0,
files: files,
handles: BTreeMap::new()
}
}
}
impl Scheme for EnvScheme {
fn open(&mut self, path: &[u8], _flags: usize) -> Result<usize> {
let data = self.files.get(path).ok_or(Error::NoEntry)?;
let id = self.next_id;
self.next_id += 1;
self.handles.insert(id, Handle {
data: data,
seek: 0
});
Ok(id)
}
fn dup(&mut self, file: usize) -> Result<usize> {
let (data, seek) = {
let handle = self.handles.get(&file).ok_or(Error::BadFile)?;
(handle.data, handle.seek)
};
let id = self.next_id;
self.next_id += 1;
self.handles.insert(id, Handle {
data: data,
seek: seek
});
Ok(id)
}
fn read(&mut self, file: usize, buffer: &mut [u8]) -> Result<usize> {
let mut handle = self.handles.get_mut(&file).ok_or(Error::BadFile)?;
let mut i = 0;
while i < buffer.len() && handle.seek < handle.data.len() {
buffer[i] = handle.data[handle.seek];
i += 1;
handle.seek += 1;
}
Ok(i)
}
fn write(&mut self, _file: usize, _buffer: &[u8]) -> Result<usize> {
Err(Error::NotPermitted)
}
fn fsync(&mut self, file: usize) -> Result<()> {
Ok(())
}
fn close(&mut self, file: usize) -> Result<()> {
self.handles.remove(&file).ok_or(Error::BadFile).and(Ok(()))
}
}

View file

@ -78,6 +78,10 @@ impl Scheme for InitFsScheme {
Err(Error::NotPermitted) Err(Error::NotPermitted)
} }
fn fsync(&mut self, file: usize) -> Result<()> {
Ok(())
}
fn close(&mut self, file: usize) -> Result<()> { fn close(&mut self, file: usize) -> Result<()> {
self.handles.remove(&file).ok_or(Error::BadFile).and(Ok(())) self.handles.remove(&file).ok_or(Error::BadFile).and(Ok(()))
} }

View file

@ -16,11 +16,15 @@ use spin::{Once, Mutex, RwLock, RwLockReadGuard, RwLockWriteGuard};
use syscall::{Error, Result}; use syscall::{Error, Result};
use self::debug::DebugScheme; use self::debug::DebugScheme;
use self::env::EnvScheme;
use self::initfs::InitFsScheme; use self::initfs::InitFsScheme;
/// Debug scheme /// Debug scheme
pub mod debug; pub mod debug;
/// Environmental variables
pub mod env;
/// InitFS scheme /// InitFS scheme
pub mod initfs; pub mod initfs;
@ -57,7 +61,7 @@ impl SchemeList {
} }
} }
/// Create a new context. /// Create a new scheme.
pub fn insert(&mut self, name: Box<[u8]>, scheme: Arc<Mutex<Box<Scheme + Send>>>) -> Result<&Arc<Mutex<Box<Scheme + Send>>>> { pub fn insert(&mut self, name: Box<[u8]>, scheme: Arc<Mutex<Box<Scheme + Send>>>) -> Result<&Arc<Mutex<Box<Scheme + Send>>>> {
if self.names.contains_key(&name) { if self.names.contains_key(&name) {
return Err(Error::FileExists); return Err(Error::FileExists);
@ -92,6 +96,7 @@ static SCHEMES: Once<RwLock<SchemeList>> = Once::new();
fn init_schemes() -> RwLock<SchemeList> { fn init_schemes() -> RwLock<SchemeList> {
let mut list: SchemeList = SchemeList::new(); let mut list: SchemeList = SchemeList::new();
list.insert(Box::new(*b"debug"), Arc::new(Mutex::new(Box::new(DebugScheme)))).expect("failed to insert debug: scheme"); list.insert(Box::new(*b"debug"), Arc::new(Mutex::new(Box::new(DebugScheme)))).expect("failed to insert debug: scheme");
list.insert(Box::new(*b"env"), Arc::new(Mutex::new(Box::new(EnvScheme::new())))).expect("failed to insert env: scheme");
list.insert(Box::new(*b"initfs"), Arc::new(Mutex::new(Box::new(InitFsScheme::new())))).expect("failed to insert initfs: scheme"); list.insert(Box::new(*b"initfs"), Arc::new(Mutex::new(Box::new(InitFsScheme::new())))).expect("failed to insert initfs: scheme");
RwLock::new(list) RwLock::new(list)
} }
@ -128,6 +133,9 @@ pub trait Scheme {
/// Returns the number of bytes written /// Returns the number of bytes written
fn write(&mut self, file: usize, buffer: &[u8]) -> Result<usize>; fn write(&mut self, file: usize, buffer: &[u8]) -> Result<usize>;
/// Sync the file descriptor
fn fsync(&mut self, file: usize) -> Result<()>;
/// Close the file descriptor /// Close the file descriptor
fn close(&mut self, file: usize) -> Result<()>; fn close(&mut self, file: usize) -> Result<()>;
} }

View file

@ -29,6 +29,8 @@ pub enum Call {
Brk = 45, Brk = 45,
/// Set process I/O privilege level /// Set process I/O privilege level
Iopl = 110, Iopl = 110,
/// Sync file descriptor
FSync = 118,
/// Clone process /// Clone process
Clone = 120, Clone = 120,
/// Yield to scheduler /// Yield to scheduler
@ -55,6 +57,7 @@ impl Call {
41 => Ok(Call::Dup), 41 => Ok(Call::Dup),
45 => Ok(Call::Brk), 45 => Ok(Call::Brk),
110 => Ok(Call::Iopl), 110 => Ok(Call::Iopl),
118 => Ok(Call::FSync),
120 => Ok(Call::Clone), 120 => Ok(Call::Clone),
158 => Ok(Call::SchedYield), 158 => Ok(Call::SchedYield),
183 => Ok(Call::GetCwd), 183 => Ok(Call::GetCwd),

View file

@ -120,3 +120,18 @@ pub fn dup(fd: usize) -> Result<usize> {
let result = scheme_mutex.lock().dup(file.number); let result = scheme_mutex.lock().dup(file.number);
result result
} }
pub fn fsync(fd: usize) -> Result<usize> {
let file = {
let contexts = context::contexts();
let context_lock = contexts.current().ok_or(Error::NoProcess)?;
let context = context_lock.read();
let file = context.get_file(fd).ok_or(Error::BadFile)?;
file
};
let schemes = scheme::schemes();
let scheme_mutex = schemes.get(file.scheme).ok_or(Error::BadFile)?;
let result = scheme_mutex.lock().fsync(file.number).and(Ok(0));
result
}

View file

@ -39,6 +39,7 @@ pub extern fn syscall(a: usize, b: usize, c: usize, d: usize, e: usize, f: usize
Call::Dup => dup(b), Call::Dup => dup(b),
Call::Brk => brk(b), Call::Brk => brk(b),
Call::Iopl => iopl(b), Call::Iopl => iopl(b),
Call::FSync => fsync(b),
Call::Clone => clone(b, stack), Call::Clone => clone(b, stack),
Call::SchedYield => sched_yield(), Call::SchedYield => sched_yield(),
Call::GetCwd => getcwd(validate_slice_mut(b as *mut u8, c)?) Call::GetCwd => getcwd(validate_slice_mut(b as *mut u8, c)?)