WIP: continue the process transition
This commit is contained in:
+8
-45
@@ -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<ContextId>,
|
||||
pub pgid: Option<ContextId>,
|
||||
pub pid: Option<ProcessId>,
|
||||
pub pgid: Option<ProcessId>,
|
||||
}
|
||||
|
||||
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<RwLock<Process>>,
|
||||
/// Signal handler
|
||||
pub sig: Option<SignalState>,
|
||||
|
||||
/// 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<RaiiFrame>,
|
||||
/// Context is being waited on
|
||||
pub waitpid: Arc<WaitMap<WaitpidKey, (ContextId, usize)>>,
|
||||
/// Context should wake up at specified time
|
||||
pub wake: Option<u128>,
|
||||
/// 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<Frame>,
|
||||
}
|
||||
@@ -233,21 +207,12 @@ pub struct SignalState {
|
||||
}
|
||||
|
||||
impl Context {
|
||||
pub fn new(cid: ContextId, pid: ContextId) -> Result<Context> {
|
||||
pub fn new(cid: ContextId, pid: ContextId, process: Arc<RwLock<Process>>) -> Result<Context> {
|
||||
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,
|
||||
|
||||
|
||||
@@ -33,21 +33,6 @@ impl ContextList {
|
||||
self.map.get(&id)
|
||||
}
|
||||
|
||||
/// Get an iterator of all parents
|
||||
pub fn ancestors(
|
||||
&'_ self,
|
||||
id: ContextId,
|
||||
) -> impl Iterator<Item = (ContextId, &Arc<RwSpinlock<Context>>)> + '_ {
|
||||
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<RwSpinlock<Context>>> {
|
||||
self.map.get(&super::current_cid())
|
||||
|
||||
@@ -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<ProcessId> {
|
||||
Ok(current()?.read().pid)
|
||||
}
|
||||
|
||||
pub fn current() -> Result<Arc<RwSpinlock<Context>>> {
|
||||
contexts()
|
||||
|
||||
@@ -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<WaitpidKey, (ProcessId, usize)>,
|
||||
pub threads: Vec<Weak<RwSpinlock<Context>>>,
|
||||
}
|
||||
|
||||
pub static PROCESSES: RwLock<BTreeMap<ProcessId, Arc<RwLock<Process>>>> = RwLock::new(BTreeMap::new());
|
||||
|
||||
/// Get an iterator of all parents
|
||||
pub fn ancestors(
|
||||
list: &BTreeSet<Process>,
|
||||
id: ProcessId,
|
||||
) -> impl Iterator<Item = (ProcessId, &Arc<RwSpinlock<Context>>)> + '_ {
|
||||
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<core::cmp::Ordering> {
|
||||
Some(Ord::cmp(&self.pid, &other.pid))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn current() -> Result<Arc<RwLock<Process>>> {
|
||||
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 {}
|
||||
@@ -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))
|
||||
|
||||
Reference in New Issue
Block a user