Add sys scheme to allow inspection of processes. WIP: Signals.
This commit is contained in:
		
							parent
							
								
									224c43f761
								
							
						
					
					
						commit
						d18bf07f3e
					
				
					 9 changed files with 445 additions and 64 deletions
				
			
		| 
						 | 
				
			
			@ -4,7 +4,7 @@ use alloc::boxed::Box;
 | 
			
		|||
use collections::{BTreeMap, Vec};
 | 
			
		||||
use core::{mem, str};
 | 
			
		||||
use core::ops::DerefMut;
 | 
			
		||||
use spin::Mutex;
 | 
			
		||||
use spin::{Mutex, RwLock};
 | 
			
		||||
 | 
			
		||||
use arch;
 | 
			
		||||
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 stack_option = None;
 | 
			
		||||
        let grants;
 | 
			
		||||
        let name;
 | 
			
		||||
        let cwd;
 | 
			
		||||
        let env;
 | 
			
		||||
        let files;
 | 
			
		||||
| 
						 | 
				
			
			@ -186,6 +187,12 @@ pub fn clone(flags: usize, stack_base: usize) -> Result<usize> {
 | 
			
		|||
                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 {
 | 
			
		||||
                cwd = context.cwd.clone();
 | 
			
		||||
            } else {
 | 
			
		||||
| 
						 | 
				
			
			@ -382,6 +389,8 @@ pub fn clone(flags: usize, stack_base: usize) -> Result<usize> {
 | 
			
		|||
                context.stack = Some(stack);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            context.name = name;
 | 
			
		||||
 | 
			
		||||
            context.cwd = cwd;
 | 
			
		||||
 | 
			
		||||
            context.env = env;
 | 
			
		||||
| 
						 | 
				
			
			@ -395,61 +404,6 @@ pub fn clone(flags: usize, stack_base: usize) -> Result<usize> {
 | 
			
		|||
    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> {
 | 
			
		||||
    let entry;
 | 
			
		||||
    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
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        let (uid, gid) = {
 | 
			
		||||
        let (uid, gid, canonical) = {
 | 
			
		||||
            let contexts = context::contexts();
 | 
			
		||||
            let context_lock = contexts.current().ok_or(Error::new(ESRCH))?;
 | 
			
		||||
            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();
 | 
			
		||||
        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 mut context = context_lock.write();
 | 
			
		||||
 | 
			
		||||
                    // Set name
 | 
			
		||||
                    context.name = Arc::new(Mutex::new(canonical));
 | 
			
		||||
 | 
			
		||||
                    // Unmap previous image and stack
 | 
			
		||||
                    context.image.clear();
 | 
			
		||||
                    drop(context.heap.take());
 | 
			
		||||
| 
						 | 
				
			
			@ -639,6 +596,69 @@ 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();
 | 
			
		||||
    {
 | 
			
		||||
        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> {
 | 
			
		||||
    let contexts = context::contexts();
 | 
			
		||||
    let context_lock = contexts.current().ok_or(Error::new(ESRCH))?;
 | 
			
		||||
| 
						 | 
				
			
			@ -679,6 +699,69 @@ pub fn iopl(_level: usize) -> Result<usize> {
 | 
			
		|||
    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> {
 | 
			
		||||
    allocate_frames((size + 4095)/4096).ok_or(Error::new(ENOMEM)).map(|frame| frame.start_address().get())
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue