WIP: Replace ContextId with direct Arcs.
This commit is contained in:
@@ -104,7 +104,7 @@ impl super::Context {
|
||||
pub fn set_userspace_io_allowed(&mut self, allowed: bool) {
|
||||
self.arch.userspace_io_allowed = allowed;
|
||||
|
||||
if self.id == super::context_id() {
|
||||
if self.is_current_context() {
|
||||
unsafe {
|
||||
crate::gdt::set_userspace_io_allowed(allowed);
|
||||
}
|
||||
|
||||
@@ -114,7 +114,7 @@ impl super::Context {
|
||||
pub fn set_userspace_io_allowed(&mut self, allowed: bool) {
|
||||
self.arch.userspace_io_allowed = allowed;
|
||||
|
||||
if self.cid == super::current_cid() {
|
||||
if self.is_current_context() {
|
||||
unsafe {
|
||||
crate::gdt::set_userspace_io_allowed(crate::gdt::pcr(), allowed);
|
||||
}
|
||||
|
||||
+10
-14
@@ -21,15 +21,11 @@ use crate::{
|
||||
|
||||
use crate::syscall::error::{Error, Result, EAGAIN, ESRCH};
|
||||
|
||||
/// Unique identifier for a context (i.e. `pid`).
|
||||
use ::core::sync::atomic::AtomicUsize;
|
||||
|
||||
use super::{
|
||||
empty_cr3,
|
||||
memory::{AddrSpaceWrapper, GrantFileRef},
|
||||
process::{Process, ProcessId},
|
||||
};
|
||||
int_like!(ContextId, AtomicContextId, usize, AtomicUsize);
|
||||
|
||||
/// The status of a context - used for scheduling
|
||||
/// See `syscall::process::waitpid` and the `sync` module for examples of usage
|
||||
@@ -131,8 +127,6 @@ impl Eq for WaitpidKey {}
|
||||
/// A context, which identifies either a process or a thread
|
||||
#[derive(Debug)]
|
||||
pub struct Context {
|
||||
/// The internal context ID of this context
|
||||
pub cid: ContextId,
|
||||
/// The process ID of this context
|
||||
pub pid: ProcessId,
|
||||
/// Process state shared with other threads
|
||||
@@ -207,9 +201,8 @@ pub struct SignalState {
|
||||
}
|
||||
|
||||
impl Context {
|
||||
pub fn new(cid: ContextId, pid: ProcessId, process: Arc<RwLock<Process>>) -> Result<Context> {
|
||||
pub fn new(pid: ProcessId, process: Arc<RwLock<Process>>) -> Result<Context> {
|
||||
let this = Context {
|
||||
cid,
|
||||
pid,
|
||||
process,
|
||||
sig: None,
|
||||
@@ -362,6 +355,10 @@ impl Context {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_current_context(&self) -> bool {
|
||||
self.running && self.cpu_id == Some(crate::cpu_id())
|
||||
}
|
||||
|
||||
pub fn addr_space(&self) -> Result<&Arc<AddrSpaceWrapper>> {
|
||||
self.addr_space.as_ref().ok_or(Error::new(ESRCH))
|
||||
}
|
||||
@@ -375,7 +372,7 @@ impl Context {
|
||||
return addr_space;
|
||||
};
|
||||
|
||||
if self.cid == super::current_cid() {
|
||||
if self.is_current_context() {
|
||||
// TODO: Share more code with context::arch::switch_to.
|
||||
let this_percpu = PercpuBlock::current();
|
||||
|
||||
@@ -474,7 +471,7 @@ impl BorrowedHtBuf {
|
||||
pub fn head() -> Result<Self> {
|
||||
Ok(Self {
|
||||
inner: Some(
|
||||
context::current()?
|
||||
context::current()
|
||||
.write()
|
||||
.syscall_head
|
||||
.take()
|
||||
@@ -486,7 +483,7 @@ impl BorrowedHtBuf {
|
||||
pub fn tail() -> Result<Self> {
|
||||
Ok(Self {
|
||||
inner: Some(
|
||||
context::current()?
|
||||
context::current()
|
||||
.write()
|
||||
.syscall_tail
|
||||
.take()
|
||||
@@ -545,9 +542,8 @@ impl BorrowedHtBuf {
|
||||
}
|
||||
impl Drop for BorrowedHtBuf {
|
||||
fn drop(&mut self) {
|
||||
let Ok(context) = context::current() else {
|
||||
return;
|
||||
};
|
||||
let context = context::current();
|
||||
|
||||
let Some(inner) = self.inner.take() else {
|
||||
return;
|
||||
};
|
||||
|
||||
@@ -1,169 +0,0 @@
|
||||
use alloc::{collections::BTreeMap, sync::Arc};
|
||||
use spin::RwLock;
|
||||
|
||||
use spinning_top::RwSpinlock;
|
||||
|
||||
use super::{
|
||||
context::{Context, ContextId, Kstack},
|
||||
memory::AddrSpaceWrapper,
|
||||
process::{new_process, Process, ProcessId, ProcessInfo},
|
||||
};
|
||||
use crate::{
|
||||
interrupt::InterruptStack,
|
||||
scheme::SchemeNamespace,
|
||||
syscall::error::{Error, Result, EAGAIN},
|
||||
};
|
||||
|
||||
/// Context list type
|
||||
pub struct ContextList {
|
||||
// Using a BTreeMap for it's range method
|
||||
map: BTreeMap<ContextId, Arc<RwSpinlock<Context>>>,
|
||||
next_id: usize,
|
||||
}
|
||||
|
||||
impl ContextList {
|
||||
/// Create a new context list.
|
||||
pub const fn new() -> Self {
|
||||
ContextList {
|
||||
map: BTreeMap::new(),
|
||||
next_id: 1,
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the nth context.
|
||||
pub fn get(&self, id: ContextId) -> Option<&Arc<RwSpinlock<Context>>> {
|
||||
self.map.get(&id)
|
||||
}
|
||||
|
||||
/// Get the current context.
|
||||
pub fn current(&self) -> Option<&Arc<RwSpinlock<Context>>> {
|
||||
self.map.get(&super::current_cid())
|
||||
}
|
||||
|
||||
pub fn iter(
|
||||
&self,
|
||||
) -> ::alloc::collections::btree_map::Iter<ContextId, Arc<RwSpinlock<Context>>> {
|
||||
self.map.iter()
|
||||
}
|
||||
|
||||
pub fn range(
|
||||
&self,
|
||||
range: impl core::ops::RangeBounds<ContextId>,
|
||||
) -> ::alloc::collections::btree_map::Range<'_, ContextId, Arc<RwSpinlock<Context>>> {
|
||||
self.map.range(range)
|
||||
}
|
||||
|
||||
pub(crate) fn insert_context_raw(
|
||||
&mut self,
|
||||
cid: ContextId,
|
||||
pid: ProcessId,
|
||||
process: Arc<RwLock<Process>>,
|
||||
) -> Result<&Arc<RwSpinlock<Context>>> {
|
||||
assert!(self
|
||||
.map
|
||||
// TODO
|
||||
.insert(
|
||||
cid,
|
||||
Arc::new(RwSpinlock::new(Context::new(cid, pid, process)?))
|
||||
)
|
||||
.is_none());
|
||||
|
||||
Ok(self
|
||||
.map
|
||||
.get(&cid)
|
||||
.expect("Failed to insert new context. ID is out of bounds."))
|
||||
}
|
||||
|
||||
/// Create a new 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.
|
||||
//
|
||||
// FIXME: Ensure the number of CPUs can't switch between new_context calls.
|
||||
let min = crate::cpu_count() as usize + 1;
|
||||
|
||||
self.next_id = core::cmp::max(self.next_id, min);
|
||||
|
||||
if self.next_id >= super::CONTEXT_MAX_CONTEXTS {
|
||||
self.next_id = min;
|
||||
}
|
||||
|
||||
while self.map.contains_key(&ContextId::from(self.next_id)) {
|
||||
self.next_id += 1;
|
||||
}
|
||||
|
||||
if self.next_id >= super::CONTEXT_MAX_CONTEXTS {
|
||||
return Err(Error::new(EAGAIN));
|
||||
}
|
||||
|
||||
let id = ContextId::from(self.next_id);
|
||||
self.next_id += 1;
|
||||
|
||||
self.insert_context_raw(id, pid, process)
|
||||
}
|
||||
|
||||
/// Spawn a context from a function.
|
||||
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(Arc::clone(&process))?;
|
||||
process.write().threads.push(Arc::downgrade(&context_lock));
|
||||
{
|
||||
let mut context = context_lock.write();
|
||||
let _ = context.set_addr_space(Some(AddrSpaceWrapper::new()?));
|
||||
|
||||
let mut stack_top = stack.initial_top();
|
||||
|
||||
const INT_REGS_SIZE: usize = core::mem::size_of::<crate::interrupt::InterruptStack>();
|
||||
|
||||
if userspace_allowed {
|
||||
unsafe {
|
||||
// Zero-initialize InterruptStack registers.
|
||||
stack_top = stack_top.sub(INT_REGS_SIZE);
|
||||
stack_top.write_bytes(0_u8, INT_REGS_SIZE);
|
||||
(&mut *stack_top.cast::<InterruptStack>()).init();
|
||||
}
|
||||
}
|
||||
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
|
||||
unsafe {
|
||||
if userspace_allowed {
|
||||
stack_top = stack_top.sub(core::mem::size_of::<usize>());
|
||||
stack_top
|
||||
.cast::<usize>()
|
||||
.write(crate::interrupt::syscall::enter_usermode as usize);
|
||||
}
|
||||
|
||||
stack_top = stack_top.sub(core::mem::size_of::<usize>());
|
||||
stack_top.cast::<usize>().write(func as usize);
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
unsafe {
|
||||
context
|
||||
.arch
|
||||
.set_lr(crate::interrupt::syscall::enter_usermode as usize);
|
||||
context.arch.set_x28(func as usize);
|
||||
context.arch.set_context_handle();
|
||||
}
|
||||
|
||||
context.arch.set_stack(stack_top as usize);
|
||||
|
||||
context.kstack = Some(stack);
|
||||
context.userspace = userspace_allowed;
|
||||
}
|
||||
Ok(context_lock)
|
||||
}
|
||||
|
||||
pub fn remove(&mut self, id: ContextId) -> Option<Arc<RwSpinlock<Context>>> {
|
||||
self.map.remove(&id)
|
||||
}
|
||||
}
|
||||
@@ -2712,7 +2712,7 @@ fn correct_inner<'l>(
|
||||
.request_fmap(scheme_number, offset, 1, flags)
|
||||
.unwrap();
|
||||
|
||||
let context_lock = super::current().map_err(|_| PfError::NonfatalInternalError)?;
|
||||
let context_lock = crate::context::current();
|
||||
context_lock
|
||||
.write()
|
||||
.hard_block(HardBlockedReason::AwaitingMmap { file_ref });
|
||||
|
||||
+137
-40
@@ -2,23 +2,33 @@
|
||||
//!
|
||||
//! 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, vec::Vec};
|
||||
use alloc::{
|
||||
borrow::Cow,
|
||||
collections::BTreeSet,
|
||||
sync::{Arc, Weak},
|
||||
vec::Vec,
|
||||
};
|
||||
|
||||
use spin::{RwLock, RwLockReadGuard, RwLockWriteGuard};
|
||||
use spin::{Once, RwLock, RwLockReadGuard, RwLockWriteGuard};
|
||||
use spinning_top::RwSpinlock;
|
||||
use syscall::ENOMEM;
|
||||
|
||||
use crate::{
|
||||
context::memory::AddrSpaceWrapper,
|
||||
cpu_set::LogicalCpuSet,
|
||||
interrupt::InterruptStack,
|
||||
paging::{RmmA, RmmArch, TableKind},
|
||||
percpu::PercpuBlock,
|
||||
sync::WaitMap,
|
||||
syscall::error::{Error, Result, ESRCH},
|
||||
syscall::error::{Error, Result},
|
||||
};
|
||||
|
||||
use self::process::{Process, ProcessId, ProcessInfo};
|
||||
use self::{
|
||||
context::Kstack,
|
||||
process::{Process, ProcessId, ProcessInfo},
|
||||
};
|
||||
pub use self::{
|
||||
context::{BorrowedHtBuf, Context, ContextId, Status, WaitpidKey},
|
||||
list::ContextList,
|
||||
context::{BorrowedHtBuf, Context, Status, WaitpidKey},
|
||||
switch::switch,
|
||||
};
|
||||
|
||||
@@ -37,9 +47,6 @@ mod arch;
|
||||
/// Context struct
|
||||
pub mod context;
|
||||
|
||||
/// Context list
|
||||
mod list;
|
||||
|
||||
/// Context switch function
|
||||
pub mod switch;
|
||||
|
||||
@@ -60,32 +67,29 @@ pub mod timeout;
|
||||
|
||||
pub use self::switch::switch_finish_hook;
|
||||
|
||||
/// Limit on number of contexts
|
||||
pub const CONTEXT_MAX_CONTEXTS: usize = (isize::max_value() as usize) - 1;
|
||||
|
||||
/// Maximum context files
|
||||
pub const CONTEXT_MAX_FILES: usize = 65_536;
|
||||
|
||||
/// Contexts list
|
||||
static CONTEXTS: RwLock<ContextList> = RwLock::new(ContextList::new());
|
||||
|
||||
pub use self::arch::empty_cr3;
|
||||
|
||||
static KMAIN_PROCESS: Once<Arc<RwLock<Process>>> = Once::new();
|
||||
|
||||
// Set of weak references to all contexts available for scheduling. The only strong references are
|
||||
// the context file descriptors.
|
||||
static CONTEXTS: RwLock<BTreeSet<ContextRef>> = RwLock::new(BTreeSet::new());
|
||||
|
||||
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 process = KMAIN_PROCESS.call_once(|| {
|
||||
Arc::new(RwLock::new(Process {
|
||||
info: ProcessInfo::default(),
|
||||
waitpid: Arc::new(WaitMap::new()),
|
||||
threads: Vec::new(),
|
||||
}))
|
||||
});
|
||||
|
||||
let context_lock = contexts
|
||||
.insert_context_raw(id, pid, process)
|
||||
.expect("could not initialize first context");
|
||||
let mut context = context_lock.write();
|
||||
let mut context =
|
||||
Context::new(pid, Arc::clone(process)).expect("failed to create kmain context");
|
||||
context.sched_affinity = LogicalCpuSet::empty();
|
||||
context.sched_affinity.atomic_set(crate::cpu_id());
|
||||
context.name = Cow::Borrowed("kmain");
|
||||
@@ -96,33 +100,126 @@ pub fn init() {
|
||||
context.running = true;
|
||||
context.cpu_id = Some(crate::cpu_id());
|
||||
|
||||
let context_lock = Arc::new(RwSpinlock::new(context));
|
||||
|
||||
CONTEXTS
|
||||
.write()
|
||||
.insert(ContextRef(Arc::downgrade(&context_lock)));
|
||||
|
||||
unsafe {
|
||||
let percpu = PercpuBlock::current();
|
||||
percpu.switch_internals.set_current_cid(context.cid);
|
||||
percpu.switch_internals.set_idle_id(context.cid);
|
||||
percpu
|
||||
.switch_internals
|
||||
.set_current_context(Arc::clone(&context_lock));
|
||||
percpu.switch_internals.set_idle_context(context_lock);
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the global schemes list, const
|
||||
pub fn contexts() -> RwLockReadGuard<'static, ContextList> {
|
||||
pub fn contexts() -> RwLockReadGuard<'static, BTreeSet<ContextRef>> {
|
||||
CONTEXTS.read()
|
||||
}
|
||||
|
||||
/// Get the global schemes list, mutable
|
||||
pub fn contexts_mut() -> RwLockWriteGuard<'static, ContextList> {
|
||||
pub fn contexts_mut() -> RwLockWriteGuard<'static, BTreeSet<ContextRef>> {
|
||||
CONTEXTS.write()
|
||||
}
|
||||
|
||||
pub fn current_cid() -> ContextId {
|
||||
PercpuBlock::current().switch_internals.current_cid()
|
||||
pub fn current() -> Arc<RwSpinlock<Context>> {
|
||||
PercpuBlock::current()
|
||||
.switch_internals
|
||||
.with_context(|context| Arc::clone(context))
|
||||
}
|
||||
pub fn current_pid() -> Result<ProcessId> {
|
||||
Ok(current()?.read().pid)
|
||||
pub fn is_current(context: &Arc<RwSpinlock<Context>>) -> bool {
|
||||
PercpuBlock::current()
|
||||
.switch_internals
|
||||
.with_context(|current| Arc::ptr_eq(context, current))
|
||||
}
|
||||
|
||||
pub fn current() -> Result<Arc<RwSpinlock<Context>>> {
|
||||
contexts()
|
||||
.current()
|
||||
.ok_or(Error::new(ESRCH))
|
||||
.map(Arc::clone)
|
||||
pub fn current_pid() -> Result<ProcessId> {
|
||||
Ok(current().read().pid)
|
||||
}
|
||||
|
||||
pub struct ContextRef(pub Weak<RwSpinlock<Context>>);
|
||||
|
||||
impl Ord for ContextRef {
|
||||
fn cmp(&self, other: &Self) -> core::cmp::Ordering {
|
||||
Ord::cmp(&self.0.as_ptr(), &other.0.as_ptr())
|
||||
}
|
||||
}
|
||||
impl PartialOrd for ContextRef {
|
||||
fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
|
||||
Some(Ord::cmp(self, other))
|
||||
}
|
||||
}
|
||||
impl PartialEq for ContextRef {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
Ord::cmp(self, other) == core::cmp::Ordering::Equal
|
||||
}
|
||||
}
|
||||
impl Eq for ContextRef {}
|
||||
|
||||
/// Spawn a context from a function.
|
||||
pub fn spawn(
|
||||
userspace_allowed: bool,
|
||||
process: Arc<RwLock<Process>>,
|
||||
func: extern "C" fn(),
|
||||
) -> Result<Arc<RwSpinlock<Context>>> {
|
||||
let stack = Kstack::new()?;
|
||||
|
||||
let context_lock = Arc::try_new(RwSpinlock::new(Context::new(
|
||||
process.read().pid,
|
||||
Arc::clone(&process),
|
||||
)?))
|
||||
.map_err(|_| Error::new(ENOMEM))?;
|
||||
|
||||
CONTEXTS
|
||||
.write()
|
||||
.insert(ContextRef(Arc::downgrade(&context_lock)));
|
||||
|
||||
process.write().threads.push(Arc::downgrade(&context_lock));
|
||||
{
|
||||
let mut context = context_lock.write();
|
||||
let _ = context.set_addr_space(Some(AddrSpaceWrapper::new()?));
|
||||
|
||||
let mut stack_top = stack.initial_top();
|
||||
|
||||
const INT_REGS_SIZE: usize = core::mem::size_of::<crate::interrupt::InterruptStack>();
|
||||
|
||||
if userspace_allowed {
|
||||
unsafe {
|
||||
// Zero-initialize InterruptStack registers.
|
||||
stack_top = stack_top.sub(INT_REGS_SIZE);
|
||||
stack_top.write_bytes(0_u8, INT_REGS_SIZE);
|
||||
(&mut *stack_top.cast::<InterruptStack>()).init();
|
||||
}
|
||||
}
|
||||
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
|
||||
unsafe {
|
||||
if userspace_allowed {
|
||||
stack_top = stack_top.sub(core::mem::size_of::<usize>());
|
||||
stack_top
|
||||
.cast::<usize>()
|
||||
.write(crate::interrupt::syscall::enter_usermode as usize);
|
||||
}
|
||||
|
||||
stack_top = stack_top.sub(core::mem::size_of::<usize>());
|
||||
stack_top.cast::<usize>().write(func as usize);
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
unsafe {
|
||||
context
|
||||
.arch
|
||||
.set_lr(crate::interrupt::syscall::enter_usermode as usize);
|
||||
context.arch.set_x28(func as usize);
|
||||
context.arch.set_context_handle();
|
||||
}
|
||||
|
||||
context.arch.set_stack(stack_top as usize);
|
||||
|
||||
context.kstack = Some(stack);
|
||||
context.userspace = userspace_allowed;
|
||||
}
|
||||
Ok(context_lock)
|
||||
}
|
||||
|
||||
@@ -91,7 +91,7 @@ pub fn ancestors(
|
||||
}
|
||||
|
||||
pub fn current() -> Result<Arc<RwLock<Process>>> {
|
||||
let pid = context::current()?.read().pid;
|
||||
let pid = context::current().read().pid;
|
||||
Ok(Arc::clone(
|
||||
PROCESSES.read().get(&pid).ok_or(Error::new(ESRCH))?,
|
||||
))
|
||||
|
||||
@@ -6,7 +6,7 @@ use crate::{
|
||||
};
|
||||
|
||||
pub fn signal_handler() {
|
||||
let context_lock = context::current().expect("running signal handler outside of context");
|
||||
let context_lock = context::current();
|
||||
let mut context = context_lock.write();
|
||||
let context = &mut *context;
|
||||
|
||||
@@ -71,7 +71,7 @@ pub fn signal_handler() {
|
||||
);
|
||||
}
|
||||
pub fn excp_handler(_signal: usize) {
|
||||
let current = context::current().expect("CPU exception but not inside of context!");
|
||||
let current = context::current();
|
||||
let context = current.write();
|
||||
|
||||
let Some(_eh) = context.sig.as_ref().and_then(|s| s.excp_handler) else {
|
||||
|
||||
+47
-29
@@ -1,7 +1,12 @@
|
||||
use core::{cell::Cell, mem, ops::Bound, sync::atomic::Ordering};
|
||||
use core::{
|
||||
cell::{Cell, RefCell},
|
||||
mem,
|
||||
ops::Bound,
|
||||
sync::atomic::Ordering,
|
||||
};
|
||||
|
||||
use alloc::sync::Arc;
|
||||
use spinning_top::guard::ArcRwSpinlockWriteGuard;
|
||||
use spinning_top::{guard::ArcRwSpinlockWriteGuard, RwSpinlock};
|
||||
use syscall::PtraceFlags;
|
||||
|
||||
use crate::{
|
||||
@@ -12,7 +17,7 @@ use crate::{
|
||||
ptrace, time,
|
||||
};
|
||||
|
||||
use super::ContextId;
|
||||
use super::ContextRef;
|
||||
|
||||
enum UpdateResult {
|
||||
CanSwitch,
|
||||
@@ -116,31 +121,32 @@ pub fn switch() -> SwitchResult {
|
||||
let contexts = contexts();
|
||||
|
||||
// Lock previous context
|
||||
let prev_context_lock = contexts
|
||||
.current()
|
||||
.expect("context::switch: not inside of context");
|
||||
let prev_context_lock = crate::context::current();
|
||||
let prev_context_guard = prev_context_lock.write_arc();
|
||||
|
||||
let idle_id = percpu.switch_internals.idle_id();
|
||||
let idle_context = percpu.switch_internals.idle_context();
|
||||
let mut skip_idle = true;
|
||||
|
||||
// Locate next context
|
||||
for (cid, next_context_lock) in contexts
|
||||
for next_context_lock in contexts
|
||||
// Include all contexts with IDs greater than the current...
|
||||
.range((Bound::Excluded(prev_context_guard.cid), Bound::Unbounded))
|
||||
.range((
|
||||
Bound::Excluded(ContextRef(Arc::downgrade(&prev_context_lock))),
|
||||
Bound::Unbounded,
|
||||
))
|
||||
.chain(
|
||||
contexts
|
||||
// ... and all contexts with IDs less than the current...
|
||||
.range((Bound::Unbounded, Bound::Excluded(prev_context_guard.cid))),
|
||||
)
|
||||
.chain(
|
||||
contexts
|
||||
// ... and finally the idle ID
|
||||
.range((Bound::Included(idle_id), Bound::Included(idle_id))),
|
||||
.range((
|
||||
Bound::Unbounded,
|
||||
Bound::Excluded(ContextRef(Arc::downgrade(&prev_context_lock))),
|
||||
)),
|
||||
)
|
||||
.filter_map(|r| r.0.upgrade())
|
||||
.chain(Some(Arc::clone(&idle_context)))
|
||||
// ... but not the current context, which is already locked
|
||||
{
|
||||
if cid == &idle_id && skip_idle {
|
||||
if Arc::ptr_eq(&next_context_lock, &idle_context) && skip_idle {
|
||||
// Skip idle process the first time it shows up
|
||||
skip_idle = false;
|
||||
continue;
|
||||
@@ -178,7 +184,11 @@ pub fn switch() -> SwitchResult {
|
||||
next_context.switch_time = switch_time;
|
||||
|
||||
let percpu = PercpuBlock::current();
|
||||
percpu.switch_internals.current_cid.set(next_context.cid);
|
||||
unsafe {
|
||||
percpu.switch_internals.set_current_context(Arc::clone(
|
||||
ArcRwSpinlockWriteGuard::rwlock(&next_context_guard),
|
||||
));
|
||||
}
|
||||
|
||||
// FIXME set th switch result in arch::switch_to instead
|
||||
let prev_context =
|
||||
@@ -245,25 +255,33 @@ pub struct ContextSwitchPercpu {
|
||||
switch_result: Cell<Option<SwitchResultInner>>,
|
||||
pit_ticks: Cell<usize>,
|
||||
|
||||
/// Unique context ID of the currently running context.
|
||||
current_cid: Cell<ContextId>,
|
||||
current_ctxt: RefCell<Option<Arc<RwSpinlock<Context>>>>,
|
||||
|
||||
// The ID of the idle process
|
||||
idle_id: Cell<ContextId>,
|
||||
// The idle process
|
||||
idle_ctxt: RefCell<Option<Arc<RwSpinlock<Context>>>>,
|
||||
|
||||
pub(crate) being_sigkilled: Cell<bool>,
|
||||
}
|
||||
impl ContextSwitchPercpu {
|
||||
pub fn current_cid(&self) -> ContextId {
|
||||
self.current_cid.get()
|
||||
pub fn with_context<T>(&self, f: impl FnOnce(&Arc<RwSpinlock<Context>>) -> T) -> T {
|
||||
f(&*self
|
||||
.current_ctxt
|
||||
.borrow()
|
||||
.as_ref()
|
||||
.expect("not inside of context"))
|
||||
}
|
||||
pub unsafe fn set_current_cid(&self, new: ContextId) {
|
||||
self.current_cid.set(new)
|
||||
pub unsafe fn set_current_context(&self, new: Arc<RwSpinlock<Context>>) {
|
||||
*self.current_ctxt.borrow_mut() = Some(new);
|
||||
}
|
||||
pub fn idle_id(&self) -> ContextId {
|
||||
self.idle_id.get()
|
||||
pub unsafe fn set_idle_context(&self, new: Arc<RwSpinlock<Context>>) {
|
||||
*self.idle_ctxt.borrow_mut() = Some(new);
|
||||
}
|
||||
pub unsafe fn set_idle_id(&self, new: ContextId) {
|
||||
self.idle_id.set(new)
|
||||
pub fn idle_context(&self) -> Arc<RwSpinlock<Context>> {
|
||||
Arc::clone(
|
||||
self.idle_ctxt
|
||||
.borrow()
|
||||
.as_ref()
|
||||
.expect("no idle context present"),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
+4
-4
@@ -9,7 +9,7 @@ use crate::{
|
||||
sync::WaitQueue,
|
||||
syscall::{
|
||||
data::Event,
|
||||
error::{Error, Result, EBADF, ESRCH},
|
||||
error::{Error, Result, EBADF},
|
||||
flag::EventFlags,
|
||||
usercopy::UserSliceWo,
|
||||
},
|
||||
@@ -37,9 +37,9 @@ impl EventQueue {
|
||||
pub fn write(&self, events: &[Event]) -> Result<usize> {
|
||||
for event in events {
|
||||
let file = {
|
||||
let contexts = context::contexts();
|
||||
let context_lock = contexts.current().ok_or(Error::new(ESRCH))?;
|
||||
let context = context_lock.read();
|
||||
let context_ref = context::current();
|
||||
let context = context_ref.read();
|
||||
|
||||
let files = context.files.read();
|
||||
match files.get(event.id).ok_or(Error::new(EBADF))? {
|
||||
Some(file) => file.clone(),
|
||||
|
||||
+18
-18
@@ -117,6 +117,8 @@ mod externs;
|
||||
/// Logging
|
||||
mod log;
|
||||
use ::log::info;
|
||||
use alloc::sync::Arc;
|
||||
use spinning_top::RwSpinlock;
|
||||
|
||||
/// Memory management
|
||||
mod memory;
|
||||
@@ -183,6 +185,7 @@ struct Bootstrap {
|
||||
env: &'static [u8],
|
||||
}
|
||||
static BOOTSTRAP: spin::Once<Bootstrap> = spin::Once::new();
|
||||
static INIT_THREAD: spin::Once<Arc<RwSpinlock<crate::context::Context>>> = spin::Once::new();
|
||||
|
||||
/// This is the kernel entry point for the primary CPU. The arch crate is responsible for calling this
|
||||
fn kmain(cpu_count: u32, bootstrap: Bootstrap) -> ! {
|
||||
@@ -218,15 +221,18 @@ fn kmain(cpu_count: u32, bootstrap: Bootstrap) -> ! {
|
||||
})
|
||||
.expect("failed to create init process");
|
||||
|
||||
match context::contexts_mut().spawn(true, process, userspace_init) {
|
||||
match context::spawn(true, process, userspace_init) {
|
||||
Ok(context_lock) => {
|
||||
let mut context = context_lock.write();
|
||||
context.status = context::Status::Runnable;
|
||||
context.name = "bootstrap".into();
|
||||
{
|
||||
let mut context = context_lock.write();
|
||||
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);
|
||||
let mut process = context.process.write();
|
||||
process.rns = SchemeNamespace::from(1);
|
||||
process.ens = SchemeNamespace::from(1);
|
||||
}
|
||||
INIT_THREAD.call_once(move || context_lock);
|
||||
}
|
||||
Err(err) => {
|
||||
panic!("failed to spawn userspace_init: {:?}", err);
|
||||
@@ -282,18 +288,12 @@ fn run_userspace() -> ! {
|
||||
|
||||
/// Allow exception handlers to send signal to arch-independent kernel
|
||||
pub fn ksignal(signal: usize) {
|
||||
info!(
|
||||
"SIGNAL {}, CPU {}, PID {:?}",
|
||||
signal,
|
||||
cpu_id(),
|
||||
context::current_cid()
|
||||
);
|
||||
let current = context::current();
|
||||
|
||||
info!("SIGNAL {signal}, CPU {}, PID {current:p}", cpu_id(),);
|
||||
{
|
||||
let contexts = context::contexts();
|
||||
if let Some(context_lock) = contexts.current() {
|
||||
let context = context_lock.read();
|
||||
info!("NAME {}", context.name);
|
||||
}
|
||||
let context = current.read();
|
||||
info!("NAME {}", context.name);
|
||||
}
|
||||
crate::context::signal::excp_handler(signal);
|
||||
}
|
||||
|
||||
+6
-8
@@ -12,19 +12,17 @@ fn rust_begin_unwind(info: &PanicInfo) -> ! {
|
||||
unsafe {
|
||||
interrupt::stack_trace();
|
||||
}
|
||||
let context_lock = context::current();
|
||||
|
||||
println!("CPU {}, CID {:?}", cpu_id(), context::current_cid());
|
||||
println!("CPU {}, CID {:p}", cpu_id(), context_lock);
|
||||
|
||||
// This could deadlock, but at this point we are going to halt anyways
|
||||
{
|
||||
let contexts = context::contexts();
|
||||
if let Some(context_lock) = contexts.current() {
|
||||
let context = context_lock.read();
|
||||
println!("NAME: {}", context.name);
|
||||
let context = context_lock.read();
|
||||
println!("NAME: {}", context.name);
|
||||
|
||||
if let Some([a, b, c, d, e, f]) = context.current_syscall() {
|
||||
println!("SYSCALL: {}", syscall::debug::format_call(a, b, c, d, e, f));
|
||||
}
|
||||
if let Some([a, b, c, d, e, f]) = context.current_syscall() {
|
||||
println!("SYSCALL: {}", syscall::debug::format_call(a, b, c, d, e, f));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+3
-9
@@ -171,12 +171,7 @@ fn proc_trigger_event(file_id: usize, flags: EventFlags) {
|
||||
/// the tracer to wake up and poll for events. Returns Some(()) if an
|
||||
/// event was sent.
|
||||
pub fn send_event(event: PtraceEvent) -> Option<()> {
|
||||
let id = {
|
||||
let contexts = context::contexts();
|
||||
let context = contexts.current()?;
|
||||
let context = context.read();
|
||||
context.pid
|
||||
};
|
||||
let id = context::current().read().pid;
|
||||
|
||||
let sessions = sessions();
|
||||
let session = sessions.get(&id)?;
|
||||
@@ -290,9 +285,8 @@ pub fn breakpoint_callback(
|
||||
/// Obtain the next breakpoint flags for the current process. This is used for
|
||||
/// detecting whether or not the tracer decided to use sysemu mode.
|
||||
pub fn next_breakpoint() -> Option<PtraceFlags> {
|
||||
let contexts = context::contexts();
|
||||
let context = contexts.current()?;
|
||||
let context = context.read();
|
||||
let context_lock = context::current();
|
||||
let context = context_lock.read();
|
||||
|
||||
let sessions = sessions();
|
||||
let session = sessions.get(&context.pid)?;
|
||||
|
||||
+86
-172
@@ -3,11 +3,10 @@ use crate::{
|
||||
context::{
|
||||
self,
|
||||
context::{HardBlockedReason, SignalState},
|
||||
contexts,
|
||||
file::{FileDescriptor, InternalFlags},
|
||||
memory::{handle_notify_files, AddrSpaceWrapper, Grant, PageSpan},
|
||||
process::{self, Process, ProcessId, ProcessInfo},
|
||||
Context, ContextId, Status,
|
||||
Context, Status,
|
||||
},
|
||||
memory::PAGE_SIZE,
|
||||
ptrace,
|
||||
@@ -49,40 +48,18 @@ fn read_from(dst: UserSliceWo, src: &[u8], offset: u64) -> Result<usize> {
|
||||
dst.copy_common_bytes_from_slice(avail_src)
|
||||
}
|
||||
|
||||
fn with_context<F, T>(pid: ContextId, callback: F) -> Result<T>
|
||||
where
|
||||
F: FnOnce(&Context) -> Result<T>,
|
||||
{
|
||||
let contexts = context::contexts();
|
||||
let context = contexts.get(pid).ok_or(Error::new(ESRCH))?;
|
||||
let context = context.read();
|
||||
if let Status::Exited(_) = context.status {
|
||||
return Err(Error::new(ESRCH));
|
||||
}
|
||||
callback(&context)
|
||||
}
|
||||
fn with_context_mut<F, T>(pid: ContextId, callback: F) -> Result<T>
|
||||
where
|
||||
F: FnOnce(&mut Context) -> Result<T>,
|
||||
{
|
||||
let contexts = context::contexts();
|
||||
let context = contexts.get(pid).ok_or(Error::new(ESRCH))?;
|
||||
let mut context = context.write();
|
||||
if let Status::Exited(_) = context.status {
|
||||
return Err(Error::new(ESRCH));
|
||||
}
|
||||
callback(&mut context)
|
||||
}
|
||||
fn try_stop_context<F, T>(pid: ContextId, callback: F) -> Result<T>
|
||||
where
|
||||
F: FnOnce(&mut Context) -> Result<T>,
|
||||
{
|
||||
if pid == context::current_cid() {
|
||||
return Err(Error::new(EBADF));
|
||||
fn try_stop_context<T>(
|
||||
context_ref: Arc<RwSpinlock<Context>>,
|
||||
callback: impl FnOnce(&mut Context) -> Result<T>,
|
||||
) -> Result<T> {
|
||||
if context::is_current(&context_ref) {
|
||||
return callback(&mut *context_ref.write());
|
||||
}
|
||||
// Stop process
|
||||
let (prev_status, mut running) = with_context_mut(pid, |context| {
|
||||
Ok((
|
||||
let (prev_status, mut running) = {
|
||||
let mut context = context_ref.write();
|
||||
|
||||
(
|
||||
core::mem::replace(
|
||||
&mut context.status,
|
||||
context::Status::HardBlocked {
|
||||
@@ -90,28 +67,27 @@ where
|
||||
},
|
||||
),
|
||||
context.running,
|
||||
))
|
||||
})?;
|
||||
)
|
||||
};
|
||||
|
||||
// Wait until stopped
|
||||
while running {
|
||||
context::switch();
|
||||
|
||||
running = with_context(pid, |context| Ok(context.running))?;
|
||||
running = context_ref.read().running;
|
||||
}
|
||||
|
||||
with_context_mut(pid, |context| {
|
||||
assert!(
|
||||
!context.running,
|
||||
"process can't have been restarted, we stopped it!"
|
||||
);
|
||||
let mut context = context_ref.write();
|
||||
assert!(
|
||||
!context.running,
|
||||
"process can't have been restarted, we stopped it!"
|
||||
);
|
||||
|
||||
let ret = callback(context);
|
||||
let ret = callback(&mut *context);
|
||||
|
||||
context.status = prev_status;
|
||||
context.status = prev_status;
|
||||
|
||||
ret
|
||||
})
|
||||
ret
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Eq)]
|
||||
@@ -257,15 +233,9 @@ fn new_handle((handle, fl): (Handle, InternalFlags)) -> Result<(usize, InternalF
|
||||
Ok((id, fl))
|
||||
}
|
||||
|
||||
fn get_context(id: ContextId) -> Result<Arc<RwSpinlock<Context>>> {
|
||||
context::contexts()
|
||||
.get(id)
|
||||
.ok_or(Error::new(ENOENT))
|
||||
.map(Arc::clone)
|
||||
}
|
||||
enum OpenTy {
|
||||
Proc(ProcessId),
|
||||
Ctxt(ContextId),
|
||||
Ctxt(Arc<RwSpinlock<Context>>),
|
||||
}
|
||||
|
||||
impl<const FULL: bool> ProcScheme<FULL> {
|
||||
@@ -366,13 +336,7 @@ impl<const FULL: bool> ProcScheme<FULL> {
|
||||
let processes = process::PROCESSES.read();
|
||||
Arc::clone(processes.get(&pid).ok_or(Error::new(ESRCH))?)
|
||||
}
|
||||
OpenTy::Ctxt(cid) => Arc::clone(
|
||||
&context::contexts()
|
||||
.get(cid)
|
||||
.ok_or(Error::new(ESRCH))?
|
||||
.read()
|
||||
.process,
|
||||
),
|
||||
OpenTy::Ctxt(ref context) => Arc::clone(&context.read().process),
|
||||
};
|
||||
|
||||
let operation_name = operation_str.ok_or(Error::new(EINVAL))?;
|
||||
@@ -394,9 +358,7 @@ impl<const FULL: bool> ProcScheme<FULL> {
|
||||
.ok_or(Error::new(ESRCH))?
|
||||
.upgrade()
|
||||
.ok_or(Error::new(ESRCH))?,
|
||||
OpenTy::Ctxt(ctxt) => {
|
||||
Arc::clone(contexts().get(ctxt).ok_or(Error::new(ESRCH))?)
|
||||
}
|
||||
OpenTy::Ctxt(ref ctxt) => Arc::clone(&ctxt),
|
||||
};
|
||||
if let Some((kind, positioned)) =
|
||||
self.openat_context(operation_name, Arc::clone(&context))?
|
||||
@@ -522,7 +484,7 @@ impl<const FULL: bool> KernelScheme for ProcScheme<FULL> {
|
||||
let pid_str = parts.next().ok_or(Error::new(ENOENT))?;
|
||||
|
||||
let pid = if pid_str == "current" {
|
||||
OpenTy::Ctxt(context::current_cid())
|
||||
OpenTy::Ctxt(context::current())
|
||||
} else if pid_str == "new" || pid_str == "new-child" {
|
||||
OpenTy::Ctxt(new_child()?)
|
||||
} else if pid_str == "new-thread" {
|
||||
@@ -530,7 +492,7 @@ impl<const FULL: bool> KernelScheme for ProcScheme<FULL> {
|
||||
} else if !FULL {
|
||||
return Err(Error::new(EACCES));
|
||||
} else {
|
||||
OpenTy::Ctxt(ContextId::new(
|
||||
OpenTy::Proc(ProcessId::new(
|
||||
pid_str.parse().map_err(|_| Error::new(ENOENT))?,
|
||||
))
|
||||
};
|
||||
@@ -568,15 +530,7 @@ impl<const FULL: bool> KernelScheme for ProcScheme<FULL> {
|
||||
new_ip,
|
||||
},
|
||||
} => {
|
||||
let cid = context.read().cid;
|
||||
|
||||
let stop_context = if cid == context::current_cid() {
|
||||
with_context_mut
|
||||
} else {
|
||||
try_stop_context
|
||||
};
|
||||
|
||||
let _ = stop_context(cid, |context: &mut Context| {
|
||||
let _ = try_stop_context(context, |context: &mut Context| {
|
||||
let regs = context.regs_mut().ok_or(Error::new(EBADFD))?;
|
||||
regs.set_instr_pointer(new_ip);
|
||||
regs.set_stack_pointer(new_sp);
|
||||
@@ -631,7 +585,7 @@ impl<const FULL: bool> KernelScheme for ProcScheme<FULL> {
|
||||
consume: bool,
|
||||
) -> Result<usize> {
|
||||
let handle = HANDLES.read().get(&id).ok_or(Error::new(EBADF))?.clone();
|
||||
let Handle::Context { context, kind } = handle else {
|
||||
let Handle::Context { kind, .. } = handle else {
|
||||
return Err(Error::new(EBADF));
|
||||
};
|
||||
|
||||
@@ -841,10 +795,9 @@ impl<const FULL: bool> KernelScheme for ProcScheme<FULL> {
|
||||
let (uid, gid) = match &*process::current()?.read() {
|
||||
process => (process.euid, process.egid),
|
||||
};
|
||||
let cid = context.read().cid;
|
||||
return self
|
||||
.open_inner(
|
||||
OpenTy::Ctxt(cid),
|
||||
OpenTy::Ctxt(context),
|
||||
Some(core::str::from_utf8(buf).map_err(|_| Error::new(EINVAL))?)
|
||||
.filter(|s| !s.is_empty()),
|
||||
O_RDWR | O_CLOEXEC,
|
||||
@@ -943,53 +896,40 @@ extern "C" fn clone_handler() {
|
||||
// usermode.
|
||||
}
|
||||
|
||||
fn new_thread() -> Result<ContextId> {
|
||||
fn new_thread() -> Result<Arc<RwSpinlock<Context>>> {
|
||||
let current_process = process::current()?;
|
||||
let new_context =
|
||||
Arc::clone(context::contexts_mut().spawn(true, current_process, clone_handler)?);
|
||||
let cid = new_context.read().cid;
|
||||
Ok(cid)
|
||||
context::spawn(true, current_process, clone_handler)
|
||||
}
|
||||
|
||||
fn new_child() -> Result<ContextId> {
|
||||
let new_id = {
|
||||
fn new_child() -> Result<Arc<RwSpinlock<Context>>> {
|
||||
let new_context = {
|
||||
let current_process_info = process::current()?.read().info;
|
||||
let new_process = process::new_process(|new_pid| ProcessInfo {
|
||||
pid: new_pid,
|
||||
ppid: current_process_info.pid,
|
||||
..current_process_info
|
||||
})?;
|
||||
let new_context_lock =
|
||||
Arc::clone(context::contexts_mut().spawn(true, new_process, clone_handler)?);
|
||||
let new_context = new_context_lock.read();
|
||||
|
||||
new_context.cid
|
||||
context::spawn(true, new_process, clone_handler)?
|
||||
};
|
||||
|
||||
if ptrace::send_event(crate::syscall::ptrace_event!(
|
||||
PTRACE_EVENT_CLONE,
|
||||
new_id.into()
|
||||
new_context.read().pid.into()
|
||||
))
|
||||
.is_some()
|
||||
{
|
||||
// Freeze the clone, allow ptrace to put breakpoints
|
||||
// to it before it starts
|
||||
let contexts = context::contexts();
|
||||
let context = contexts
|
||||
.get(new_id)
|
||||
.expect("Newly created context doesn't exist??");
|
||||
let mut context = context.write();
|
||||
let mut context = new_context.write();
|
||||
context.status = context::Status::HardBlocked {
|
||||
reason: HardBlockedReason::PtraceStop,
|
||||
};
|
||||
}
|
||||
|
||||
Ok(new_id)
|
||||
Ok(new_context)
|
||||
}
|
||||
fn extract_scheme_number(fd: usize) -> Result<(KernelSchemes, usize)> {
|
||||
let (scheme_id, number) = match &*context::contexts()
|
||||
.current()
|
||||
.ok_or(Error::new(ESRCH))?
|
||||
let (scheme_id, number) = match &*context::current()
|
||||
.read()
|
||||
.get_file(FileHandle::from(fd))
|
||||
.ok_or(Error::new(EBADF))?
|
||||
@@ -1052,9 +992,7 @@ impl ProcHandle {
|
||||
.threads
|
||||
.first()
|
||||
.and_then(|f| f.upgrade())
|
||||
.ok_or(Error::new(ESRCH))?
|
||||
.read()
|
||||
.cid;
|
||||
.ok_or(Error::new(ESRCH))?;
|
||||
|
||||
if op.contains(PTRACE_STOP_SINGLESTEP) {
|
||||
try_stop_context(first, |context| match context.regs_mut() {
|
||||
@@ -1140,11 +1078,7 @@ impl ProcHandle {
|
||||
read_flags: u32,
|
||||
) -> Result<usize> {
|
||||
match self {
|
||||
Self::Static { bytes, .. } => {
|
||||
let mut handles = HANDLES.write();
|
||||
let handle = handles.get_mut(&id).ok_or(Error::new(EBADF))?;
|
||||
read_from(buf, &bytes, offset)
|
||||
}
|
||||
Self::Static { bytes, .. } => read_from(buf, &bytes, offset),
|
||||
Self::Trace { pid, clones, .. } => {
|
||||
// Wait for event
|
||||
if (read_flags as usize) & O_NONBLOCK != O_NONBLOCK {
|
||||
@@ -1277,8 +1211,7 @@ impl ContextHandle {
|
||||
RegsKind::Float => {
|
||||
let regs = unsafe { buf.read_exact::<FloatRegisters>()? };
|
||||
|
||||
let cid = context.read().cid;
|
||||
try_stop_context(cid, |context| {
|
||||
try_stop_context(context, |context| {
|
||||
// NOTE: The kernel will never touch floats
|
||||
|
||||
// Ignore the rare case of floating point
|
||||
@@ -1291,8 +1224,7 @@ impl ContextHandle {
|
||||
RegsKind::Int => {
|
||||
let regs = unsafe { buf.read_exact::<IntRegisters>()? };
|
||||
|
||||
let cid = context.read().cid;
|
||||
try_stop_context(cid, |context| match context.regs_mut() {
|
||||
try_stop_context(context, |context| match context.regs_mut() {
|
||||
None => {
|
||||
println!(
|
||||
"{}:{}: Couldn't read registers from stopped process",
|
||||
@@ -1310,8 +1242,7 @@ impl ContextHandle {
|
||||
}
|
||||
RegsKind::Env => {
|
||||
let regs = unsafe { buf.read_exact::<EnvRegisters>()? };
|
||||
let cid = context.read().cid;
|
||||
write_env_regs(cid, regs)?;
|
||||
write_env_regs(context, regs)?;
|
||||
Ok(mem::size_of::<EnvRegisters>())
|
||||
}
|
||||
},
|
||||
@@ -1511,35 +1442,28 @@ impl ContextHandle {
|
||||
mem::size_of::<FloatRegisters>(),
|
||||
)
|
||||
}
|
||||
RegsKind::Int => {
|
||||
let cid = context.read().cid;
|
||||
try_stop_context(cid, |context| match context.regs() {
|
||||
None => {
|
||||
assert!(!context.running, "try_stop_context is broken, clearly");
|
||||
println!(
|
||||
"{}:{}: Couldn't read registers from stopped process",
|
||||
file!(),
|
||||
line!()
|
||||
);
|
||||
Err(Error::new(ENOTRECOVERABLE))
|
||||
}
|
||||
Some(stack) => {
|
||||
let mut regs = IntRegisters::default();
|
||||
stack.save(&mut regs);
|
||||
Ok((Output { int: regs }, mem::size_of::<IntRegisters>()))
|
||||
}
|
||||
})?
|
||||
}
|
||||
RegsKind::Env => {
|
||||
let cid = context.read().cid;
|
||||
|
||||
(
|
||||
Output {
|
||||
env: read_env_regs(cid)?,
|
||||
},
|
||||
mem::size_of::<EnvRegisters>(),
|
||||
)
|
||||
}
|
||||
RegsKind::Int => try_stop_context(context, |context| match context.regs() {
|
||||
None => {
|
||||
assert!(!context.running, "try_stop_context is broken, clearly");
|
||||
println!(
|
||||
"{}:{}: Couldn't read registers from stopped process",
|
||||
file!(),
|
||||
line!()
|
||||
);
|
||||
Err(Error::new(ENOTRECOVERABLE))
|
||||
}
|
||||
Some(stack) => {
|
||||
let mut regs = IntRegisters::default();
|
||||
stack.save(&mut regs);
|
||||
Ok((Output { int: regs }, mem::size_of::<IntRegisters>()))
|
||||
}
|
||||
})?,
|
||||
RegsKind::Env => (
|
||||
Output {
|
||||
env: read_env_regs(context)?,
|
||||
},
|
||||
mem::size_of::<EnvRegisters>(),
|
||||
),
|
||||
};
|
||||
|
||||
let src_buf =
|
||||
@@ -1604,16 +1528,16 @@ impl ContextHandle {
|
||||
}
|
||||
}
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
fn write_env_regs(&self, info: &Info, regs: EnvRegisters) -> Result<()> {
|
||||
fn write_env_regs(context: Arc<RwSpinlock<Context>>, regs: EnvRegisters) -> Result<()> {
|
||||
use crate::device::cpu::registers::control_regs;
|
||||
|
||||
if info.pid == context::context_id() {
|
||||
if context::is_current(&context) {
|
||||
unsafe {
|
||||
control_regs::tpidr_el0_write(regs.tpidr_el0 as u64);
|
||||
control_regs::tpidrro_el0_write(regs.tpidrro_el0 as u64);
|
||||
}
|
||||
} else {
|
||||
try_stop_context(info.pid, |context| {
|
||||
try_stop_context(context, |context| {
|
||||
context.arch.tpidr_el0 = regs.tpidr_el0;
|
||||
context.arch.tpidrro_el0 = regs.tpidrro_el0;
|
||||
Ok(())
|
||||
@@ -1623,24 +1547,19 @@ fn write_env_regs(&self, info: &Info, regs: EnvRegisters) -> Result<()> {
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "x86")]
|
||||
fn write_env_regs(&self, info: &Info, regs: EnvRegisters) -> Result<()> {
|
||||
fn write_env_regs(context: Arc<RwSpinlock<Context>>, regs: EnvRegisters) -> Result<()> {
|
||||
if !(RmmA::virt_is_valid(VirtualAddress::new(regs.fsbase as usize))
|
||||
&& RmmA::virt_is_valid(VirtualAddress::new(regs.gsbase as usize)))
|
||||
{
|
||||
return Err(Error::new(EINVAL));
|
||||
}
|
||||
|
||||
if info.pid == context::context_id() {
|
||||
if context::is_current(&context) {
|
||||
unsafe {
|
||||
(&mut *crate::gdt::pcr()).gdt[crate::gdt::GDT_USER_FS].set_offset(regs.fsbase);
|
||||
(&mut *crate::gdt::pcr()).gdt[crate::gdt::GDT_USER_GS].set_offset(regs.gsbase);
|
||||
|
||||
match context::contexts()
|
||||
.current()
|
||||
.ok_or(Error::new(ESRCH))?
|
||||
.write()
|
||||
.arch
|
||||
{
|
||||
match context.write().arch {
|
||||
ref mut arch => {
|
||||
arch.fsbase = regs.fsbase as usize;
|
||||
arch.gsbase = regs.gsbase as usize;
|
||||
@@ -1648,7 +1567,7 @@ fn write_env_regs(&self, info: &Info, regs: EnvRegisters) -> Result<()> {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
try_stop_context(info.pid, |context| {
|
||||
try_stop_context(context, |context| {
|
||||
context.arch.fsbase = regs.fsbase as usize;
|
||||
context.arch.gsbase = regs.gsbase as usize;
|
||||
Ok(())
|
||||
@@ -1658,26 +1577,21 @@ fn write_env_regs(&self, info: &Info, regs: EnvRegisters) -> Result<()> {
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
fn write_env_regs(cid: ContextId, regs: EnvRegisters) -> Result<()> {
|
||||
fn write_env_regs(context: Arc<RwSpinlock<Context>>, regs: EnvRegisters) -> Result<()> {
|
||||
if !(RmmA::virt_is_valid(VirtualAddress::new(regs.fsbase as usize))
|
||||
&& RmmA::virt_is_valid(VirtualAddress::new(regs.gsbase as usize)))
|
||||
{
|
||||
return Err(Error::new(EINVAL));
|
||||
}
|
||||
|
||||
if cid == context::current_cid() {
|
||||
if context::is_current(&context) {
|
||||
unsafe {
|
||||
x86::msr::wrmsr(x86::msr::IA32_FS_BASE, regs.fsbase as u64);
|
||||
// We have to write to KERNEL_GSBASE, because when the kernel returns to
|
||||
// userspace, it will have executed SWAPGS first.
|
||||
x86::msr::wrmsr(x86::msr::IA32_KERNEL_GSBASE, regs.gsbase as u64);
|
||||
|
||||
match context::contexts()
|
||||
.current()
|
||||
.ok_or(Error::new(ESRCH))?
|
||||
.write()
|
||||
.arch
|
||||
{
|
||||
match context::current().write().arch {
|
||||
ref mut arch => {
|
||||
arch.fsbase = regs.fsbase as usize;
|
||||
arch.gsbase = regs.gsbase as usize;
|
||||
@@ -1685,7 +1599,7 @@ fn write_env_regs(cid: ContextId, regs: EnvRegisters) -> Result<()> {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
try_stop_context(cid, |context| {
|
||||
try_stop_context(context, |context| {
|
||||
context.arch.fsbase = regs.fsbase as usize;
|
||||
context.arch.gsbase = regs.gsbase as usize;
|
||||
Ok(())
|
||||
@@ -1694,10 +1608,10 @@ fn write_env_regs(cid: ContextId, regs: EnvRegisters) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
fn read_env_regs(&self, info: &Info) -> Result<EnvRegisters> {
|
||||
fn read_env_regs(context: Arc<RwSpinlock<Context>>) -> Result<EnvRegisters> {
|
||||
use crate::device::cpu::registers::control_regs;
|
||||
|
||||
let (tpidr_el0, tpidrro_el0) = if info.pid == context::context_id() {
|
||||
let (tpidr_el0, tpidrro_el0) = if context::is_current(&context) {
|
||||
unsafe {
|
||||
(
|
||||
control_regs::tpidr_el0() as usize,
|
||||
@@ -1705,7 +1619,7 @@ fn read_env_regs(&self, info: &Info) -> Result<EnvRegisters> {
|
||||
)
|
||||
}
|
||||
} else {
|
||||
try_stop_context(info.pid, |context| {
|
||||
try_stop_context(context, |context| {
|
||||
Ok((context.arch.tpidr_el0, context.arch.tpidrro_el0))
|
||||
})?
|
||||
};
|
||||
@@ -1716,8 +1630,8 @@ fn read_env_regs(&self, info: &Info) -> Result<EnvRegisters> {
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "x86")]
|
||||
fn read_env_regs(&self, info: &Info) -> Result<EnvRegisters> {
|
||||
let (fsbase, gsbase) = if info.pid == context::context_id() {
|
||||
fn read_env_regs(context: Arc<RwSpinlock<Context>>) -> Result<EnvRegisters> {
|
||||
let (fsbase, gsbase) = if context::is_current(&context) {
|
||||
unsafe {
|
||||
(
|
||||
(&*crate::gdt::pcr()).gdt[crate::gdt::GDT_USER_FS].offset() as u64,
|
||||
@@ -1725,7 +1639,7 @@ fn read_env_regs(&self, info: &Info) -> Result<EnvRegisters> {
|
||||
)
|
||||
}
|
||||
} else {
|
||||
try_stop_context(info.pid, |context| {
|
||||
try_stop_context(context, |context| {
|
||||
Ok((context.arch.fsbase as u64, context.arch.gsbase as u64))
|
||||
})?
|
||||
};
|
||||
@@ -1736,9 +1650,9 @@ fn read_env_regs(&self, info: &Info) -> Result<EnvRegisters> {
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
fn read_env_regs(cid: ContextId) -> Result<EnvRegisters> {
|
||||
fn read_env_regs(context: Arc<RwSpinlock<Context>>) -> Result<EnvRegisters> {
|
||||
// TODO: Avoid rdmsr if fsgsbase is not enabled, if this is worth optimizing for.
|
||||
let (fsbase, gsbase) = if cid == context::current_cid() {
|
||||
let (fsbase, gsbase) = if context::is_current(&context) {
|
||||
unsafe {
|
||||
(
|
||||
x86::msr::rdmsr(x86::msr::IA32_FS_BASE),
|
||||
@@ -1746,7 +1660,7 @@ fn read_env_regs(cid: ContextId) -> Result<EnvRegisters> {
|
||||
)
|
||||
}
|
||||
} else {
|
||||
try_stop_context(cid, |context| {
|
||||
try_stop_context(context, |context| {
|
||||
Ok((context.arch.fsbase as u64, context.arch.gsbase as u64))
|
||||
})?
|
||||
};
|
||||
|
||||
+1
-5
@@ -77,11 +77,7 @@ impl KernelScheme for RootScheme {
|
||||
return Err(Error::new(EINVAL));
|
||||
}
|
||||
|
||||
let context = {
|
||||
let contexts = context::contexts();
|
||||
let context = contexts.current().ok_or(Error::new(ESRCH))?;
|
||||
Arc::downgrade(context)
|
||||
};
|
||||
let context = Arc::downgrade(&context::current());
|
||||
|
||||
let id = self.next_id.fetch_add(1, Ordering::Relaxed);
|
||||
|
||||
|
||||
@@ -10,9 +10,13 @@ pub fn resource() -> Result<Vec<u8>> {
|
||||
let mut rows = Vec::new();
|
||||
{
|
||||
let contexts = context::contexts();
|
||||
for (id, context_lock) in contexts.iter() {
|
||||
for context_lock in contexts.iter().filter_map(|r| r.0.upgrade()) {
|
||||
let context = context_lock.read();
|
||||
rows.push((*id, context.name.clone(), context.status_reason));
|
||||
rows.push((
|
||||
context.pid.get(),
|
||||
context.name.clone(),
|
||||
context.status_reason,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -27,8 +27,8 @@ pub fn resource() -> Result<Vec<u8>> {
|
||||
);
|
||||
{
|
||||
let contexts = context::contexts();
|
||||
for (_id, context_lock) in contexts.iter() {
|
||||
let context = context_lock.read();
|
||||
for context_ref in contexts.iter().filter_map(|r| r.0.upgrade()) {
|
||||
let context = context_ref.read();
|
||||
|
||||
let mut stat_string = String::new();
|
||||
// TODO: All user programs must have some grant in order for executable memory to even
|
||||
|
||||
@@ -3,7 +3,7 @@ use alloc::vec::Vec;
|
||||
use crate::{context, syscall::error::Result};
|
||||
|
||||
pub fn resource() -> Result<Vec<u8>> {
|
||||
Ok(context::current()?
|
||||
Ok(context::current()
|
||||
.read()
|
||||
.name
|
||||
.clone()
|
||||
|
||||
@@ -9,9 +9,13 @@ pub fn resource() -> Result<Vec<u8>> {
|
||||
let mut rows = Vec::new();
|
||||
{
|
||||
let contexts = context::contexts();
|
||||
for (id, context_lock) in contexts.iter() {
|
||||
let context = context_lock.read();
|
||||
rows.push((*id, context.name.clone(), context.files.read().clone()));
|
||||
for context_ref in contexts.iter().filter_map(|r| r.0.upgrade()) {
|
||||
let context = context_ref.read();
|
||||
rows.push((
|
||||
context.pid,
|
||||
context.name.clone(),
|
||||
context.files.read().clone(),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,10 +1,6 @@
|
||||
use alloc::vec::Vec;
|
||||
|
||||
use crate::{
|
||||
context::process,
|
||||
scheme,
|
||||
syscall::error::{Error, Result},
|
||||
};
|
||||
use crate::{context::process, scheme, syscall::error::Result};
|
||||
|
||||
pub fn resource() -> Result<Vec<u8>> {
|
||||
let scheme_ns = process::current()?.read().ens;
|
||||
|
||||
@@ -1,10 +1,6 @@
|
||||
use alloc::vec::Vec;
|
||||
|
||||
use crate::{
|
||||
context::process,
|
||||
scheme,
|
||||
syscall::error::{Error, Result, ESRCH},
|
||||
};
|
||||
use crate::{context::process, scheme, syscall::error::Result};
|
||||
|
||||
pub fn resource() -> Result<Vec<u8>> {
|
||||
let scheme_ns = process::current()?.read().ens;
|
||||
|
||||
@@ -10,9 +10,13 @@ pub fn resource() -> Result<Vec<u8>> {
|
||||
let mut rows = Vec::new();
|
||||
{
|
||||
let contexts = context::contexts();
|
||||
for (id, context_lock) in contexts.iter() {
|
||||
let context = context_lock.read();
|
||||
rows.push((*id, context.name.clone(), context.current_syscall()));
|
||||
for context_ref in contexts.iter().filter_map(|r| r.0.upgrade()) {
|
||||
let context = context_ref.read();
|
||||
rows.push((
|
||||
context.pid.get(),
|
||||
context.name.clone(),
|
||||
context.current_syscall(),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+11
-11
@@ -122,7 +122,7 @@ impl ParsedCqe {
|
||||
log::warn!(
|
||||
"Unknown scheme -> kernel message {} from {}",
|
||||
packet.a,
|
||||
context::current().unwrap().read().name
|
||||
context::current().read().name
|
||||
);
|
||||
|
||||
// Some schemes don't implement cancellation properly yet, so we temporarily
|
||||
@@ -276,7 +276,7 @@ impl UserInner {
|
||||
return Err(Error::new(ENODEV));
|
||||
}
|
||||
|
||||
let current_context = context::current()?;
|
||||
let current_context = context::current();
|
||||
|
||||
{
|
||||
let mut states = self.states.lock();
|
||||
@@ -295,7 +295,7 @@ impl UserInner {
|
||||
context::switch();
|
||||
|
||||
let eintr_if_sigkill = || {
|
||||
if context::current()?.read().being_sigkilled {
|
||||
if context::current().read().being_sigkilled {
|
||||
// EINTR directly if SIGKILL was found without waiting for scheme. Data loss
|
||||
// doesn't matter.
|
||||
Err(Error::new(EINTR))
|
||||
@@ -317,7 +317,7 @@ impl UserInner {
|
||||
*o = old_state;
|
||||
drop(states);
|
||||
eintr_if_sigkill()?;
|
||||
context::current()?.write().block("UserInner::call");
|
||||
context::current().write().block("UserInner::call");
|
||||
}
|
||||
// spurious wakeup
|
||||
State::Waiting {
|
||||
@@ -342,7 +342,7 @@ impl UserInner {
|
||||
..Default::default()
|
||||
});
|
||||
event::trigger(self.root_id, self.handle_id, EVENT_READ);
|
||||
context::current()?.write().block("UserInner::call");
|
||||
context::current().write().block("UserInner::call");
|
||||
}
|
||||
|
||||
// invalid state
|
||||
@@ -830,7 +830,7 @@ impl UserInner {
|
||||
|
||||
let tag = self.next_id()?;
|
||||
let mut states = self.states.lock();
|
||||
states[tag as usize] = State::Fmap(Arc::downgrade(&context::current()?));
|
||||
states[tag as usize] = State::Fmap(Arc::downgrade(&context::current()));
|
||||
|
||||
/*self.todo.send(Packet {
|
||||
id: packet_id,
|
||||
@@ -855,7 +855,7 @@ impl UserInner {
|
||||
0,
|
||||
uid_gid_hack_merge(current_uid_gid()?),
|
||||
],
|
||||
caller: context::current()?.read().pid.get() as u64,
|
||||
caller: context::current().read().pid.get() as u64,
|
||||
});
|
||||
event::trigger(self.root_id, self.handle_id, EVENT_READ);
|
||||
|
||||
@@ -869,7 +869,7 @@ impl UserInner {
|
||||
ParsedCqe::ResponseWithFd { tag, fd } => self.respond(
|
||||
tag,
|
||||
Response::Fd(
|
||||
context::current()?
|
||||
context::current()
|
||||
.read()
|
||||
.remove_file(FileHandle::from(fd))
|
||||
.ok_or(Error::new(EINVAL))?
|
||||
@@ -894,7 +894,7 @@ impl UserInner {
|
||||
// FIXME: Description can leak if context::current() fails, or if there is no
|
||||
// additional file table space.
|
||||
if flags.contains(FobtainFdFlags::MANUAL_FD) {
|
||||
context::current()?.read().insert_file(
|
||||
context::current().read().insert_file(
|
||||
FileHandle::from(dst_fd_or_ptr),
|
||||
FileDescriptor {
|
||||
description,
|
||||
@@ -902,7 +902,7 @@ impl UserInner {
|
||||
},
|
||||
);
|
||||
} else {
|
||||
let fd = context::current()?
|
||||
let fd = context::current()
|
||||
.read()
|
||||
.add_file(FileDescriptor {
|
||||
description,
|
||||
@@ -1089,7 +1089,7 @@ impl UserInner {
|
||||
}
|
||||
|
||||
let (pid, desc) = {
|
||||
let context_lock = context::current()?;
|
||||
let context_lock = context::current();
|
||||
let context = context_lock.read();
|
||||
// TODO: Faster, cleaner mechanism to get descriptor
|
||||
let mut desc_res = Err(Error::new(EBADF));
|
||||
|
||||
+20
-22
@@ -1,4 +1,7 @@
|
||||
use alloc::{sync::Arc, vec::Vec};
|
||||
use alloc::{
|
||||
sync::{Arc, Weak},
|
||||
vec::Vec,
|
||||
};
|
||||
use spin::{Mutex, MutexGuard};
|
||||
use spinning_top::RwSpinlock;
|
||||
|
||||
@@ -6,7 +9,7 @@ use crate::context::{self, Context};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct WaitCondition {
|
||||
contexts: Mutex<Vec<Arc<RwSpinlock<Context>>>>,
|
||||
contexts: Mutex<Vec<Weak<RwSpinlock<Context>>>>,
|
||||
}
|
||||
|
||||
impl WaitCondition {
|
||||
@@ -20,8 +23,10 @@ impl WaitCondition {
|
||||
pub fn notify(&self) -> usize {
|
||||
let mut contexts = self.contexts.lock();
|
||||
let len = contexts.len();
|
||||
while let Some(context_lock) = contexts.pop() {
|
||||
context_lock.write().unblock();
|
||||
while let Some(context_weak) = contexts.pop() {
|
||||
if let Some(context_ref) = context_weak.upgrade() {
|
||||
context_ref.write().unblock();
|
||||
}
|
||||
}
|
||||
len
|
||||
}
|
||||
@@ -30,34 +35,31 @@ impl WaitCondition {
|
||||
pub unsafe fn notify_signal(&self) -> usize {
|
||||
let contexts = self.contexts.lock();
|
||||
let len = contexts.len();
|
||||
for context_lock in contexts.iter() {
|
||||
context_lock.write().unblock();
|
||||
for context_weak in contexts.iter() {
|
||||
if let Some(context_ref) = context_weak.upgrade() {
|
||||
context_ref.write().unblock();
|
||||
}
|
||||
}
|
||||
len
|
||||
}
|
||||
|
||||
// Wait until notified. Unlocks guard when blocking is ready. Returns false if resumed by a signal or the notify_signal function
|
||||
pub fn wait<T>(&self, guard: MutexGuard<T>, reason: &'static str) -> bool {
|
||||
let cid;
|
||||
let current_context_ref = context::current();
|
||||
{
|
||||
let context_lock = {
|
||||
let contexts = context::contexts();
|
||||
let context_lock = contexts.current().expect("WaitCondition::wait: no context");
|
||||
Arc::clone(context_lock)
|
||||
};
|
||||
|
||||
{
|
||||
let mut context = context_lock.write();
|
||||
let mut context = current_context_ref.write();
|
||||
if let Some((control, _, _)) = context.sigcontrol()
|
||||
&& control.currently_pending_unblocked() != 0
|
||||
{
|
||||
return false;
|
||||
}
|
||||
cid = context.cid;
|
||||
context.block(reason);
|
||||
}
|
||||
|
||||
self.contexts.lock().push(context_lock);
|
||||
self.contexts
|
||||
.lock()
|
||||
.push(Arc::downgrade(¤t_context_ref));
|
||||
|
||||
drop(guard);
|
||||
}
|
||||
@@ -69,14 +71,10 @@ impl WaitCondition {
|
||||
{
|
||||
let mut contexts = self.contexts.lock();
|
||||
|
||||
// TODO: retain
|
||||
let mut i = 0;
|
||||
while i < contexts.len() {
|
||||
let remove = {
|
||||
let context = contexts[i].read();
|
||||
context.cid == cid
|
||||
};
|
||||
|
||||
if remove {
|
||||
if Weak::as_ptr(&contexts[i]) == Arc::as_ptr(¤t_context_ref) {
|
||||
contexts.remove(i);
|
||||
waited = false;
|
||||
break;
|
||||
|
||||
+12
-2
@@ -243,7 +243,12 @@ pub fn debug_start([a, b, c, d, e, f]: [usize; 6]) {
|
||||
let contexts = crate::context::contexts();
|
||||
if let Some(context_lock) = contexts.current() {
|
||||
let context = context_lock.read();
|
||||
print!("{} ({}/{}): ", context.name, context.pid.get(), context.cid.get());
|
||||
print!(
|
||||
"{} ({}/{}): ",
|
||||
context.name,
|
||||
context.pid.get(),
|
||||
context.cid.get()
|
||||
);
|
||||
}
|
||||
|
||||
// Do format_call outside print! so possible exception handlers cannot reentrantly
|
||||
@@ -279,7 +284,12 @@ pub fn debug_end([a, b, c, d, e, f]: [usize; 6], result: Result<usize>) {
|
||||
let contexts = crate::context::contexts();
|
||||
if let Some(context_lock) = contexts.current() {
|
||||
let context = context_lock.read();
|
||||
print!("{} ({}/{}): ", context.name, context.pid.get(), context.cid.get());
|
||||
print!(
|
||||
"{} ({}/{}): ",
|
||||
context.name,
|
||||
context.pid.get(),
|
||||
context.cid.get()
|
||||
);
|
||||
}
|
||||
|
||||
// Do format_call outside print! so possible exception handlers cannot reentrantly
|
||||
|
||||
@@ -3,7 +3,7 @@ use alloc::sync::Arc;
|
||||
use crate::{
|
||||
context::{self, process},
|
||||
paging::VirtualAddress,
|
||||
syscall::error::{Error, Result, EFAULT, EPERM, ESRCH},
|
||||
syscall::error::{Error, Result, EFAULT, EPERM},
|
||||
};
|
||||
fn enforce_root() -> Result<()> {
|
||||
if process::current()?.read().euid != 0 {
|
||||
@@ -21,7 +21,7 @@ pub fn iopl(level: usize) -> Result<usize> {
|
||||
pub fn iopl(level: usize) -> Result<usize> {
|
||||
enforce_root()?;
|
||||
|
||||
context::current()?
|
||||
context::current()
|
||||
.write()
|
||||
.set_userspace_io_allowed(level >= 3);
|
||||
|
||||
@@ -31,7 +31,7 @@ pub fn iopl(level: usize) -> Result<usize> {
|
||||
pub fn virttophys(virtual_address: usize) -> Result<usize> {
|
||||
enforce_root()?;
|
||||
|
||||
let addr_space = Arc::clone(context::current()?.read().addr_space()?);
|
||||
let addr_space = Arc::clone(context::current().read().addr_space()?);
|
||||
let addr_space = addr_space.acquire_read();
|
||||
|
||||
match addr_space
|
||||
|
||||
+13
-16
@@ -27,7 +27,7 @@ pub fn file_op_generic_ext<T>(
|
||||
fd: FileHandle,
|
||||
op: impl FnOnce(&dyn KernelScheme, Arc<RwLock<FileDescription>>, FileDescription) -> Result<T>,
|
||||
) -> Result<T> {
|
||||
let file = context::current()?
|
||||
let file = context::current()
|
||||
.read()
|
||||
.get_file(fd)
|
||||
.ok_or(Error::new(EBADF))?;
|
||||
@@ -101,7 +101,7 @@ pub fn open(raw_path: UserSliceRo, flags: usize) -> Result<FileHandle> {
|
||||
};
|
||||
//drop(path_buf);
|
||||
|
||||
context::current()?
|
||||
context::current()
|
||||
.read()
|
||||
.add_file(FileDescriptor {
|
||||
description,
|
||||
@@ -160,7 +160,7 @@ pub fn unlink(raw_path: UserSliceRo) -> Result<()> {
|
||||
/// Close syscall
|
||||
pub fn close(fd: FileHandle) -> Result<()> {
|
||||
let file = {
|
||||
let context_lock = context::current()?;
|
||||
let context_lock = context::current();
|
||||
let context = context_lock.read();
|
||||
context.remove_file(fd).ok_or(Error::new(EBADF))?
|
||||
};
|
||||
@@ -170,7 +170,7 @@ 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()?
|
||||
let file = context::current()
|
||||
.read()
|
||||
.get_file(fd)
|
||||
.ok_or(Error::new(EBADF))?;
|
||||
@@ -214,7 +214,7 @@ fn duplicate_file(fd: FileHandle, user_buf: UserSliceRo) -> Result<FileDescripto
|
||||
pub fn dup(fd: FileHandle, buf: UserSliceRo) -> Result<FileHandle> {
|
||||
let new_file = duplicate_file(fd, buf)?;
|
||||
|
||||
context::current()?
|
||||
context::current()
|
||||
.read()
|
||||
.add_file(new_file)
|
||||
.ok_or(Error::new(EMFILE))
|
||||
@@ -228,9 +228,8 @@ pub fn dup2(fd: FileHandle, new_fd: FileHandle, buf: UserSliceRo) -> Result<File
|
||||
let _ = close(new_fd);
|
||||
let new_file = duplicate_file(fd, buf)?;
|
||||
|
||||
let contexts = context::contexts();
|
||||
let context_lock = contexts.current().ok_or(Error::new(ESRCH))?;
|
||||
let context = context_lock.read();
|
||||
let context_ref = context::current();
|
||||
let context = context_ref.read();
|
||||
|
||||
context
|
||||
.insert_file(new_fd, new_file)
|
||||
@@ -241,7 +240,7 @@ pub fn sendfd(socket: FileHandle, fd: FileHandle, flags_raw: usize, arg: u64) ->
|
||||
let requested_flags = SendFdFlags::from_bits(flags_raw).ok_or(Error::new(EINVAL))?;
|
||||
|
||||
let (scheme, number, desc_to_send) = {
|
||||
let current_lock = context::current()?;
|
||||
let current_lock = context::current();
|
||||
let current = current_lock.read();
|
||||
|
||||
// TODO: Ensure deadlocks can't happen
|
||||
@@ -287,7 +286,7 @@ pub fn sendfd(socket: FileHandle, fd: FileHandle, flags_raw: usize, arg: u64) ->
|
||||
|
||||
/// File descriptor controls
|
||||
pub fn fcntl(fd: FileHandle, cmd: usize, arg: usize) -> Result<usize> {
|
||||
let file = context::current()?
|
||||
let file = context::current()
|
||||
.read()
|
||||
.get_file(fd)
|
||||
.ok_or(Error::new(EBADF))?;
|
||||
@@ -298,8 +297,7 @@ pub fn fcntl(fd: FileHandle, cmd: usize, arg: usize) -> Result<usize> {
|
||||
// Not in match because 'files' cannot be locked
|
||||
let new_file = duplicate_file(fd, UserSlice::empty())?;
|
||||
|
||||
let contexts = context::contexts();
|
||||
let context_lock = contexts.current().ok_or(Error::new(ESRCH))?;
|
||||
let context_lock = context::current();
|
||||
let context = context_lock.read();
|
||||
|
||||
return context
|
||||
@@ -320,8 +318,7 @@ pub fn fcntl(fd: FileHandle, cmd: usize, arg: usize) -> Result<usize> {
|
||||
|
||||
// Perform kernel operation if scheme agrees
|
||||
{
|
||||
let contexts = context::contexts();
|
||||
let context_lock = contexts.current().ok_or(Error::new(ESRCH))?;
|
||||
let context_lock = context::current();
|
||||
let context = context_lock.read();
|
||||
|
||||
let mut files = context.files.write();
|
||||
@@ -364,7 +361,7 @@ pub fn frename(fd: FileHandle, raw_path: UserSliceRo) -> Result<()> {
|
||||
process.ens,
|
||||
),
|
||||
};
|
||||
let file = context::current()?
|
||||
let file = context::current()
|
||||
.read()
|
||||
.get_file(fd)
|
||||
.ok_or(Error::new(EBADF))?;
|
||||
@@ -433,7 +430,7 @@ pub fn funmap(virtual_address: usize, length: usize) -> Result<usize> {
|
||||
);
|
||||
}
|
||||
|
||||
let addr_space = Arc::clone(context::current()?.read().addr_space()?);
|
||||
let addr_space = Arc::clone(context::current().read().addr_space()?);
|
||||
let span = PageSpan::validate_nonempty(VirtualAddress::new(virtual_address), length_aligned)
|
||||
.ok_or(Error::new(EINVAL))?;
|
||||
let unpin = false;
|
||||
|
||||
@@ -89,7 +89,7 @@ pub fn futex(addr: usize, op: usize, val: usize, val2: usize, _addr2: usize) ->
|
||||
{
|
||||
let mut futexes = FUTEXES.write();
|
||||
|
||||
let context_lock = context::current()?;
|
||||
let context_lock = context::current();
|
||||
|
||||
let (fetched, expected) = if op == FUTEX_WAIT {
|
||||
// Must be aligned, otherwise it could cross a page boundary and mess up the
|
||||
@@ -162,7 +162,7 @@ pub fn futex(addr: usize, op: usize, val: usize, val2: usize, _addr2: usize) ->
|
||||
context::switch();
|
||||
|
||||
if timeout_opt.is_some() {
|
||||
context::current()?.write().wake = None;
|
||||
context::current().write().wake = None;
|
||||
Err(Error::new(ETIMEDOUT))
|
||||
} else {
|
||||
Ok(0)
|
||||
|
||||
@@ -35,7 +35,7 @@ pub fn exit(status: usize) -> ! {
|
||||
);
|
||||
|
||||
{
|
||||
let context_lock = context::current().expect("exit failed to find context");
|
||||
let context_lock = context::current();
|
||||
|
||||
let close_files;
|
||||
let addrspace_opt;
|
||||
@@ -175,7 +175,7 @@ pub fn kill(pid: ProcessId, sig: usize, parent_sigchld: bool) -> Result<usize> {
|
||||
}
|
||||
|
||||
let mut send = |context: &mut context::Context, proc: &ProcessInfo| -> SendResult {
|
||||
let is_self = context.cid == context::current_cid();
|
||||
let is_self = context.is_current_context();
|
||||
|
||||
// Non-root users cannot kill arbitrarily.
|
||||
if euid != 0 && euid != proc.ruid && ruid != proc.ruid {
|
||||
@@ -640,9 +640,7 @@ pub unsafe fn usermode_bootstrap(bootstrap: &Bootstrap) {
|
||||
|
||||
{
|
||||
let addr_space = Arc::clone(
|
||||
context::contexts()
|
||||
.current()
|
||||
.expect("expected a context to exist when executing init")
|
||||
context::current()
|
||||
.read()
|
||||
.addr_space()
|
||||
.expect("expected bootstrap context to have an address space"),
|
||||
@@ -689,7 +687,6 @@ pub unsafe fn usermode_bootstrap(bootstrap: &Bootstrap) {
|
||||
// Start in a minimal environment without any stack.
|
||||
|
||||
match context::current()
|
||||
.expect("bootstrap was not running inside any context")
|
||||
.write()
|
||||
.regs_mut()
|
||||
.expect("bootstrap needs registers to be available")
|
||||
|
||||
+1
-1
@@ -30,7 +30,7 @@ pub fn nanosleep(req_buf: UserSliceRo, rem_buf_opt: Option<UserSliceWo>) -> Resu
|
||||
let start = time::monotonic();
|
||||
let end = start + (req.tv_sec as u128 * time::NANOS_PER_SEC) + (req.tv_nsec as u128);
|
||||
|
||||
let current_context = context::current()?;
|
||||
let current_context = context::current();
|
||||
{
|
||||
let mut context = current_context.write();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user