Add specification to vesad

Fix piping
Fix bug where resources are not closed
Add arpd
Remove question_mark features
This commit is contained in:
Jeremy Soller 2016-10-14 18:22:57 -06:00
parent 05a5c52f68
commit ad448956d6
12 changed files with 360 additions and 93 deletions

View file

@ -1,9 +1,9 @@
use alloc::arc::{Arc, Weak};
use collections::BTreeMap;
use collections::{BTreeMap, VecDeque};
use core::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering};
use spin::{Once, RwLock, RwLockReadGuard, RwLockWriteGuard};
use spin::{Mutex, Once, RwLock, RwLockReadGuard, RwLockWriteGuard};
use sync::WaitQueue;
use sync::WaitCondition;
use syscall::error::{Error, Result, EBADF, EPIPE};
use syscall::scheme::Scheme;
@ -30,8 +30,8 @@ fn pipes_mut() -> RwLockWriteGuard<'static, (BTreeMap<usize, PipeRead>, BTreeMap
pub fn pipe(_flags: usize) -> (usize, usize) {
let mut pipes = pipes_mut();
let read_id = PIPE_NEXT_ID.fetch_add(1, Ordering::SeqCst);
let read = PipeRead::new();
let write_id = PIPE_NEXT_ID.fetch_add(1, Ordering::SeqCst);
let read = PipeRead::new();
let write = PipeWrite::new(&read);
pipes.0.insert(read_id, read);
pipes.1.insert(write_id, write);
@ -104,21 +104,43 @@ impl Scheme for PipeScheme {
/// Read side of a pipe
#[derive(Clone)]
pub struct PipeRead {
vec: Arc<WaitQueue<u8>>
condition: Arc<WaitCondition>,
vec: Arc<Mutex<VecDeque<u8>>>
}
impl PipeRead {
pub fn new() -> Self {
PipeRead {
vec: Arc::new(WaitQueue::new())
condition: Arc::new(WaitCondition::new()),
vec: Arc::new(Mutex::new(VecDeque::new())),
}
}
fn read(&self, buf: &mut [u8]) -> Result<usize> {
if buf.is_empty() || (Arc::weak_count(&self.vec) == 0 && self.vec.is_empty()) {
Ok(0)
} else {
Ok(self.vec.receive_into(buf))
loop {
{
let mut vec = self.vec.lock();
let mut i = 0;
while i < buf.len() {
if let Some(b) = vec.pop_front() {
buf[i] = b;
i += 1;
} else {
break;
}
}
if i > 0 {
return Ok(i);
}
}
if Arc::weak_count(&self.vec) == 0 {
return Ok(0);
} else {
self.condition.wait();
}
}
}
}
@ -126,24 +148,37 @@ impl PipeRead {
/// Read side of a pipe
#[derive(Clone)]
pub struct PipeWrite {
vec: Weak<WaitQueue<u8>>,
condition: Arc<WaitCondition>,
vec: Weak<Mutex<VecDeque<u8>>>
}
impl PipeWrite {
pub fn new(read: &PipeRead) -> Self {
PipeWrite {
condition: read.condition.clone(),
vec: Arc::downgrade(&read.vec),
}
}
fn write(&self, buf: &[u8]) -> Result<usize> {
match self.vec.upgrade() {
Some(vec) => {
vec.send_from(buf);
if let Some(vec_lock) = self.vec.upgrade() {
let mut vec = vec_lock.lock();
Ok(buf.len())
},
None => Err(Error::new(EPIPE))
for &b in buf.iter() {
vec.push_back(b);
}
self.condition.notify();
Ok(buf.len())
} else {
Err(Error::new(EPIPE))
}
}
}
impl Drop for PipeWrite {
fn drop(&mut self) {
self.condition.notify();
}
}

View file

@ -4,7 +4,7 @@ use alloc::boxed::Box;
use collections::{BTreeMap, Vec};
use core::{mem, str};
use core::ops::DerefMut;
use spin::{Mutex, RwLock};
use spin::Mutex;
use arch;
use arch::externs::memcpy;
@ -596,26 +596,56 @@ pub fn exec(path: &[u8], arg_ptrs: &[[usize; 2]]) -> Result<usize> {
unsafe { usermode(entry, sp); }
}
fn terminate(context_lock: Arc<RwLock<context::Context>>, status: usize) {
let mut close_files = Vec::new();
pub fn exit(status: usize) -> ! {
{
let (vfork, ppid) = {
let context_lock = {
let contexts = context::contexts();
let context_lock = contexts.current().ok_or(Error::new(ESRCH)).expect("exit failed to find context");
context_lock.clone()
};
let mut close_files = Vec::new();
{
let mut context = context_lock.write();
context.image.clear();
drop(context.heap.take());
drop(context.stack.take());
context.grants = Arc::new(Mutex::new(Vec::new()));
if Arc::strong_count(&context.files) == 1 {
mem::swap(context.files.lock().deref_mut(), &mut close_files);
}
context.files = Arc::new(Mutex::new(Vec::new()));
context.status = context::Status::Exited(status);
}
/// Files must be closed while context is valid so that messages can be passed
for (fd, file_option) in close_files.drain(..).enumerate() {
if let Some(file) = file_option {
context::event::unregister(fd, file.scheme, file.number);
let scheme_option = {
let schemes = scheme::schemes();
schemes.get(file.scheme).map(|scheme| scheme.clone())
};
if let Some(scheme) = scheme_option {
let _ = scheme.close(file.number);
}
}
}
let (vfork, ppid) = {
let mut context = context_lock.write();
context.image.clear();
drop(context.heap.take());
drop(context.stack.take());
context.grants = Arc::new(Mutex::new(Vec::new()));
let vfork = context.vfork;
context.vfork = false;
context.status = context::Status::Exited(status);
context.waitpid.notify();
(vfork, context.ppid)
};
if vfork {
let contexts = context::contexts();
if let Some(parent_lock) = contexts.get(ppid) {
@ -629,31 +659,6 @@ fn terminate(context_lock: Arc<RwLock<context::Context>>, status: usize) {
}
}
for (fd, file_option) in close_files.drain(..).enumerate() {
if let Some(file) = file_option {
context::event::unregister(fd, file.scheme, file.number);
let scheme_option = {
let schemes = scheme::schemes();
schemes.get(file.scheme).map(|scheme| scheme.clone())
};
if let Some(scheme) = scheme_option {
let _ = scheme.close(file.number);
}
}
}
}
pub fn exit(status: usize) -> ! {
{
let context_lock = {
let contexts = context::contexts();
let context_lock = contexts.current().ok_or(Error::new(ESRCH)).expect("exit failed to find context");
context_lock.clone()
};
terminate(context_lock, status);
}
unsafe { context::switch(); }
unreachable!();
@ -702,45 +707,45 @@ pub fn iopl(_level: usize) -> Result<usize> {
pub fn kill(pid: usize, sig: usize) -> Result<usize> {
use syscall::flag::*;
let context_lock = {
let _context_lock = {
let contexts = context::contexts();
let context_lock = contexts.get(pid).ok_or(Error::new(ESRCH))?;
context_lock.clone()
};
let term = |context_lock| {
terminate(context_lock, !sig);
let term = || {
println!("Terminate {}", pid);
};
let core = |context_lock| {
terminate(context_lock, !sig);
let core = || {
println!("Core {}", pid);
};
let stop = || {
println!("Stop {}", pid);
};
let cont = || {
println!("Continue {}", pid);
};
match sig {
0 => (),
SIGHUP => term(context_lock),
SIGINT => term(context_lock),
SIGQUIT => core(context_lock),
SIGILL => core(context_lock),
SIGTRAP => core(context_lock),
SIGABRT => core(context_lock),
SIGBUS => core(context_lock),
SIGFPE => core(context_lock),
SIGKILL => term(context_lock),
SIGUSR1 => term(context_lock),
SIGSEGV => core(context_lock),
SIGPIPE => term(context_lock),
SIGALRM => term(context_lock),
SIGTERM => term(context_lock),
SIGSTKFLT => term(context_lock),
SIGHUP => term(),
SIGINT => term(),
SIGQUIT => core(),
SIGILL => core(),
SIGTRAP => core(),
SIGABRT => core(),
SIGBUS => core(),
SIGFPE => core(),
SIGKILL => term(),
SIGUSR1 => term(),
SIGSEGV => core(),
SIGPIPE => term(),
SIGALRM => term(),
SIGTERM => term(),
SIGSTKFLT => term(),
SIGCHLD => (),
SIGCONT => cont(),
SIGSTOP => stop(),
@ -748,14 +753,14 @@ pub fn kill(pid: usize, sig: usize) -> Result<usize> {
SIGTTIN => stop(),
SIGTTOU => stop(),
SIGURG => (),
SIGXCPU => core(context_lock),
SIGXFSZ => core(context_lock),
SIGVTALRM => term(context_lock),
SIGPROF => term(context_lock),
SIGXCPU => core(),
SIGXFSZ => core(),
SIGVTALRM => term(),
SIGPROF => term(),
SIGWINCH => (),
SIGIO => term(context_lock),
SIGPWR => term(context_lock),
SIGSYS => core(context_lock),
SIGIO => term(),
SIGPWR => term(),
SIGSYS => core(),
_ => return Err(Error::new(EINVAL))
}