From 8f452b0b0fe1011d7fa1e2f356efab626be35bad Mon Sep 17 00:00:00 2001 From: 4lDO2 <4lDO2@protonmail.com> Date: Mon, 8 Jul 2024 16:02:46 +0200 Subject: [PATCH] WIP: continue the process transition --- src/context/context.rs | 53 ++--------- src/context/list.rs | 15 --- src/context/mod.rs | 7 ++ src/context/process.rs | 84 +++++++++++++++++ src/context/switch.rs | 6 +- src/main.rs | 6 +- src/syscall/fs.rs | 16 ++-- src/syscall/mod.rs | 22 ++--- src/syscall/privilege.rs | 115 ++++++++++------------- src/syscall/process.rs | 198 +++++++++++++++++++-------------------- 10 files changed, 268 insertions(+), 254 deletions(-) create mode 100644 src/context/process.rs diff --git a/src/context/context.rs b/src/context/context.rs index fb72f73d8a..0ae9109607 100644 --- a/src/context/context.rs +++ b/src/context/context.rs @@ -27,7 +27,7 @@ use ::core::sync::atomic::AtomicUsize; use super::{ empty_cr3, - memory::{AddrSpaceWrapper, GrantFileRef}, + memory::{AddrSpaceWrapper, GrantFileRef}, process::{Process, ProcessId}, }; int_like!(ContextId, AtomicContextId, usize, AtomicUsize); @@ -71,8 +71,8 @@ pub enum HardBlockedReason { #[derive(Copy, Clone, Debug)] pub struct WaitpidKey { - pub pid: Option, - pub pgid: Option, + pub pid: Option, + pub pgid: Option, } impl Ord for WaitpidKey { @@ -134,31 +134,11 @@ pub struct Context { /// The internal context ID of this context pub cid: ContextId, /// The process ID of this context - pub pid: ContextId, - /// The group ID of this context - pub pgid: ContextId, - /// The ID of the parent context - pub ppid: ContextId, - /// The ID of the session - pub session_id: ContextId, - /// The real user id - pub ruid: u32, - /// The real group id - pub rgid: u32, - /// The real namespace id - pub rns: SchemeNamespace, - /// The effective user id - pub euid: u32, - /// The effective group id - pub egid: u32, - /// The effective namespace id - pub ens: SchemeNamespace, - + pub pid: ProcessId, + /// Process state shared with other threads + pub process: Arc>, /// Signal handler pub sig: Option, - - /// Process umask - pub umask: usize, /// Status of context pub status: Status, pub status_reason: &'static str, @@ -186,8 +166,6 @@ pub struct Context { /// Tail buffer to use when system call buffers are not page aligned // TODO: Store in user memory? pub syscall_tail: Option, - /// Context is being waited on - pub waitpid: Arc>, /// Context should wake up at specified time pub wake: Option, /// The architecture specific context @@ -209,10 +187,6 @@ pub struct Context { /// All contexts except kmain will primarily live in userspace, and enter the kernel only when /// interrupts or syscalls occur. This flag is set for all contexts but kmain. pub userspace: bool, - /// A somewhat hacky way to initially stop a context when creating - /// a new instance of the proc: scheme, entirely separate from - /// signals or any other way to restart a process. - pub ptrace_stop: bool, pub being_sigkilled: bool, pub fmap_ret: Option, } @@ -233,21 +207,12 @@ pub struct SignalState { } impl Context { - pub fn new(cid: ContextId, pid: ContextId) -> Result { + pub fn new(cid: ContextId, pid: ContextId, process: Arc>) -> Result { let this = Context { cid, pid, - pgid: pid, - ppid: ContextId::from(0), - session_id: ContextId::from(0), - ruid: 0, - rgid: 0, - rns: SchemeNamespace::from(0), - euid: 0, - egid: 0, - ens: SchemeNamespace::from(0), + process, sig: None, - umask: 0o022, status: Status::HardBlocked { reason: HardBlockedReason::NotYetStarted, }, @@ -260,7 +225,6 @@ impl Context { inside_syscall: false, syscall_head: Some(RaiiFrame::allocate()?), syscall_tail: Some(RaiiFrame::allocate()?), - waitpid: Arc::new(WaitMap::new()), wake: None, arch: arch::Context::new(), kfx: AlignedBox::<[u8], { arch::KFX_ALIGN }>::try_zeroed_slice(crate::arch::kfx_size())?, @@ -269,7 +233,6 @@ impl Context { name: Cow::Borrowed(""), files: Arc::new(RwLock::new(Vec::new())), userspace: false, - ptrace_stop: false, fmap_ret: None, being_sigkilled: false, diff --git a/src/context/list.rs b/src/context/list.rs index f7cc4e040a..1b71f7253f 100644 --- a/src/context/list.rs +++ b/src/context/list.rs @@ -33,21 +33,6 @@ impl ContextList { self.map.get(&id) } - /// Get an iterator of all parents - pub fn ancestors( - &'_ self, - id: ContextId, - ) -> impl Iterator>)> + '_ { - iter::successors( - self.get(id).map(|context| (id, context)), - move |(_id, context)| { - let context = context.read(); - let id = context.ppid; - self.get(id).map(|context| (id, context)) - }, - ) - } - /// Get the current context. pub fn current(&self) -> Option<&Arc>> { self.map.get(&super::current_cid()) diff --git a/src/context/mod.rs b/src/context/mod.rs index aedbac3631..a1896997b1 100644 --- a/src/context/mod.rs +++ b/src/context/mod.rs @@ -14,6 +14,7 @@ use crate::{ syscall::error::{Error, Result, ESRCH}, }; +use self::process::ProcessId; pub use self::{ context::{BorrowedHtBuf, Context, ContextId, Status, WaitpidKey}, list::ContextList, @@ -47,6 +48,9 @@ pub mod file; /// Memory struct - contains a set of pages for a context pub mod memory; +/// Process handling - TODO move to userspace +pub mod process; + /// Signal handling pub mod signal; @@ -103,6 +107,9 @@ pub fn contexts_mut() -> RwLockWriteGuard<'static, ContextList> { pub fn current_cid() -> ContextId { PercpuBlock::current().switch_internals.current_cid() } +pub fn current_pid() -> Result { + Ok(current()?.read().pid) +} pub fn current() -> Result>> { contexts() diff --git a/src/context/process.rs b/src/context/process.rs new file mode 100644 index 0000000000..aa6d03667c --- /dev/null +++ b/src/context/process.rs @@ -0,0 +1,84 @@ +// TODO: move all this code to userspace +use alloc::collections::BTreeMap; +use alloc::sync::{Arc, Weak}; +use alloc::vec::Vec; + +use spin::RwLock; +use spinning_top::RwSpinlock; + +use syscall::{Error, Result, ESRCH}; + +use crate::scheme::SchemeNamespace; +use crate::sync::WaitMap; + +use crate::context::{self, Context, WaitpidKey}; + +int_like!(ProcessId, usize); + +#[derive(Debug)] +pub struct Process { + /// The process ID of this process + pub pid: ProcessId, + /// The group ID of this process + pub pgid: ProcessId, + /// The ID of the parent process + pub ppid: ProcessId, + /// The ID of the session + pub session_id: ProcessId, + /// The real user id + pub ruid: u32, + /// The real group id + pub rgid: u32, + /// The real namespace id + pub rns: SchemeNamespace, + /// The effective user id + pub euid: u32, + /// The effective group id + pub egid: u32, + /// The effective namespace id + pub ens: SchemeNamespace, + /// Process umask + pub umask: usize, + /// Context is being waited on + pub waitpid: WaitMap, + pub threads: Vec>>, +} + +pub static PROCESSES: RwLock>>> = RwLock::new(BTreeMap::new()); + +/// Get an iterator of all parents +pub fn ancestors( + list: &BTreeSet, + id: ProcessId, +) -> impl Iterator>)> + '_ { + core::iter::successors( + list.get(&id).map(|process| (id, process)), + move |(_id, process)| { + let context = process.read(); + let id = process.ppid; + list.get(&id).map(|context| (id, context)) + }, + ) +} + +impl Ord for Process { + fn cmp(&self, other: &Self) -> core::cmp::Ordering { + Ord::cmp(&self.pid, &other.pid) + } +} +impl PartialOrd for Process { + fn partial_cmp(&self, other: &Self) -> Option { + Some(Ord::cmp(&self.pid, &other.pid)) + } +} + +pub fn current() -> Result>> { + let pid = context::current()?.read().pid; + PROCESSES.read().get(&pid).ok_or(Error::new(ESRCH)) +} +impl PartialEq for Process { + fn eq(&self, other: &Self) -> bool { + Ord::cmp(self, other) == core::cmp::Ordering::Equal + } +} +impl Eq for Process {} diff --git a/src/context/switch.rs b/src/context/switch.rs index b5e8c85a7e..5b86fb2a09 100644 --- a/src/context/switch.rs +++ b/src/context/switch.rs @@ -131,7 +131,7 @@ pub fn switch() -> SwitchResult { let mut skip_idle = true; // Locate next context - for (pid, next_context_lock) in contexts + for (cid, next_context_lock) in contexts // Include all contexts with IDs greater than the current... .range((Bound::Excluded(prev_context_guard.cid), Bound::Unbounded)) .chain( @@ -146,7 +146,7 @@ pub fn switch() -> SwitchResult { ) // ... but not the current context, which is already locked { - if pid == &idle_id && skip_idle { + if cid == &idle_id && skip_idle { // Skip idle process the first time it shows up skip_idle = false; continue; @@ -201,7 +201,7 @@ pub fn switch() -> SwitchResult { })); let (ptrace_session, ptrace_flags) = if let Some((session, bp)) = ptrace::sessions() - .get(&next_context.pid) + .get(&next_context.cid) .map(|s| (Arc::downgrade(s), s.data.lock().breakpoint)) { (Some(session), bp.map_or(PtraceFlags::empty(), |f| f.flags)) diff --git a/src/main.rs b/src/main.rs index add30e69d0..80c4ff354b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -200,10 +200,12 @@ fn kmain(cpu_count: u32, bootstrap: Bootstrap) -> ! { match context::contexts_mut().spawn(true, userspace_init) { Ok(context_lock) => { let mut context = context_lock.write(); - context.rns = SchemeNamespace::from(1); - context.ens = SchemeNamespace::from(1); context.status = context::Status::Runnable; context.name = "bootstrap".into(); + + let mut process = context.process.write(); + process.rns = SchemeNamespace::from(1); + process.ens = SchemeNamespace::from(1); } Err(err) => { panic!("failed to spawn userspace_init: {:?}", err); diff --git a/src/syscall/fs.rs b/src/syscall/fs.rs index a081d1eb6f..f971a53a6d 100644 --- a/src/syscall/fs.rs +++ b/src/syscall/fs.rs @@ -7,7 +7,7 @@ use crate::{ context::{ self, file::{FileDescription, FileDescriptor, InternalFlags}, - memory::{AddrSpace, PageSpan}, + memory::{AddrSpace, PageSpan}, process, }, paging::{Page, VirtualAddress, PAGE_SIZE}, scheme::{self, CallerCtx, FileHandle, KernelScheme, OpenResult}, @@ -54,13 +54,13 @@ const PATH_MAX: usize = PAGE_SIZE; /// Open syscall pub fn open(raw_path: UserSliceRo, flags: usize) -> Result { - let (pid, uid, gid, scheme_ns, umask) = match context::current()?.read() { - ref context => ( - context.pid.into(), - context.euid, - context.egid, - context.ens, - context.umask, + let (pid, uid, gid, scheme_ns, umask) = match process::current()?.read() { + ref process => ( + process.pid.into(), + process.euid, + process.egid, + process.ens, + process.umask, ), }; diff --git a/src/syscall/mod.rs b/src/syscall/mod.rs index d508bb4f34..3bac33565a 100644 --- a/src/syscall/mod.rs +++ b/src/syscall/mod.rs @@ -25,7 +25,7 @@ use self::{ use crate::{interrupt::InterruptStack, percpu::PercpuBlock}; use crate::{ - context::{memory::AddrSpace, ContextId}, + context::{memory::AddrSpace, process::ProcessId}, scheme::{memory::MemoryScheme, FileHandle, SchemeNamespace}, }; @@ -205,14 +205,14 @@ pub fn syscall( .map(|()| 0) } SYS_FUTEX => futex(b, c, d, e, f), - SYS_GETPID => getpid().map(ContextId::into), - SYS_GETPGID => getpgid(ContextId::from(b)).map(ContextId::into), - SYS_GETPPID => getppid().map(ContextId::into), + SYS_GETPID => getpid().map(ProcessId::into), + SYS_GETPGID => getpgid(ProcessId::from(b)).map(ProcessId::into), + SYS_GETPPID => getppid().map(ProcessId::into), SYS_EXIT => exit(b), - SYS_KILL => kill(ContextId::from(b), c, false), + SYS_KILL => kill(ProcessId::from(b), c, false), SYS_WAITPID => waitpid( - ContextId::from(b), + ProcessId::from(b), if c == 0 { None } else { @@ -220,7 +220,7 @@ pub fn syscall( }, WaitFlags::from_bits_truncate(d), ) - .map(ContextId::into), + .map(ProcessId::into), SYS_IOPL => iopl(b), SYS_GETEGID => getegid(), SYS_GETENS => getens(), @@ -234,10 +234,10 @@ pub fn syscall( c.checked_mul(core::mem::size_of::<[usize; 2]>()) .ok_or(Error::new(EOVERFLOW))?, )?), - SYS_SETPGID => setpgid(ContextId::from(b), ContextId::from(c)), - SYS_SETREUID => setreuid(b as u32, c as u32), - SYS_SETRENS => setrens(SchemeNamespace::from(b), SchemeNamespace::from(c)), - SYS_SETREGID => setregid(b as u32, c as u32), + SYS_SETPGID => setpgid(ProcessId::from(b), ProcessId::from(c)).map(|()| 0), + SYS_SETREUID => setreuid(b as u32, c as u32).map(|()| 0), + SYS_SETRENS => setrens(SchemeNamespace::from(b), SchemeNamespace::from(c)).map(|()| 0), + SYS_SETREGID => setregid(b as u32, c as u32).map(|()| 0), SYS_UMASK => umask(b), SYS_VIRTTOPHYS => virttophys(b), diff --git a/src/syscall/privilege.rs b/src/syscall/privilege.rs index b12d239edb..ea69478c79 100644 --- a/src/syscall/privilege.rs +++ b/src/syscall/privilege.rs @@ -1,7 +1,7 @@ use alloc::vec::Vec; use crate::{ - context, + context::{self, process}, scheme::{self, SchemeNamespace}, syscall::error::*, }; @@ -12,50 +12,32 @@ use super::{ }; pub fn getegid() -> Result { - let contexts = context::contexts(); - let context_lock = contexts.current().ok_or(Error::new(ESRCH))?; - let context = context_lock.read(); - Ok(context.egid as usize) + Ok(process::current()?.read().egid as usize) } pub fn getens() -> Result { - let contexts = context::contexts(); - let context_lock = contexts.current().ok_or(Error::new(ESRCH))?; - let context = context_lock.read(); - Ok(context.ens.into()) + Ok(process::current()?.read().ens.into()) } pub fn geteuid() -> Result { - let contexts = context::contexts(); - let context_lock = contexts.current().ok_or(Error::new(ESRCH))?; - let context = context_lock.read(); - Ok(context.euid as usize) + Ok(process::current()?.read().euid as usize) } pub fn getgid() -> Result { - let contexts = context::contexts(); - let context_lock = contexts.current().ok_or(Error::new(ESRCH))?; - let context = context_lock.read(); - Ok(context.rgid as usize) + Ok(process::current()?.read().rgid as usize) } pub fn getns() -> Result { - let contexts = context::contexts(); - let context_lock = contexts.current().ok_or(Error::new(ESRCH))?; - let context = context_lock.read(); - Ok(context.rns.into()) + Ok(process::current()?.read().rns.into()) } pub fn getuid() -> Result { - let contexts = context::contexts(); - let context_lock = contexts.current().ok_or(Error::new(ESRCH))?; - let context = context_lock.read(); - Ok(context.ruid as usize) + Ok(process::current()?.read().ruid as usize) } pub fn mkns(mut user_buf: UserSliceRo) -> Result { - let (uid, from) = match context::current()?.read() { - ref context => (context.euid, context.ens), + let (uid, from) = match process::current()?.read() { + ref process => (process.euid, process.ens), }; // TODO: Lift this restriction later? @@ -86,18 +68,17 @@ pub fn mkns(mut user_buf: UserSliceRo) -> Result { Ok(to.into()) } -pub fn setregid(rgid: u32, egid: u32) -> Result { - let contexts = context::contexts(); - let context_lock = contexts.current().ok_or(Error::new(ESRCH))?; - let mut context = context_lock.write(); +pub fn setregid(rgid: u32, egid: u32) -> Result<()> { + let process_lock = process::current()?; + let mut process = process_lock.write(); - let setrgid = if context.euid == 0 { + let setrgid = if process.euid == 0 { // Allow changing RGID if root true - } else if rgid == context.egid { + } else if rgid == process.egid { // Allow changing RGID if used for EGID true - } else if rgid == context.rgid { + } else if rgid == process.rgid { // Allow changing RGID if used for RGID true } else if rgid as i32 == -1 { @@ -108,13 +89,13 @@ pub fn setregid(rgid: u32, egid: u32) -> Result { return Err(Error::new(EPERM)); }; - let setegid = if context.euid == 0 { + let setegid = if process.euid == 0 { // Allow changing EGID if root true - } else if egid == context.egid { + } else if egid == process.egid { // Allow changing EGID if used for EGID true - } else if egid == context.rgid { + } else if egid == process.rgid { // Allow changing EGID if used for RGID true } else if egid as i32 == -1 { @@ -126,20 +107,19 @@ pub fn setregid(rgid: u32, egid: u32) -> Result { }; if setrgid { - context.rgid = rgid; + process.rgid = rgid; } if setegid { - context.egid = egid; + process.egid = egid; } - Ok(0) + Ok(()) } -pub fn setrens(rns: SchemeNamespace, ens: SchemeNamespace) -> Result { - let contexts = context::contexts(); - let context_lock = contexts.current().ok_or(Error::new(ESRCH))?; - let mut context = context_lock.write(); +pub fn setrens(rns: SchemeNamespace, ens: SchemeNamespace) -> Result<()> { + let process_lock = process::current()?; + let mut process = process_lock.write(); let setrns = if rns.get() as isize == -1 { // Ignore RNS if -1 is passed @@ -147,16 +127,16 @@ pub fn setrens(rns: SchemeNamespace, ens: SchemeNamespace) -> Result { } else if rns.get() == 0 { // Allow entering capability mode true - } else if context.rns.get() == 0 { + } else if process.rns.get() == 0 { // Do not allow leaving capability mode return Err(Error::new(EPERM)); - } else if context.euid == 0 { + } else if process.euid == 0 { // Allow setting RNS if root true - } else if rns == context.ens { + } else if rns == process.ens { // Allow setting RNS if used for ENS true - } else if rns == context.rns { + } else if rns == process.rns { // Allow setting RNS if used for RNS true } else { @@ -170,16 +150,16 @@ pub fn setrens(rns: SchemeNamespace, ens: SchemeNamespace) -> Result { } else if ens.get() == 0 { // Allow entering capability mode true - } else if context.ens.get() == 0 { + } else if process.ens.get() == 0 { // Do not allow leaving capability mode return Err(Error::new(EPERM)); - } else if context.euid == 0 { + } else if process.euid == 0 { // Allow setting ENS if root true - } else if ens == context.ens { + } else if ens == process.ens { // Allow setting ENS if used for ENS true - } else if ens == context.rns { + } else if ens == process.rns { // Allow setting ENS if used for RNS true } else { @@ -189,29 +169,28 @@ pub fn setrens(rns: SchemeNamespace, ens: SchemeNamespace) -> Result { if setrns { assert_ne!(rns.get() as isize, -1); - context.rns = rns; + process.rns = rns; } if setens { assert_ne!(ens.get() as isize, -1); - context.ens = ens; + process.ens = ens; } - Ok(0) + Ok(()) } -pub fn setreuid(ruid: u32, euid: u32) -> Result { - let contexts = context::contexts(); - let context_lock = contexts.current().ok_or(Error::new(ESRCH))?; - let mut context = context_lock.write(); +pub fn setreuid(ruid: u32, euid: u32) -> Result<()> { + let process_lock = process::current()?; + let mut process = process_lock.write(); - let setruid = if context.euid == 0 { + let setruid = if process.euid == 0 { // Allow setting RUID if root true - } else if ruid == context.euid { + } else if ruid == process.euid { // Allow setting RUID if used for EUID true - } else if ruid == context.ruid { + } else if ruid == process.ruid { // Allow setting RUID if used for RUID true } else if ruid as i32 == -1 { @@ -222,13 +201,13 @@ pub fn setreuid(ruid: u32, euid: u32) -> Result { return Err(Error::new(EPERM)); }; - let seteuid = if context.euid == 0 { + let seteuid = if process.euid == 0 { // Allow setting EUID if root true - } else if euid == context.euid { + } else if euid == process.euid { // Allow setting EUID if used for EUID true - } else if euid == context.ruid { + } else if euid == process.ruid { // Allow setting EUID if used for RUID true } else if euid as i32 == -1 { @@ -240,12 +219,12 @@ pub fn setreuid(ruid: u32, euid: u32) -> Result { }; if setruid { - context.ruid = ruid; + process.ruid = ruid; } if seteuid { - context.euid = euid; + process.euid = euid; } - Ok(0) + Ok(()) } diff --git a/src/syscall/process.rs b/src/syscall/process.rs index fa126b931e..e101db66cb 100644 --- a/src/syscall/process.rs +++ b/src/syscall/process.rs @@ -6,8 +6,7 @@ use rmm::Arch; use spin::RwLock; use crate::context::{ - memory::{AddrSpace, Grant, PageSpan}, - ContextId, WaitpidKey, + memory::{AddrSpace, Grant, PageSpan}, process::{self, ProcessId}, WaitpidKey }; use crate::{ @@ -62,17 +61,18 @@ pub fn exit(status: usize) -> ! { // PGID and PPID must be grabbed after close, as context switches could change PGID or PPID if parent exits let (pgid, ppid) = { let context = context_lock.read(); - (context.pgid, context.ppid) + let process = context.process.read(); + (process.pgid, process.ppid) }; let _ = kill(ppid, SIGCHLD, true); - // Transfer child processes to parent + // Transfer child processes to parent (TODO: init) { - let contexts = context::contexts(); - for (_id, context_lock) in contexts.iter() { - let mut context = context_lock.write(); - if context.ppid == pid { - context.ppid = ppid; + let processes = context::process::PROCESSES.read(); + for (pid, process_lock) in processes.iter() { + let mut process = process_lock.write(); + if process.ppid == pid { + process.ppid = ppid; } } } @@ -113,37 +113,32 @@ pub fn exit(status: usize) -> ! { unreachable!(); } -pub fn getpid() -> Result { - Ok(context::current()?.read().pid) +pub fn getpid() -> Result { + context::current_pid() } -pub fn getpgid(pid: ContextId) -> Result { - let contexts = context::contexts(); - let context_lock = if pid.get() == 0 { - contexts.current().ok_or(Error::new(ESRCH))? +pub fn getpgid(pid: ProcessId) -> Result { + let process_lock = if pid.get() == 0 { + process::current()? } else { - contexts.get(pid).ok_or(Error::new(ESRCH))? + Arc::clone(process::PROCESSES.get(&pid).ok_or(Error::new(ESRCH))?) }; - let context = context_lock.read(); - Ok(context.pgid) + let process = process_lock.read(); + Ok(process.pgid) } -pub fn getppid() -> Result { - let contexts = context::contexts(); - let context_lock = contexts.current().ok_or(Error::new(ESRCH))?; - let context = context_lock.read(); - Ok(context.ppid) +pub fn getppid() -> Result { + Ok(process::current()?.read().ppid) } -pub fn kill(pid: ContextId, sig: usize, parent_sigchld: bool) -> Result { +pub fn kill(pid: ProcessId, sig: usize, parent_sigchld: bool) -> Result { let (ruid, euid, current_pgid) = { - let contexts = context::contexts(); - let context_lock = contexts.current().ok_or(Error::new(ESRCH))?; - let context = context_lock.read(); - (context.ruid, context.euid, context.pgid) + let process_lock = process::current?; + let process = process_lock.read(); + (process.ruid, process.euid, process.pgid) }; - if euid == 0 && pid == ContextId::new(1) { + if euid == 0 && pid.get() == 1 { match sig { SIGTERM => unsafe { crate::stop::kreset() }, SIGKILL => unsafe { crate::stop::kstop() }, @@ -161,19 +156,19 @@ pub fn kill(pid: ContextId, sig: usize, parent_sigchld: bool) -> Result { let mut killed_self = false; { - let contexts = context::contexts(); + let processes = process::PROCESSES.read(); enum SendResult { Forbidden, Succeeded, SucceededSigchld { - ppid: ContextId, - pgid: ContextId, + ppid: ProcessId, + pgid: ProcessId, orig_signal: usize, }, SucceededSigcont { - ppid: ContextId, - pgid: ContextId, + ppid: ProcessId, + pgid: ProcessId, }, } @@ -264,8 +259,8 @@ pub fn kill(pid: ContextId, sig: usize, parent_sigchld: bool) -> Result { } => { sent += 1; let waitpid = Arc::clone( - &context::contexts() - .get(ppid) + &process::PROCESSES.read() + .get(&ppid) .ok_or(Error::new(ESRCH))? .read() .waitpid, @@ -282,8 +277,8 @@ pub fn kill(pid: ContextId, sig: usize, parent_sigchld: bool) -> Result { SendResult::SucceededSigcont { ppid, pgid } => { sent += 1; let waitpid = Arc::clone( - &context::contexts() - .get(ppid) + &process::PROCESSES.read() + .get(&ppid) .ok_or(Error::new(ESRCH))? .read() .waitpid, @@ -302,20 +297,22 @@ pub fn kill(pid: ContextId, sig: usize, parent_sigchld: bool) -> Result { if pid.get() as isize > 0 { // Send to a single process - if let Some(context_lock) = contexts.get(pid) { + if let Some(process_lock) = processes.get(&pid) { found += 1; - let result = send(&mut *context_lock.write()); + let result = send(&mut *process_lock.write()); handle_send(pid, result)?; } } else if pid.get() == 1_usize.wrapping_neg() { // Send to every process with permission, except for init - for (pid, context_lock) in contexts.iter() { - let mut context = context_lock.write(); + for (pid, process_lock) in processes.iter() { + let mut process = process_lock.write(); - if context.pid.get() <= 2 { + if process.pid.get() <= 2 { continue; } found += 1; + let context_lock = process.threads.first().ok_or(Error::new(ESRCH))?.upgrade().ok_or(Error::new(ESRCH))?; + let context = context_lock.write(); let result = send(&mut *context); drop(context); @@ -325,12 +322,12 @@ pub fn kill(pid: ContextId, sig: usize, parent_sigchld: bool) -> Result { let pgid = if pid.get() == 0 { current_pgid } else { - ContextId::from(pid.get().wrapping_neg()) + ProcessId::from(pid.get().wrapping_neg()) }; // Send to every process in the process group whose ID - for (pid, context_lock) in contexts.iter() { - let mut context = context_lock.write(); + for (pid, process_lock) in processes.iter() { + let mut context = process_lock.write(); if context.pgid != pgid { continue; @@ -367,29 +364,25 @@ pub fn mprotect(address: usize, size: usize, flags: MapFlags) -> Result<()> { AddrSpace::current()?.mprotect(span, flags) } -pub fn setpgid(pid: ContextId, pgid: ContextId) -> Result { - let contexts = context::contexts(); +pub fn setpgid(pid: ProcessId, pgid: ProcessId) -> Result<()> { + let current_pid = context::current_pid()?; - let current_pid = { - let context_lock = contexts.current().ok_or(Error::new(ESRCH))?; - let context = context_lock.read(); - context.pid - }; + let processes = process::PROCESSES.read(); - let context_lock = if pid.get() == 0 { - contexts.current().ok_or(Error::new(ESRCH))? + let process_lock = if pid.get() == 0 { + process::current()? } else { - contexts.get(pid).ok_or(Error::new(ESRCH))? + Arc::clone(processes.get(&pid).ok_or(Error::new(ESRCH))?) }; - let mut context = context_lock.write(); - if context.pid == current_pid || context.ppid == current_pid { + let mut process = process_lock.write(); + if process.pid == current_pid || process.ppid == current_pid { if pgid.get() == 0 { - context.pgid = context.pid; + process.pgid = process.pid; } else { - context.pgid = pgid; + process.pgid = pgid; } - Ok(0) + Ok(()) } else { Err(Error::new(ESRCH)) } @@ -398,48 +391,48 @@ pub fn setpgid(pid: ContextId, pgid: ContextId) -> Result { pub fn umask(mask: usize) -> Result { let previous; { - let contexts = context::contexts(); - let context_lock = contexts.current().ok_or(Error::new(ESRCH))?; - let mut context = context_lock.write(); - previous = context.umask; - context.umask = mask; + let process_lock = process::current()?; + let mut process = process_lock.write(); + previous = process.umask; + process.umask = mask; } Ok(previous) } -fn reap(pid: ContextId) -> Result { +fn reap(pid: ProcessId) -> Result { + let process_lock = Arc::clone(process::PROCESSES.read().get(&pid).ok_or(Error::new(ESRCH))?); + // Spin until not running - let mut running = true; - while running { + loop { // TODO: exit WaitCondition? { - let contexts = context::contexts(); - let context_lock = contexts.get(pid).ok_or(Error::new(ESRCH))?; - let context = context_lock.read(); - running = context.running; + let mut process = process_lock.read(); + if process.threads.iter().all(|t| t.upgrade().map_or(true, |t| !t.read().running)) { + break; + } } + // TODO: context switch? interrupt::pause(); } - let _ = context::contexts_mut() - .remove(pid) + let _ = process::PROCESSES.write() + .remove(&pid) .ok_or(Error::new(ESRCH))?; Ok(pid) } pub fn waitpid( - pid: ContextId, + pid: ProcessId, status_ptr: Option, flags: WaitFlags, -) -> Result { - let (ppid, waitpid) = { - let contexts = context::contexts(); - let context_lock = contexts.current().ok_or(Error::new(ESRCH))?; - let context = context_lock.read(); - (context.pid, Arc::clone(&context.waitpid)) +) -> Result { + let (ppid, process_lock) = { + let process_lock = process::current()?; + let process = process_lock.read(); + (process.pid, process_lock) }; let write_status = |value| { status_ptr @@ -447,7 +440,7 @@ pub fn waitpid( .unwrap_or(Ok(())) }; - let grim_reaper = |w_pid: ContextId, status: usize| -> Option> { + let grim_reaper = |w_pid: ProcessId, status: usize| -> Option> { if wifcontinued(status) { if flags & WCONTINUED == WCONTINUED { Some(write_status(status).map(|()| w_pid)) @@ -471,10 +464,10 @@ pub fn waitpid( { let mut found = false; - let contexts = context::contexts(); - for (_id, context_lock) in contexts.iter() { - let context = context_lock.read(); - if context.ppid == ppid { + let contexts = process::PROCESSES.read(); + for (_id, process_lock) in processs.iter() { + let process = process_lock.read(); + if process.ppid == ppid { found = true; break; } @@ -489,23 +482,23 @@ pub fn waitpid( if let Some((_wid, (w_pid, status))) = waitpid.receive_any_nonblock() { grim_reaper(w_pid, status) } else { - Some(Ok(ContextId::from(0))) + Some(Ok(ProcessId::from(0))) } } else { let (_wid, (w_pid, status)) = waitpid.receive_any("waitpid any"); grim_reaper(w_pid, status) } } else if (pid.get() as isize) < 0 { - let pgid = ContextId::from(-(pid.get() as isize) as usize); + let pgid = ProcessId::from(-(pid.get() as isize) as usize); // Check for existence of child in process group PGID { let mut found = false; - let contexts = context::contexts(); - for (_id, context_lock) in contexts.iter() { - let context = context_lock.read(); - if context.pgid == pgid { + let processes = process::PROCESSES.read(); + for (_pid, process_lock) in processes.iter() { + let process = process_lock.read(); + if process.pgid == pgid { found = true; break; } @@ -523,7 +516,7 @@ pub fn waitpid( }) { grim_reaper(w_pid, status) } else { - Some(Ok(ContextId::from(0))) + Some(Ok(ProcessId::from(0))) } } else { let (w_pid, status) = waitpid.receive( @@ -537,17 +530,18 @@ pub fn waitpid( } } else { let hack_status = { - let contexts = context::contexts(); - let context_lock = contexts.get(pid).ok_or(Error::new(ECHILD))?; - let mut context = context_lock.write(); - if context.ppid != ppid { + let processes = process::PROCESSES.read(); + let process_lock = processes.get(&pid).ok_or(Error::new(ECHILD))?; + let process = process_lock.read(); + + if process.ppid != ppid { println!( "TODO: Hack for rustc - changing ppid of {} from {} to {}", - context.pid.get(), - context.ppid.get(), + process.pid.get(), + process.ppid.get(), ppid.get() ); - context.ppid = ppid; + process.ppid = ppid; //return Err(Error::new(ECHILD)); Some(context.status.clone()) } else { @@ -568,7 +562,7 @@ pub fn waitpid( }) { grim_reaper(w_pid, status) } else { - Some(Ok(ContextId::from(0))) + Some(Ok(ProcessId::from(0))) } } else { let (w_pid, status) = waitpid.receive(