Skip to content
Snippets Groups Projects
Commit 9bc242c1 authored by Jeremy Soller's avatar Jeremy Soller
Browse files

Implement the typical use of waitpid

parent 5f570fa5
Branches
No related tags found
No related merge requests found
......@@ -77,4 +77,8 @@ impl ContextList {
}
Ok(context_lock)
}
pub fn remove(&mut self, id: usize) -> Option<RwLock<Context>> {
self.map.remove(&id)
}
}
use super::{Error, Result};
/// System call list
/// See http://syscalls.kernelgrok.com/ for numbers
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
#[repr(C)]
pub enum Call {
/// Exit syscall
Exit = 1,
/// Read syscall
Read = 3,
/// Write syscall
Write = 4,
/// Open syscall
Open = 5,
/// Close syscall
Close = 6,
/// Wait for a process
WaitPid = 7,
/// Execute syscall
Exec = 11,
/// Get process ID
GetPid = 20,
/// Duplicate file descriptor
Dup = 41,
/// Set process break
Brk = 45,
/// Set process I/O privilege level
Iopl = 110,
/// Clone process
Clone = 120,
/// Yield to scheduler
SchedYield = 158
}
/// Convert numbers to calls
/// See http://syscalls.kernelgrok.com/
impl Call {
pub fn from(number: usize) -> Result<Call> {
match number {
1 => Ok(Call::Exit),
3 => Ok(Call::Read),
4 => Ok(Call::Write),
5 => Ok(Call::Open),
6 => Ok(Call::Close),
7 => Ok(Call::WaitPid),
11 => Ok(Call::Exec),
20 => Ok(Call::GetPid),
41 => Ok(Call::Dup),
45 => Ok(Call::Brk),
110 => Ok(Call::Iopl),
120 => Ok(Call::Clone),
158 => Ok(Call::SchedYield),
_ => Err(Error::NoCall)
}
}
}
/// The error number for an invalid value
/// See http://www-numi.fnal.gov/offline_software/srt_public_context/WebDocs/Errors/unix_system_errors.html for numbers
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
#[repr(C)]
pub enum Error {
/// Operation not permitted
NotPermitted = 1,
/// No such file or directory
NoEntry = 2,
/// No such process
NoProcess = 3,
/// Invalid executable format
NoExec = 8,
/// Bad file number
BadFile = 9,
/// Try again
TryAgain = 11,
/// File exists
FileExists = 17,
/// Invalid argument
InvalidValue = 22,
/// Too many open files
TooManyFiles = 24,
/// Syscall not implemented
NoCall = 38
}
pub type Result<T> = ::core::result::Result<T, Error>;
///! Syscall handlers
use core::slice;
pub use self::call::*;
pub use self::error::*;
pub use self::fs::*;
pub use self::process::*;
pub use self::validate::*;
/// Filesystem syscalls
pub mod fs;
/// Process syscalls
pub mod process;
/// System call numbers
mod call;
/// System call list
/// See http://syscalls.kernelgrok.com/ for numbers
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
#[repr(C)]
pub enum Call {
/// Exit syscall
Exit = 1,
/// Read syscall
Read = 3,
/// Write syscall
Write = 4,
/// Open syscall
Open = 5,
/// Close syscall
Close = 6,
/// Execute syscall
Exec = 11,
/// Get process ID
GetPid = 20,
/// Duplicate file descriptor
Dup = 41,
/// Set process break
Brk = 45,
/// Set process I/O privilege level
Iopl = 110,
/// Clone process
Clone = 120,
/// Yield to scheduler
SchedYield = 158
}
/// System error codes
mod error;
/// Convert numbers to calls
/// See http://syscalls.kernelgrok.com/
impl Call {
fn from(number: usize) -> Result<Call> {
match number {
1 => Ok(Call::Exit),
3 => Ok(Call::Read),
4 => Ok(Call::Write),
5 => Ok(Call::Open),
6 => Ok(Call::Close),
11 => Ok(Call::Exec),
20 => Ok(Call::GetPid),
41 => Ok(Call::Dup),
45 => Ok(Call::Brk),
110 => Ok(Call::Iopl),
120 => Ok(Call::Clone),
158 => Ok(Call::SchedYield),
_ => Err(Error::NoCall)
}
}
}
/// The error number for an invalid value
/// See http://www-numi.fnal.gov/offline_software/srt_public_context/WebDocs/Errors/unix_system_errors.html for numbers
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
#[repr(C)]
pub enum Error {
/// Operation not permitted
NotPermitted = 1,
/// No such file or directory
NoEntry = 2,
/// No such process
NoProcess = 3,
/// Invalid executable format
NoExec = 8,
/// Bad file number
BadFile = 9,
/// Try again
TryAgain = 11,
/// File exists
FileExists = 17,
/// Invalid argument
InvalidValue = 22,
/// Too many open files
TooManyFiles = 24,
/// Syscall not implemented
NoCall = 38
}
pub type Result<T> = ::core::result::Result<T, Error>;
/// Filesystem syscalls
mod fs;
/// Convert a pointer and length to slice, if valid
/// TODO: Check validity
pub fn convert_slice<T>(ptr: *const T, len: usize) -> Result<&'static [T]> {
Ok(unsafe { slice::from_raw_parts(ptr, len) })
}
/// Process syscalls
mod process;
/// Convert a pointer and length to slice, if valid
/// TODO: Check validity
pub fn convert_slice_mut<T>(ptr: *mut T, len: usize) -> Result<&'static mut [T]> {
Ok(unsafe { slice::from_raw_parts_mut(ptr, len) })
}
/// Validate input
mod validate;
#[no_mangle]
pub extern fn syscall(a: usize, b: usize, c: usize, d: usize, e: usize, f: usize, stack: usize) -> usize {
......@@ -112,11 +28,12 @@ pub extern fn syscall(a: usize, b: usize, c: usize, d: usize, e: usize, f: usize
match Call::from(a) {
Ok(call) => match call {
Call::Exit => exit(b),
Call::Read => read(b, convert_slice_mut(c as *mut u8, d)?),
Call::Write => write(b, convert_slice(c as *const u8, d)?),
Call::Open => open(convert_slice(b as *const u8, c)?, d),
Call::Read => read(b, validate_slice_mut(c as *mut u8, d)?),
Call::Write => write(b, validate_slice(c as *const u8, d)?),
Call::Open => open(validate_slice(b as *const u8, c)?, d),
Call::Close => close(b),
Call::Exec => exec(convert_slice(b as *const u8, c)?, convert_slice(d as *const [usize; 2], e)?),
Call::WaitPid => waitpid(b, c, d),
Call::Exec => exec(validate_slice(b as *const u8, c)?, validate_slice(d as *const [usize; 2], e)?),
Call::GetPid => getpid(),
Call::Dup => dup(b),
Call::Brk => brk(b),
......
......@@ -363,3 +363,27 @@ pub fn sched_yield() -> Result<usize> {
unsafe { context::switch(); }
Ok(0)
}
pub fn waitpid(pid: usize, _status_ptr: usize, _options: usize) -> Result<usize> {
loop {
{
let mut exited = false;
{
let contexts = context::contexts();
let context_lock = contexts.get(pid).ok_or(Error::NoProcess)?;
let context = context_lock.read();
if context.status == context::Status::Exited {
exited = true;
}
}
if exited {
let mut contexts = context::contexts_mut();
return contexts.remove(pid).ok_or(Error::NoProcess).and(Ok(pid));
}
}
unsafe { context::switch(); }
}
}
use core::slice;
use super::Result;
/// Convert a pointer and length to slice, if valid
/// TODO: Check validity
pub fn validate_slice<T>(ptr: *const T, len: usize) -> Result<&'static [T]> {
Ok(unsafe { slice::from_raw_parts(ptr, len) })
}
/// Convert a pointer and length to slice, if valid
/// TODO: Check validity
pub fn validate_slice_mut<T>(ptr: *mut T, len: usize) -> Result<&'static mut [T]> {
Ok(unsafe { slice::from_raw_parts_mut(ptr, len) })
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment