Add sys scheme to allow inspection of processes. WIP: Signals.
This commit is contained in:
parent
224c43f761
commit
d18bf07f3e
3
Makefile
3
Makefile
|
@ -267,6 +267,7 @@ coreutils: \
|
||||||
filesystem/bin/mkdir \
|
filesystem/bin/mkdir \
|
||||||
filesystem/bin/mv \
|
filesystem/bin/mv \
|
||||||
filesystem/bin/printenv \
|
filesystem/bin/printenv \
|
||||||
|
filesystem/bin/ps \
|
||||||
filesystem/bin/pwd \
|
filesystem/bin/pwd \
|
||||||
filesystem/bin/realpath \
|
filesystem/bin/realpath \
|
||||||
filesystem/bin/reset \
|
filesystem/bin/reset \
|
||||||
|
@ -280,7 +281,7 @@ coreutils: \
|
||||||
filesystem/bin/true \
|
filesystem/bin/true \
|
||||||
filesystem/bin/wc \
|
filesystem/bin/wc \
|
||||||
filesystem/bin/yes
|
filesystem/bin/yes
|
||||||
#filesystem/bin/free filesystem/bin/ps filesystem/bin/shutdown filesystem/bin/test
|
#filesystem/bin/free filesystem/bin/shutdown filesystem/bin/test
|
||||||
|
|
||||||
extrautils: \
|
extrautils: \
|
||||||
filesystem/bin/calc \
|
filesystem/bin/calc \
|
||||||
|
|
|
@ -55,6 +55,8 @@ pub struct Context {
|
||||||
pub stack: Option<Memory>,
|
pub stack: Option<Memory>,
|
||||||
/// User grants
|
/// User grants
|
||||||
pub grants: Arc<Mutex<Vec<Grant>>>,
|
pub grants: Arc<Mutex<Vec<Grant>>>,
|
||||||
|
/// The name of the context
|
||||||
|
pub name: Arc<Mutex<Vec<u8>>>,
|
||||||
/// The current working directory
|
/// The current working directory
|
||||||
pub cwd: Arc<Mutex<Vec<u8>>>,
|
pub cwd: Arc<Mutex<Vec<u8>>>,
|
||||||
/// Kernel events
|
/// Kernel events
|
||||||
|
@ -87,6 +89,7 @@ impl Context {
|
||||||
heap: None,
|
heap: None,
|
||||||
stack: None,
|
stack: None,
|
||||||
grants: Arc::new(Mutex::new(Vec::new())),
|
grants: Arc::new(Mutex::new(Vec::new())),
|
||||||
|
name: Arc::new(Mutex::new(Vec::new())),
|
||||||
cwd: Arc::new(Mutex::new(Vec::new())),
|
cwd: Arc::new(Mutex::new(Vec::new())),
|
||||||
events: Arc::new(WaitQueue::new()),
|
events: Arc::new(WaitQueue::new()),
|
||||||
env: Arc::new(Mutex::new(BTreeMap::new())),
|
env: Arc::new(Mutex::new(BTreeMap::new())),
|
||||||
|
|
|
@ -22,6 +22,7 @@ use self::initfs::InitFsScheme;
|
||||||
use self::irq::{IRQ_SCHEME_ID, IrqScheme};
|
use self::irq::{IRQ_SCHEME_ID, IrqScheme};
|
||||||
use self::pipe::{PIPE_SCHEME_ID, PipeScheme};
|
use self::pipe::{PIPE_SCHEME_ID, PipeScheme};
|
||||||
use self::root::{ROOT_SCHEME_ID, RootScheme};
|
use self::root::{ROOT_SCHEME_ID, RootScheme};
|
||||||
|
use self::sys::SysScheme;
|
||||||
|
|
||||||
/// Debug scheme
|
/// Debug scheme
|
||||||
pub mod debug;
|
pub mod debug;
|
||||||
|
@ -44,6 +45,9 @@ pub mod pipe;
|
||||||
/// Root scheme
|
/// Root scheme
|
||||||
pub mod root;
|
pub mod root;
|
||||||
|
|
||||||
|
/// System information
|
||||||
|
pub mod sys;
|
||||||
|
|
||||||
/// Userspace schemes
|
/// Userspace schemes
|
||||||
pub mod user;
|
pub mod user;
|
||||||
|
|
||||||
|
@ -121,6 +125,7 @@ fn init_schemes() -> RwLock<SchemeList> {
|
||||||
list.insert(Box::new(*b"initfs"), Arc::new(Box::new(InitFsScheme::new()))).expect("failed to insert initfs scheme");
|
list.insert(Box::new(*b"initfs"), Arc::new(Box::new(InitFsScheme::new()))).expect("failed to insert initfs scheme");
|
||||||
IRQ_SCHEME_ID.store(list.insert(Box::new(*b"irq"), Arc::new(Box::new(IrqScheme))).expect("failed to insert irq scheme"), Ordering::SeqCst);
|
IRQ_SCHEME_ID.store(list.insert(Box::new(*b"irq"), Arc::new(Box::new(IrqScheme))).expect("failed to insert irq scheme"), Ordering::SeqCst);
|
||||||
PIPE_SCHEME_ID.store(list.insert(Box::new(*b"pipe"), Arc::new(Box::new(PipeScheme))).expect("failed to insert pipe scheme"), Ordering::SeqCst);
|
PIPE_SCHEME_ID.store(list.insert(Box::new(*b"pipe"), Arc::new(Box::new(PipeScheme))).expect("failed to insert pipe scheme"), Ordering::SeqCst);
|
||||||
|
list.insert(Box::new(*b"sys"), Arc::new(Box::new(SysScheme::new()))).expect("failed to insert sys scheme");
|
||||||
RwLock::new(list)
|
RwLock::new(list)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
90
kernel/scheme/sys/context.rs
Normal file
90
kernel/scheme/sys/context.rs
Normal file
|
@ -0,0 +1,90 @@
|
||||||
|
use collections::{String, Vec};
|
||||||
|
use core::str;
|
||||||
|
|
||||||
|
use context;
|
||||||
|
use syscall::error::Result;
|
||||||
|
|
||||||
|
pub fn resource() -> Result<Vec<u8>> {
|
||||||
|
let mut string = format!("{:<6}{:<6}{:<6}{:<6}{:<6}{:<8}{}\n",
|
||||||
|
"PID",
|
||||||
|
"PPID",
|
||||||
|
"UID",
|
||||||
|
"GID",
|
||||||
|
"STAT",
|
||||||
|
"MEM",
|
||||||
|
"NAME");
|
||||||
|
{
|
||||||
|
let contexts = context::contexts();
|
||||||
|
for (_id, context_lock) in contexts.iter() {
|
||||||
|
let context = context_lock.read();
|
||||||
|
|
||||||
|
let mut memory = 0;
|
||||||
|
if let Some(ref kfx) = context.kstack {
|
||||||
|
memory += kfx.len();
|
||||||
|
}
|
||||||
|
if let Some(ref kstack) = context.kstack {
|
||||||
|
memory += kstack.len();
|
||||||
|
}
|
||||||
|
for shared_mem in context.image.iter() {
|
||||||
|
shared_mem.with(|mem| {
|
||||||
|
memory += mem.size();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if let Some(ref heap) = context.heap {
|
||||||
|
heap.with(|heap| {
|
||||||
|
memory += heap.size();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if let Some(ref stack) = context.stack {
|
||||||
|
memory += stack.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
let memory_string = if memory >= 1024 * 1024 * 1024 {
|
||||||
|
format!("{} GB", memory / 1024 / 1024 / 1024)
|
||||||
|
} else if memory >= 1024 * 1024 {
|
||||||
|
format!("{} MB", memory / 1024 / 1024)
|
||||||
|
} else if memory >= 1024 {
|
||||||
|
format!("{} KB", memory / 1024)
|
||||||
|
} else {
|
||||||
|
format!("{} B", memory)
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut stat_string = String::new();
|
||||||
|
if context.stack.is_some() {
|
||||||
|
stat_string.push('U');
|
||||||
|
} else {
|
||||||
|
stat_string.push('K');
|
||||||
|
}
|
||||||
|
match context.status {
|
||||||
|
context::Status::Runnable => {
|
||||||
|
stat_string.push('R');
|
||||||
|
},
|
||||||
|
context::Status::Blocked => if context.wake.is_some() {
|
||||||
|
stat_string.push('S');
|
||||||
|
} else {
|
||||||
|
stat_string.push('B');
|
||||||
|
},
|
||||||
|
context::Status::Exited(_status) => {
|
||||||
|
stat_string.push('Z');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if context.running {
|
||||||
|
stat_string.push('+');
|
||||||
|
}
|
||||||
|
|
||||||
|
let name_bytes = context.name.lock();
|
||||||
|
let name = str::from_utf8(&name_bytes).unwrap_or("");
|
||||||
|
|
||||||
|
string.push_str(&format!("{:<6}{:<6}{:<6}{:<6}{:<6}{:<8}{}\n",
|
||||||
|
context.id,
|
||||||
|
context.ppid,
|
||||||
|
context.euid,
|
||||||
|
context.egid,
|
||||||
|
stat_string,
|
||||||
|
memory_string,
|
||||||
|
name));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(string.into_bytes())
|
||||||
|
}
|
162
kernel/scheme/sys/mod.rs
Normal file
162
kernel/scheme/sys/mod.rs
Normal file
|
@ -0,0 +1,162 @@
|
||||||
|
use alloc::boxed::Box;
|
||||||
|
use collections::{BTreeMap, Vec};
|
||||||
|
use core::{cmp, str};
|
||||||
|
use core::sync::atomic::{AtomicUsize, Ordering};
|
||||||
|
use spin::RwLock;
|
||||||
|
|
||||||
|
use syscall::data::Stat;
|
||||||
|
use syscall::error::{Error, EBADF, EINVAL, ENOENT, Result};
|
||||||
|
use syscall::flag::{MODE_FILE, SEEK_CUR, SEEK_END, SEEK_SET};
|
||||||
|
use syscall::scheme::Scheme;
|
||||||
|
|
||||||
|
mod context;
|
||||||
|
//mod interrupt;
|
||||||
|
//mod log;
|
||||||
|
//mod memory;
|
||||||
|
//mod test;
|
||||||
|
|
||||||
|
struct Handle {
|
||||||
|
path: &'static [u8],
|
||||||
|
data: Vec<u8>,
|
||||||
|
mode: u16,
|
||||||
|
seek: usize
|
||||||
|
}
|
||||||
|
|
||||||
|
type SysFn = Fn() -> Result<Vec<u8>> + Send + Sync;
|
||||||
|
|
||||||
|
/// System information scheme
|
||||||
|
pub struct SysScheme {
|
||||||
|
next_id: AtomicUsize,
|
||||||
|
files: BTreeMap<&'static [u8], Box<SysFn>>,
|
||||||
|
handles: RwLock<BTreeMap<usize, Handle>>
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SysScheme {
|
||||||
|
pub fn new() -> SysScheme {
|
||||||
|
let mut files: BTreeMap<&'static [u8], Box<SysFn>> = BTreeMap::new();
|
||||||
|
|
||||||
|
files.insert(b"context", Box::new(move || context::resource()));
|
||||||
|
//files.insert(b"interrupt", Box::new(move || interrupt::resource()));
|
||||||
|
//files.insert(b"log", Box::new(move || log::resource()));
|
||||||
|
//files.insert(b"memory", Box::new(move || memory::resource()));
|
||||||
|
//files.insert(b"test", Box::new(move || test::resource()));
|
||||||
|
|
||||||
|
SysScheme {
|
||||||
|
next_id: AtomicUsize::new(0),
|
||||||
|
files: files,
|
||||||
|
handles: RwLock::new(BTreeMap::new())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Scheme for SysScheme {
|
||||||
|
fn open(&self, path: &[u8], _flags: usize, _uid: u32, _gid: u32) -> Result<usize> {
|
||||||
|
let path_utf8 = str::from_utf8(path).map_err(|_err| Error::new(ENOENT))?;
|
||||||
|
let path_trimmed = path_utf8.trim_matches('/');
|
||||||
|
|
||||||
|
//Have to iterate to get the path without allocation
|
||||||
|
for entry in self.files.iter() {
|
||||||
|
if entry.0 == &path_trimmed.as_bytes() {
|
||||||
|
let id = self.next_id.fetch_add(1, Ordering::SeqCst);
|
||||||
|
self.handles.write().insert(id, Handle {
|
||||||
|
path: entry.0,
|
||||||
|
data: entry.1()?,
|
||||||
|
mode: MODE_FILE | 0o444,
|
||||||
|
seek: 0
|
||||||
|
});
|
||||||
|
|
||||||
|
return Ok(id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Err(Error::new(ENOENT))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn dup(&self, id: usize) -> Result<usize> {
|
||||||
|
let (path, data, mode, seek) = {
|
||||||
|
let handles = self.handles.read();
|
||||||
|
let handle = handles.get(&id).ok_or(Error::new(EBADF))?;
|
||||||
|
(handle.path, handle.data.clone(), handle.mode, handle.seek)
|
||||||
|
};
|
||||||
|
|
||||||
|
let id = self.next_id.fetch_add(1, Ordering::SeqCst);
|
||||||
|
self.handles.write().insert(id, Handle {
|
||||||
|
path: path,
|
||||||
|
data: data,
|
||||||
|
mode: mode,
|
||||||
|
seek: seek
|
||||||
|
});
|
||||||
|
|
||||||
|
Ok(id)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn read(&self, id: usize, buffer: &mut [u8]) -> Result<usize> {
|
||||||
|
let mut handles = self.handles.write();
|
||||||
|
let mut handle = handles.get_mut(&id).ok_or(Error::new(EBADF))?;
|
||||||
|
|
||||||
|
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 seek(&self, id: usize, pos: usize, whence: usize) -> Result<usize> {
|
||||||
|
let mut handles = self.handles.write();
|
||||||
|
let mut handle = handles.get_mut(&id).ok_or(Error::new(EBADF))?;
|
||||||
|
|
||||||
|
handle.seek = match whence {
|
||||||
|
SEEK_SET => cmp::min(handle.data.len(), pos),
|
||||||
|
SEEK_CUR => cmp::max(0, cmp::min(handle.data.len() as isize, handle.seek as isize + pos as isize)) as usize,
|
||||||
|
SEEK_END => cmp::max(0, cmp::min(handle.data.len() as isize, handle.data.len() as isize + pos as isize)) as usize,
|
||||||
|
_ => return Err(Error::new(EINVAL))
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(handle.seek)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn fpath(&self, id: usize, buf: &mut [u8]) -> Result<usize> {
|
||||||
|
let handles = self.handles.read();
|
||||||
|
let handle = handles.get(&id).ok_or(Error::new(EBADF))?;
|
||||||
|
|
||||||
|
//TODO: Copy scheme part in kernel
|
||||||
|
let mut i = 0;
|
||||||
|
let scheme_path = b"initfs:";
|
||||||
|
while i < buf.len() && i < scheme_path.len() {
|
||||||
|
buf[i] = scheme_path[i];
|
||||||
|
i += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut j = 0;
|
||||||
|
while i < buf.len() && j < handle.path.len() {
|
||||||
|
buf[i] = handle.path[j];
|
||||||
|
i += 1;
|
||||||
|
j += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(i)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn fstat(&self, id: usize, stat: &mut Stat) -> Result<usize> {
|
||||||
|
let handles = self.handles.read();
|
||||||
|
let handle = handles.get(&id).ok_or(Error::new(EBADF))?;
|
||||||
|
|
||||||
|
stat.st_mode = handle.mode;
|
||||||
|
stat.st_uid = 0;
|
||||||
|
stat.st_gid = 0;
|
||||||
|
stat.st_size = handle.data.len() as u64;
|
||||||
|
|
||||||
|
Ok(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn fsync(&self, _id: usize) -> Result<usize> {
|
||||||
|
Ok(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn close(&self, id: usize) -> Result<usize> {
|
||||||
|
self.handles.write().remove(&id).ok_or(Error::new(EBADF)).and(Ok(0))
|
||||||
|
}
|
||||||
|
}
|
|
@ -4,7 +4,7 @@ use alloc::boxed::Box;
|
||||||
use collections::{BTreeMap, Vec};
|
use collections::{BTreeMap, Vec};
|
||||||
use core::{mem, str};
|
use core::{mem, str};
|
||||||
use core::ops::DerefMut;
|
use core::ops::DerefMut;
|
||||||
use spin::Mutex;
|
use spin::{Mutex, RwLock};
|
||||||
|
|
||||||
use arch;
|
use arch;
|
||||||
use arch::externs::memcpy;
|
use arch::externs::memcpy;
|
||||||
|
@ -71,6 +71,7 @@ pub fn clone(flags: usize, stack_base: usize) -> Result<usize> {
|
||||||
let mut heap_option = None;
|
let mut heap_option = None;
|
||||||
let mut stack_option = None;
|
let mut stack_option = None;
|
||||||
let grants;
|
let grants;
|
||||||
|
let name;
|
||||||
let cwd;
|
let cwd;
|
||||||
let env;
|
let env;
|
||||||
let files;
|
let files;
|
||||||
|
@ -186,6 +187,12 @@ pub fn clone(flags: usize, stack_base: usize) -> Result<usize> {
|
||||||
grants = Arc::new(Mutex::new(Vec::new()));
|
grants = Arc::new(Mutex::new(Vec::new()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if flags & CLONE_VM == CLONE_VM {
|
||||||
|
name = context.name.clone();
|
||||||
|
} else {
|
||||||
|
name = Arc::new(Mutex::new(context.name.lock().clone()));
|
||||||
|
}
|
||||||
|
|
||||||
if flags & CLONE_FS == CLONE_FS {
|
if flags & CLONE_FS == CLONE_FS {
|
||||||
cwd = context.cwd.clone();
|
cwd = context.cwd.clone();
|
||||||
} else {
|
} else {
|
||||||
|
@ -382,6 +389,8 @@ pub fn clone(flags: usize, stack_base: usize) -> Result<usize> {
|
||||||
context.stack = Some(stack);
|
context.stack = Some(stack);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
context.name = name;
|
||||||
|
|
||||||
context.cwd = cwd;
|
context.cwd = cwd;
|
||||||
|
|
||||||
context.env = env;
|
context.env = env;
|
||||||
|
@ -395,61 +404,6 @@ pub fn clone(flags: usize, stack_base: usize) -> Result<usize> {
|
||||||
Ok(pid)
|
Ok(pid)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn exit(status: usize) -> ! {
|
|
||||||
{
|
|
||||||
let mut close_files = Vec::new();
|
|
||||||
{
|
|
||||||
let contexts = context::contexts();
|
|
||||||
let (vfork, ppid) = {
|
|
||||||
let context_lock = contexts.current().expect("tried to exit without context");
|
|
||||||
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);
|
|
||||||
|
|
||||||
let vfork = context.vfork;
|
|
||||||
context.vfork = false;
|
|
||||||
context.waitpid.notify();
|
|
||||||
(vfork, context.ppid)
|
|
||||||
};
|
|
||||||
if vfork {
|
|
||||||
if let Some(context_lock) = contexts.get(ppid) {
|
|
||||||
let mut context = context_lock.write();
|
|
||||||
if ! context.unblock() {
|
|
||||||
println!("{} not blocked for exit vfork unblock", ppid);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
println!("{} not found for exit vfork unblock", ppid);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
unsafe { context::switch(); }
|
|
||||||
|
|
||||||
unreachable!();
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn exec(path: &[u8], arg_ptrs: &[[usize; 2]]) -> Result<usize> {
|
pub fn exec(path: &[u8], arg_ptrs: &[[usize; 2]]) -> Result<usize> {
|
||||||
let entry;
|
let entry;
|
||||||
let mut sp = arch::USER_STACK_OFFSET + arch::USER_STACK_SIZE - 256;
|
let mut sp = arch::USER_STACK_OFFSET + arch::USER_STACK_SIZE - 256;
|
||||||
|
@ -461,14 +415,14 @@ pub fn exec(path: &[u8], arg_ptrs: &[[usize; 2]]) -> Result<usize> {
|
||||||
args.push(arg.to_vec()); // Must be moved into kernel space before exec unmaps all memory
|
args.push(arg.to_vec()); // Must be moved into kernel space before exec unmaps all memory
|
||||||
}
|
}
|
||||||
|
|
||||||
let (uid, gid) = {
|
let (uid, gid, canonical) = {
|
||||||
let contexts = context::contexts();
|
let contexts = context::contexts();
|
||||||
let context_lock = contexts.current().ok_or(Error::new(ESRCH))?;
|
let context_lock = contexts.current().ok_or(Error::new(ESRCH))?;
|
||||||
let context = context_lock.read();
|
let context = context_lock.read();
|
||||||
(context.euid, context.egid)
|
(context.euid, context.egid, context.canonicalize(path))
|
||||||
};
|
};
|
||||||
|
|
||||||
let file = syscall::open(path, 0)?;
|
let file = syscall::open(&canonical, 0)?;
|
||||||
let mut stat = Stat::default();
|
let mut stat = Stat::default();
|
||||||
syscall::file_op_mut_slice(syscall::number::SYS_FSTAT, file, &mut stat)?;
|
syscall::file_op_mut_slice(syscall::number::SYS_FSTAT, file, &mut stat)?;
|
||||||
|
|
||||||
|
@ -505,6 +459,9 @@ pub fn exec(path: &[u8], arg_ptrs: &[[usize; 2]]) -> Result<usize> {
|
||||||
let context_lock = contexts.current().ok_or(Error::new(ESRCH))?;
|
let context_lock = contexts.current().ok_or(Error::new(ESRCH))?;
|
||||||
let mut context = context_lock.write();
|
let mut context = context_lock.write();
|
||||||
|
|
||||||
|
// Set name
|
||||||
|
context.name = Arc::new(Mutex::new(canonical));
|
||||||
|
|
||||||
// Unmap previous image and stack
|
// Unmap previous image and stack
|
||||||
context.image.clear();
|
context.image.clear();
|
||||||
drop(context.heap.take());
|
drop(context.heap.take());
|
||||||
|
@ -639,6 +596,69 @@ pub fn exec(path: &[u8], arg_ptrs: &[[usize; 2]]) -> Result<usize> {
|
||||||
unsafe { usermode(entry, sp); }
|
unsafe { usermode(entry, sp); }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn terminate(context_lock: Arc<RwLock<context::Context>>, status: usize) {
|
||||||
|
let mut close_files = Vec::new();
|
||||||
|
{
|
||||||
|
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()));
|
||||||
|
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);
|
||||||
|
|
||||||
|
let vfork = context.vfork;
|
||||||
|
context.vfork = false;
|
||||||
|
context.waitpid.notify();
|
||||||
|
(vfork, context.ppid)
|
||||||
|
};
|
||||||
|
if vfork {
|
||||||
|
let contexts = context::contexts();
|
||||||
|
if let Some(parent_lock) = contexts.get(ppid) {
|
||||||
|
let mut parent = parent_lock.write();
|
||||||
|
if ! parent.unblock() {
|
||||||
|
println!("{} not blocked for exit vfork unblock", ppid);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
println!("{} not found for exit vfork unblock", ppid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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!();
|
||||||
|
}
|
||||||
|
|
||||||
pub fn getegid() -> Result<usize> {
|
pub fn getegid() -> Result<usize> {
|
||||||
let contexts = context::contexts();
|
let contexts = context::contexts();
|
||||||
let context_lock = contexts.current().ok_or(Error::new(ESRCH))?;
|
let context_lock = contexts.current().ok_or(Error::new(ESRCH))?;
|
||||||
|
@ -679,6 +699,69 @@ pub fn iopl(_level: usize) -> Result<usize> {
|
||||||
Ok(0)
|
Ok(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn kill(pid: usize, sig: usize) -> Result<usize> {
|
||||||
|
use syscall::flag::*;
|
||||||
|
|
||||||
|
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 core = |context_lock| {
|
||||||
|
terminate(context_lock, !sig);
|
||||||
|
};
|
||||||
|
|
||||||
|
let stop = || {
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
let cont = || {
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
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),
|
||||||
|
SIGCHLD => (),
|
||||||
|
SIGCONT => cont(),
|
||||||
|
SIGSTOP => stop(),
|
||||||
|
SIGTSTP => stop(),
|
||||||
|
SIGTTIN => stop(),
|
||||||
|
SIGTTOU => stop(),
|
||||||
|
SIGURG => (),
|
||||||
|
SIGXCPU => core(context_lock),
|
||||||
|
SIGXFSZ => core(context_lock),
|
||||||
|
SIGVTALRM => term(context_lock),
|
||||||
|
SIGPROF => term(context_lock),
|
||||||
|
SIGWINCH => (),
|
||||||
|
SIGIO => term(context_lock),
|
||||||
|
SIGPWR => term(context_lock),
|
||||||
|
SIGSYS => core(context_lock),
|
||||||
|
_ => return Err(Error::new(EINVAL))
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(0)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn physalloc(size: usize) -> Result<usize> {
|
pub fn physalloc(size: usize) -> Result<usize> {
|
||||||
allocate_frames((size + 4095)/4096).ok_or(Error::new(ENOMEM)).map(|frame| frame.start_address().get())
|
allocate_frames((size + 4095)/4096).ok_or(Error::new(ENOMEM)).map(|frame| frame.start_address().get())
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,10 +34,6 @@ pub const MODE_PERM: u16 = 0x0FFF;
|
||||||
pub const MODE_SETUID: u16 = 0o4000;
|
pub const MODE_SETUID: u16 = 0o4000;
|
||||||
pub const MODE_SETGID: u16 = 0o2000;
|
pub const MODE_SETGID: u16 = 0o2000;
|
||||||
|
|
||||||
pub const SEEK_SET: usize = 0;
|
|
||||||
pub const SEEK_CUR: usize = 1;
|
|
||||||
pub const SEEK_END: usize = 2;
|
|
||||||
|
|
||||||
pub const O_RDONLY: usize = 0x0000_0000;
|
pub const O_RDONLY: usize = 0x0000_0000;
|
||||||
pub const O_WRONLY: usize = 0x0001_0000;
|
pub const O_WRONLY: usize = 0x0001_0000;
|
||||||
pub const O_RDWR: usize = 0x0002_0000;
|
pub const O_RDWR: usize = 0x0002_0000;
|
||||||
|
@ -52,4 +48,40 @@ pub const O_CREAT: usize = 0x0200_0000;
|
||||||
pub const O_TRUNC: usize = 0x0400_0000;
|
pub const O_TRUNC: usize = 0x0400_0000;
|
||||||
pub const O_EXCL: usize = 0x0800_0000;
|
pub const O_EXCL: usize = 0x0800_0000;
|
||||||
|
|
||||||
|
pub const SEEK_SET: usize = 0;
|
||||||
|
pub const SEEK_CUR: usize = 1;
|
||||||
|
pub const SEEK_END: usize = 2;
|
||||||
|
|
||||||
|
pub const SIGHUP: usize = 1;
|
||||||
|
pub const SIGINT: usize = 2;
|
||||||
|
pub const SIGQUIT: usize = 3;
|
||||||
|
pub const SIGILL: usize = 4;
|
||||||
|
pub const SIGTRAP: usize = 5;
|
||||||
|
pub const SIGABRT: usize = 6;
|
||||||
|
pub const SIGBUS: usize = 7;
|
||||||
|
pub const SIGFPE: usize = 8;
|
||||||
|
pub const SIGKILL: usize = 9;
|
||||||
|
pub const SIGUSR1: usize = 10;
|
||||||
|
pub const SIGSEGV: usize = 11;
|
||||||
|
pub const SIGUSR2: usize = 12;
|
||||||
|
pub const SIGPIPE: usize = 13;
|
||||||
|
pub const SIGALRM: usize = 14;
|
||||||
|
pub const SIGTERM: usize = 15;
|
||||||
|
pub const SIGSTKFLT: usize= 16;
|
||||||
|
pub const SIGCHLD: usize = 17;
|
||||||
|
pub const SIGCONT: usize = 18;
|
||||||
|
pub const SIGSTOP: usize = 19;
|
||||||
|
pub const SIGTSTP: usize = 20;
|
||||||
|
pub const SIGTTIN: usize = 21;
|
||||||
|
pub const SIGTTOU: usize = 22;
|
||||||
|
pub const SIGURG: usize = 23;
|
||||||
|
pub const SIGXCPU: usize = 24;
|
||||||
|
pub const SIGXFSZ: usize = 25;
|
||||||
|
pub const SIGVTALRM: usize= 26;
|
||||||
|
pub const SIGPROF: usize = 27;
|
||||||
|
pub const SIGWINCH: usize = 28;
|
||||||
|
pub const SIGIO: usize = 29;
|
||||||
|
pub const SIGPWR: usize = 30;
|
||||||
|
pub const SIGSYS: usize = 31;
|
||||||
|
|
||||||
pub const WNOHANG: usize = 1;
|
pub const WNOHANG: usize = 1;
|
||||||
|
|
|
@ -112,6 +112,10 @@ pub unsafe fn iopl(level: usize) -> Result<usize> {
|
||||||
syscall1(SYS_IOPL, level)
|
syscall1(SYS_IOPL, level)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn kill(pid: usize, sig: usize) -> Result<usize> {
|
||||||
|
unsafe { syscall2(SYS_KILL, pid, sig) }
|
||||||
|
}
|
||||||
|
|
||||||
pub unsafe fn link(old: *const u8, new: *const u8) -> Result<usize> {
|
pub unsafe fn link(old: *const u8, new: *const u8) -> Result<usize> {
|
||||||
syscall2(SYS_LINK, old as usize, new as usize)
|
syscall2(SYS_LINK, old as usize, new as usize)
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,6 +41,7 @@ pub const SYS_GETGID: usize = 200;
|
||||||
pub const SYS_GETPID: usize = 20;
|
pub const SYS_GETPID: usize = 20;
|
||||||
pub const SYS_GETUID: usize = 199;
|
pub const SYS_GETUID: usize = 199;
|
||||||
pub const SYS_IOPL: usize = 110;
|
pub const SYS_IOPL: usize = 110;
|
||||||
|
pub const SYS_KILL: usize = 37;
|
||||||
pub const SYS_NANOSLEEP: usize =162;
|
pub const SYS_NANOSLEEP: usize =162;
|
||||||
pub const SYS_PHYSALLOC: usize =945;
|
pub const SYS_PHYSALLOC: usize =945;
|
||||||
pub const SYS_PHYSFREE: usize = 946;
|
pub const SYS_PHYSFREE: usize = 946;
|
||||||
|
|
Loading…
Reference in a new issue