use core::ops::{Deref, DerefMut}; // 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::{CallerCtx, SchemeNamespace}; use crate::sync::WaitMap; use crate::context::{self, Context, WaitpidKey}; int_like!(ProcessId, usize); #[derive(Debug)] pub struct Process { pub info: ProcessInfo, /// Context is being waited on pub waitpid: Arc>, /// Threads of process pub threads: Vec>>, } #[derive(Debug, Clone, Copy)] pub struct ProcessInfo { /// 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, } impl Deref for Process { type Target = ProcessInfo; fn deref(&self) -> &Self::Target { &self.info } } impl DerefMut for Process { fn deref_mut(&mut self) -> &mut Self::Target { &mut self.info } } pub static PROCESSES: RwLock>>> = RwLock::new(BTreeMap::new()); /// Get an iterator of all parents pub fn ancestors( list: &BTreeMap>>, id: ProcessId, ) -> impl Iterator>)> + '_ { core::iter::successors( list.get(&id).map(|process| (id, process)), move |(_id, process)| { let process = process.read(); let id = process.ppid; list.get(&id).map(|process| (id, process)) }, ) } pub fn current() -> Result>> { let pid = context::current()?.read().pid; Ok(Arc::clone(PROCESSES.read().get(&pid).ok_or(Error::new(ESRCH))?)) } impl Process { pub fn caller_ctx(&self) -> CallerCtx { CallerCtx { pid: self.pid.into(), uid: self.euid, gid: self.egid, } } }