Fix half of proc scheme errors.
This commit is contained in:
@@ -93,6 +93,15 @@ macro_rules! int_like {
|
||||
}
|
||||
#[allow(dead_code)]
|
||||
#[inline]
|
||||
pub fn fetch_add(
|
||||
&self,
|
||||
with: $new_type_name,
|
||||
order: ::core::sync::atomic::Ordering,
|
||||
) -> $new_type_name {
|
||||
$new_type_name::from(self.container.fetch_add(with.into(), order))
|
||||
}
|
||||
#[allow(dead_code)]
|
||||
#[inline]
|
||||
pub fn compare_exchange(
|
||||
&self,
|
||||
current: $new_type_name,
|
||||
|
||||
@@ -26,7 +26,8 @@ use ::core::sync::atomic::AtomicUsize;
|
||||
|
||||
use super::{
|
||||
empty_cr3,
|
||||
memory::{AddrSpaceWrapper, GrantFileRef}, process::{Process, ProcessId},
|
||||
memory::{AddrSpaceWrapper, GrantFileRef},
|
||||
process::{Process, ProcessId},
|
||||
};
|
||||
int_like!(ContextId, AtomicContextId, usize, AtomicUsize);
|
||||
|
||||
@@ -65,7 +66,7 @@ pub enum HardBlockedReason {
|
||||
AwaitingMmap { file_ref: GrantFileRef },
|
||||
// TODO: PageFaultOom?
|
||||
NotYetStarted,
|
||||
// TODO: ptrace_stop?
|
||||
PtraceStop,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
|
||||
+13
-4
@@ -5,10 +5,12 @@ use spinning_top::RwSpinlock;
|
||||
|
||||
use super::{
|
||||
context::{Context, ContextId, Kstack},
|
||||
memory::AddrSpaceWrapper, process::{Process, ProcessId},
|
||||
memory::AddrSpaceWrapper,
|
||||
process::{new_process, Process, ProcessId, ProcessInfo},
|
||||
};
|
||||
use crate::{
|
||||
interrupt::InterruptStack,
|
||||
scheme::SchemeNamespace,
|
||||
syscall::error::{Error, Result, EAGAIN},
|
||||
};
|
||||
|
||||
@@ -60,7 +62,10 @@ impl ContextList {
|
||||
assert!(self
|
||||
.map
|
||||
// TODO
|
||||
.insert(cid, Arc::new(RwSpinlock::new(Context::new(cid, pid, process)?)))
|
||||
.insert(
|
||||
cid,
|
||||
Arc::new(RwSpinlock::new(Context::new(cid, pid, process)?))
|
||||
)
|
||||
.is_none());
|
||||
|
||||
Ok(self
|
||||
@@ -70,7 +75,10 @@ impl ContextList {
|
||||
}
|
||||
|
||||
/// Create a new context.
|
||||
pub fn new_context(&mut self, process: Arc<RwLock<Process>>) -> Result<&Arc<RwSpinlock<Context>>> {
|
||||
pub fn new_context(
|
||||
&mut self,
|
||||
process: Arc<RwLock<Process>>,
|
||||
) -> Result<&Arc<RwSpinlock<Context>>> {
|
||||
let pid = process.read().pid;
|
||||
|
||||
// Zero is not a valid context ID, therefore add 1.
|
||||
@@ -102,11 +110,12 @@ impl ContextList {
|
||||
pub fn spawn(
|
||||
&mut self,
|
||||
userspace_allowed: bool,
|
||||
process: Arc<RwLock<Process>>,
|
||||
func: extern "C" fn(),
|
||||
) -> Result<&Arc<RwSpinlock<Context>>> {
|
||||
let stack = Kstack::new()?;
|
||||
|
||||
let context_lock = self.new_context()?;
|
||||
let context_lock = self.new_context(process)?;
|
||||
{
|
||||
let mut context = context_lock.write();
|
||||
let _ = context.set_addr_space(Some(AddrSpaceWrapper::new()?));
|
||||
|
||||
+12
-3
@@ -2,7 +2,7 @@
|
||||
//!
|
||||
//! For resources on contexts, please consult [wikipedia](https://en.wikipedia.org/wiki/Context_switch) and [osdev](https://wiki.osdev.org/Context_Switching)
|
||||
|
||||
use alloc::{borrow::Cow, sync::Arc};
|
||||
use alloc::{borrow::Cow, sync::Arc, vec::Vec};
|
||||
|
||||
use spin::{RwLock, RwLockReadGuard, RwLockWriteGuard};
|
||||
use spinning_top::RwSpinlock;
|
||||
@@ -11,10 +11,11 @@ use crate::{
|
||||
cpu_set::LogicalCpuSet,
|
||||
paging::{RmmA, RmmArch, TableKind},
|
||||
percpu::PercpuBlock,
|
||||
sync::WaitMap,
|
||||
syscall::error::{Error, Result, ESRCH},
|
||||
};
|
||||
|
||||
use self::process::ProcessId;
|
||||
use self::process::{Process, ProcessId, ProcessInfo};
|
||||
pub use self::{
|
||||
context::{BorrowedHtBuf, Context, ContextId, Status, WaitpidKey},
|
||||
list::ContextList,
|
||||
@@ -73,8 +74,16 @@ pub use self::arch::empty_cr3;
|
||||
pub fn init() {
|
||||
let mut contexts = contexts_mut();
|
||||
let id = ContextId::from(crate::cpu_id().get() as usize + 1);
|
||||
|
||||
let pid = ProcessId::new(0);
|
||||
let process = Arc::new(RwLock::new(Process {
|
||||
info: ProcessInfo::default(),
|
||||
waitpid: Arc::new(WaitMap::new()),
|
||||
threads: Vec::new(),
|
||||
}));
|
||||
|
||||
let context_lock = contexts
|
||||
.insert_context_raw(id)
|
||||
.insert_context_raw(id, pid, process)
|
||||
.expect("could not initialize first context");
|
||||
let mut context = context_lock.write();
|
||||
context.sched_affinity = LogicalCpuSet::empty();
|
||||
|
||||
+32
-11
@@ -1,21 +1,28 @@
|
||||
use core::ops::{Deref, DerefMut};
|
||||
use core::{
|
||||
ops::{Deref, DerefMut},
|
||||
sync::atomic::{AtomicUsize, Ordering},
|
||||
};
|
||||
|
||||
// TODO: move all this code to userspace
|
||||
use alloc::collections::BTreeMap;
|
||||
use alloc::sync::{Arc, Weak};
|
||||
use alloc::vec::Vec;
|
||||
use alloc::{
|
||||
collections::BTreeMap,
|
||||
sync::{Arc, Weak},
|
||||
vec::Vec,
|
||||
};
|
||||
|
||||
use spin::RwLock;
|
||||
use spinning_top::RwSpinlock;
|
||||
|
||||
use syscall::{Error, Result, ESRCH};
|
||||
use syscall::{Error, Result, ENOMEM, ESRCH};
|
||||
|
||||
use crate::scheme::{CallerCtx, SchemeNamespace};
|
||||
use crate::sync::WaitMap;
|
||||
use crate::{
|
||||
scheme::{CallerCtx, SchemeNamespace},
|
||||
sync::WaitMap,
|
||||
};
|
||||
|
||||
use crate::context::{self, Context, WaitpidKey};
|
||||
|
||||
int_like!(ProcessId, usize);
|
||||
int_like!(ProcessId, AtomicProcessId, usize, AtomicUsize);
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Process {
|
||||
@@ -25,7 +32,7 @@ pub struct Process {
|
||||
/// Threads of process
|
||||
pub threads: Vec<Weak<RwSpinlock<Context>>>,
|
||||
}
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
#[derive(Debug, Clone, Copy, Default)]
|
||||
pub struct ProcessInfo {
|
||||
/// The process ID of this process
|
||||
pub pid: ProcessId,
|
||||
@@ -63,7 +70,10 @@ impl DerefMut for Process {
|
||||
}
|
||||
}
|
||||
|
||||
pub static PROCESSES: RwLock<BTreeMap<ProcessId, Arc<RwLock<Process>>>> = RwLock::new(BTreeMap::new());
|
||||
pub const INIT: ProcessId = ProcessId::new(1);
|
||||
static NEXT_PID: AtomicProcessId = AtomicProcessId::new(INIT);
|
||||
pub static PROCESSES: RwLock<BTreeMap<ProcessId, Arc<RwLock<Process>>>> =
|
||||
RwLock::new(BTreeMap::new());
|
||||
|
||||
/// Get an iterator of all parents
|
||||
pub fn ancestors(
|
||||
@@ -82,7 +92,9 @@ pub fn ancestors(
|
||||
|
||||
pub fn current() -> Result<Arc<RwLock<Process>>> {
|
||||
let pid = context::current()?.read().pid;
|
||||
Ok(Arc::clone(PROCESSES.read().get(&pid).ok_or(Error::new(ESRCH))?))
|
||||
Ok(Arc::clone(
|
||||
PROCESSES.read().get(&pid).ok_or(Error::new(ESRCH))?,
|
||||
))
|
||||
}
|
||||
impl Process {
|
||||
pub fn caller_ctx(&self) -> CallerCtx {
|
||||
@@ -93,3 +105,12 @@ impl Process {
|
||||
}
|
||||
}
|
||||
}
|
||||
pub fn new_process(info: impl FnOnce(ProcessId) -> ProcessInfo) -> Result<Arc<RwLock<Process>>> {
|
||||
let pid = NEXT_PID.fetch_add(ProcessId::new(1), Ordering::Relaxed);
|
||||
Arc::try_new(RwLock::new(Process {
|
||||
waitpid: Arc::try_new(WaitMap::new()).map_err(|_| Error::new(ENOMEM))?,
|
||||
threads: Vec::new(),
|
||||
info: info(pid),
|
||||
}))
|
||||
.map_err(|_| Error::new(ENOMEM))
|
||||
}
|
||||
|
||||
+23
-2
@@ -61,7 +61,13 @@ extern crate bitflags;
|
||||
|
||||
use core::sync::atomic::{AtomicU32, Ordering};
|
||||
|
||||
use crate::{context::switch::SwitchResult, scheme::SchemeNamespace};
|
||||
use crate::{
|
||||
context::{
|
||||
process::{new_process, ProcessInfo, INIT},
|
||||
switch::SwitchResult,
|
||||
},
|
||||
scheme::SchemeNamespace,
|
||||
};
|
||||
|
||||
use crate::consts::*;
|
||||
|
||||
@@ -197,7 +203,22 @@ fn kmain(cpu_count: u32, bootstrap: Bootstrap) -> ! {
|
||||
#[cfg(feature = "profiling")]
|
||||
profiling::ready_for_profiling();
|
||||
|
||||
match context::contexts_mut().spawn(true, userspace_init) {
|
||||
let process = new_process(|_| ProcessInfo {
|
||||
pid: INIT,
|
||||
ppid: INIT,
|
||||
pgid: INIT,
|
||||
session_id: INIT,
|
||||
ruid: 0,
|
||||
rgid: 0,
|
||||
euid: 0,
|
||||
egid: 0,
|
||||
rns: SchemeNamespace::new(0),
|
||||
ens: SchemeNamespace::new(0),
|
||||
umask: 0o22,
|
||||
})
|
||||
.expect("failed to create init process");
|
||||
|
||||
match context::contexts_mut().spawn(true, process, userspace_init) {
|
||||
Ok(context_lock) => {
|
||||
let mut context = context_lock.write();
|
||||
context.status = context::Status::Runnable;
|
||||
|
||||
+932
-929
File diff suppressed because it is too large
Load Diff
@@ -1,7 +1,8 @@
|
||||
use alloc::vec::Vec;
|
||||
|
||||
use crate::{
|
||||
context::process, scheme,
|
||||
context::process,
|
||||
scheme,
|
||||
syscall::error::{Error, Result},
|
||||
};
|
||||
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
use alloc::vec::Vec;
|
||||
|
||||
use crate::{
|
||||
context::process, scheme,
|
||||
context::process,
|
||||
scheme,
|
||||
syscall::error::{Error, Result, ESRCH},
|
||||
};
|
||||
|
||||
|
||||
+6
-2
@@ -21,10 +21,14 @@ use syscall::{
|
||||
|
||||
use crate::{
|
||||
context::{
|
||||
self, context::HardBlockedReason, file::{FileDescription, FileDescriptor, InternalFlags}, memory::{
|
||||
self,
|
||||
context::HardBlockedReason,
|
||||
file::{FileDescription, FileDescriptor, InternalFlags},
|
||||
memory::{
|
||||
AddrSpace, AddrSpaceWrapper, BorrowedFmapSource, Grant, GrantFileRef, MmapMode,
|
||||
PageSpan, DANGLING,
|
||||
}, process, BorrowedHtBuf, Context, Status
|
||||
},
|
||||
process, BorrowedHtBuf, Context, Status,
|
||||
},
|
||||
event,
|
||||
memory::Frame,
|
||||
|
||||
+10
-3
@@ -7,7 +7,8 @@ use crate::{
|
||||
context::{
|
||||
self,
|
||||
file::{FileDescription, FileDescriptor, InternalFlags},
|
||||
memory::{AddrSpace, PageSpan}, process,
|
||||
memory::{AddrSpace, PageSpan},
|
||||
process,
|
||||
},
|
||||
paging::{Page, VirtualAddress, PAGE_SIZE},
|
||||
scheme::{self, CallerCtx, FileHandle, KernelScheme, OpenResult},
|
||||
@@ -169,7 +170,10 @@ pub fn close(fd: FileHandle) -> Result<()> {
|
||||
|
||||
fn duplicate_file(fd: FileHandle, user_buf: UserSliceRo) -> Result<FileDescriptor> {
|
||||
let caller_ctx = process::current()?.read().caller_ctx();
|
||||
let file = context::current()?.read().get_file(fd).ok_or(Error::new(EBADF))?;
|
||||
let file = context::current()?
|
||||
.read()
|
||||
.get_file(fd)
|
||||
.ok_or(Error::new(EBADF))?;
|
||||
|
||||
if user_buf.is_empty() {
|
||||
Ok(FileDescriptor {
|
||||
@@ -360,7 +364,10 @@ pub fn frename(fd: FileHandle, raw_path: UserSliceRo) -> Result<()> {
|
||||
process.ens,
|
||||
),
|
||||
};
|
||||
let file = context::current()?.read().get_file(fd).ok_or(Error::new(EBADF))?;
|
||||
let file = context::current()?
|
||||
.read()
|
||||
.get_file(fd)
|
||||
.ok_or(Error::new(EBADF))?;
|
||||
|
||||
/*
|
||||
let mut path_buf = BorrowedHtBuf::head()?;
|
||||
|
||||
+3
-1
@@ -236,7 +236,9 @@ pub fn syscall(
|
||||
)?),
|
||||
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_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),
|
||||
|
||||
+64
-20
@@ -6,7 +6,9 @@ use rmm::Arch;
|
||||
use spin::RwLock;
|
||||
|
||||
use crate::context::{
|
||||
memory::{AddrSpace, Grant, PageSpan}, process::{self, ProcessId, ProcessInfo}, WaitpidKey
|
||||
memory::{AddrSpace, Grant, PageSpan},
|
||||
process::{self, ProcessId, ProcessInfo},
|
||||
WaitpidKey,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
@@ -116,7 +118,12 @@ pub fn getpgid(pid: ProcessId) -> Result<ProcessId> {
|
||||
let process_lock = if pid.get() == 0 {
|
||||
process::current()?
|
||||
} else {
|
||||
Arc::clone(process::PROCESSES.read().get(&pid).ok_or(Error::new(ESRCH))?)
|
||||
Arc::clone(
|
||||
process::PROCESSES
|
||||
.read()
|
||||
.get(&pid)
|
||||
.ok_or(Error::new(ESRCH))?,
|
||||
)
|
||||
};
|
||||
let process = process_lock.read();
|
||||
Ok(process.pgid)
|
||||
@@ -254,7 +261,8 @@ pub fn kill(pid: ProcessId, sig: usize, parent_sigchld: bool) -> Result<usize> {
|
||||
} => {
|
||||
sent += 1;
|
||||
let waitpid = Arc::clone(
|
||||
&process::PROCESSES.read()
|
||||
&process::PROCESSES
|
||||
.read()
|
||||
.get(&ppid)
|
||||
.ok_or(Error::new(ESRCH))?
|
||||
.read()
|
||||
@@ -271,17 +279,19 @@ pub fn kill(pid: ProcessId, sig: usize, parent_sigchld: bool) -> Result<usize> {
|
||||
}
|
||||
SendResult::SucceededSigcont { ppid, pgid } => {
|
||||
sent += 1;
|
||||
&process::PROCESSES.read()
|
||||
.get(&ppid)
|
||||
.ok_or(Error::new(ESRCH))?
|
||||
.read()
|
||||
.waitpid.send(
|
||||
WaitpidKey {
|
||||
pid: Some(pid),
|
||||
pgid: Some(pgid),
|
||||
},
|
||||
(pid, 0xffff),
|
||||
);
|
||||
&process::PROCESSES
|
||||
.read()
|
||||
.get(&ppid)
|
||||
.ok_or(Error::new(ESRCH))?
|
||||
.read()
|
||||
.waitpid
|
||||
.send(
|
||||
WaitpidKey {
|
||||
pid: Some(pid),
|
||||
pgid: Some(pgid),
|
||||
},
|
||||
(pid, 0xffff),
|
||||
);
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
@@ -293,7 +303,15 @@ pub fn kill(pid: ProcessId, sig: usize, parent_sigchld: bool) -> Result<usize> {
|
||||
found += 1;
|
||||
let (context_lock, info) = {
|
||||
let process = process_lock.read();
|
||||
(process.threads.first().ok_or(Error::new(ESRCH))?.upgrade().ok_or(Error::new(ESRCH))?, process.info)
|
||||
(
|
||||
process
|
||||
.threads
|
||||
.first()
|
||||
.ok_or(Error::new(ESRCH))?
|
||||
.upgrade()
|
||||
.ok_or(Error::new(ESRCH))?,
|
||||
process.info,
|
||||
)
|
||||
};
|
||||
let mut context = context_lock.write();
|
||||
let result = send(&mut *context, &info);
|
||||
@@ -304,7 +322,15 @@ pub fn kill(pid: ProcessId, sig: usize, parent_sigchld: bool) -> Result<usize> {
|
||||
for (pid, process_lock) in processes.iter() {
|
||||
let (context_lock, info) = {
|
||||
let process = process_lock.read();
|
||||
(process.threads.first().ok_or(Error::new(ESRCH))?.upgrade().ok_or(Error::new(ESRCH))?, process.info)
|
||||
(
|
||||
process
|
||||
.threads
|
||||
.first()
|
||||
.ok_or(Error::new(ESRCH))?
|
||||
.upgrade()
|
||||
.ok_or(Error::new(ESRCH))?,
|
||||
process.info,
|
||||
)
|
||||
};
|
||||
|
||||
if info.pid.get() <= 2 {
|
||||
@@ -328,7 +354,15 @@ pub fn kill(pid: ProcessId, sig: usize, parent_sigchld: bool) -> Result<usize> {
|
||||
for (pid, process_lock) in processes.iter() {
|
||||
let (context_lock, info) = {
|
||||
let process = process_lock.read();
|
||||
(process.threads.first().ok_or(Error::new(ESRCH))?.upgrade().ok_or(Error::new(ESRCH))?, process.info)
|
||||
(
|
||||
process
|
||||
.threads
|
||||
.first()
|
||||
.ok_or(Error::new(ESRCH))?
|
||||
.upgrade()
|
||||
.ok_or(Error::new(ESRCH))?,
|
||||
process.info,
|
||||
)
|
||||
};
|
||||
|
||||
if info.pgid != pgid {
|
||||
@@ -404,14 +438,23 @@ pub fn umask(mask: usize) -> Result<usize> {
|
||||
}
|
||||
|
||||
fn reap(pid: ProcessId) -> Result<ProcessId> {
|
||||
let process_lock = Arc::clone(process::PROCESSES.read().get(&pid).ok_or(Error::new(ESRCH))?);
|
||||
let process_lock = Arc::clone(
|
||||
process::PROCESSES
|
||||
.read()
|
||||
.get(&pid)
|
||||
.ok_or(Error::new(ESRCH))?,
|
||||
);
|
||||
|
||||
// Spin until not running
|
||||
loop {
|
||||
// TODO: exit WaitCondition?
|
||||
{
|
||||
let mut process = process_lock.read();
|
||||
if process.threads.iter().all(|t| t.upgrade().map_or(true, |t| !t.read().running)) {
|
||||
if process
|
||||
.threads
|
||||
.iter()
|
||||
.all(|t| t.upgrade().map_or(true, |t| !t.read().running))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -420,7 +463,8 @@ fn reap(pid: ProcessId) -> Result<ProcessId> {
|
||||
interrupt::pause();
|
||||
}
|
||||
|
||||
let _ = process::PROCESSES.write()
|
||||
let _ = process::PROCESSES
|
||||
.write()
|
||||
.remove(&pid)
|
||||
.ok_or(Error::new(ESRCH))?;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user