Implement the typical use of waitpid
This commit is contained in:
parent
e680a84a57
commit
3e726a5d0d
|
@ -77,4 +77,8 @@ impl ContextList {
|
|||
}
|
||||
Ok(context_lock)
|
||||
}
|
||||
|
||||
pub fn remove(&mut self, id: usize) -> Option<RwLock<Context>> {
|
||||
self.map.remove(&id)
|
||||
}
|
||||
}
|
||||
|
|
57
kernel/syscall/call.rs
Normal file
57
kernel/syscall/call.rs
Normal file
|
@ -0,0 +1,57 @@
|
|||
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)
|
||||
}
|
||||
}
|
||||
}
|
28
kernel/syscall/error.rs
Normal file
28
kernel/syscall/error.rs
Normal file
|
@ -0,0 +1,28 @@
|
|||
/// 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>;
|
|
@ -1,109 +1,25 @@
|
|||
///! 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::*;
|
||||
|
||||
/// System call numbers
|
||||
mod call;
|
||||
|
||||
/// System error codes
|
||||
mod error;
|
||||
|
||||
/// Filesystem syscalls
|
||||
pub mod fs;
|
||||
mod fs;
|
||||
|
||||
/// Process syscalls
|
||||
pub mod process;
|
||||
mod process;
|
||||
|
||||
/// 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
|
||||
}
|
||||
|
||||
/// 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>;
|
||||
|
||||
/// 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) })
|
||||
}
|
||||
|
||||
/// 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(); }
|
||||
}
|
||||
}
|
||||
|
|
15
kernel/syscall/validate.rs
Normal file
15
kernel/syscall/validate.rs
Normal file
|
@ -0,0 +1,15 @@
|
|||
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) })
|
||||
}
|
Loading…
Reference in a new issue