Add rustfmt from relibc and apply it with cargo fmt

This commit is contained in:
Jeremy Soller
2024-01-17 13:52:01 -07:00
parent 73897bd83d
commit 45f1c4e29e
166 changed files with 7353 additions and 3851 deletions
+48 -40
View File
@@ -1,16 +1,20 @@
use alloc::sync::Arc;
use core::arch::asm;
use core::mem;
use core::ptr;
use core::sync::atomic::{AtomicBool, Ordering};
use core::mem::offset_of;
use core::{
arch::asm,
mem,
mem::offset_of,
ptr,
sync::atomic::{AtomicBool, Ordering},
};
use spin::Once;
use crate::{push_scratch, pop_scratch};
use crate::interrupt::handler::ScratchRegisters;
use crate::device::cpu::registers::{control_regs, tlb};
use crate::paging::{RmmA, RmmArch, TableKind};
use crate::syscall::FloatRegisters;
use crate::{
device::cpu::registers::{control_regs, tlb},
interrupt::handler::ScratchRegisters,
paging::{RmmA, RmmArch, TableKind},
pop_scratch, push_scratch,
syscall::FloatRegisters,
};
/// This must be used by the kernel to ensure that context switches are done atomically
/// Compare and exchange this to true when beginning a context switch on any CPU
@@ -25,24 +29,24 @@ pub const KFX_ALIGN: usize = 16;
pub struct Context {
elr_el1: usize,
sp_el0: usize,
pub(crate) tpidr_el0: usize, /* Pointer to TLS region for this Context */
pub(crate) tpidr_el0: usize, /* Pointer to TLS region for this Context */
pub(crate) tpidrro_el0: usize, /* Pointer to TLS (read-only) region for this Context */
spsr_el1: usize,
esr_el1: usize,
fx_loadable: bool,
sp: usize, /* Stack Pointer (x31) */
lr: usize, /* Link Register (x30) */
fp: usize, /* Frame pointer Register (x29) */
x28: usize, /* Callee saved Register */
x27: usize, /* Callee saved Register */
x26: usize, /* Callee saved Register */
x25: usize, /* Callee saved Register */
x24: usize, /* Callee saved Register */
x23: usize, /* Callee saved Register */
x22: usize, /* Callee saved Register */
x21: usize, /* Callee saved Register */
x20: usize, /* Callee saved Register */
x19: usize, /* Callee saved Register */
sp: usize, /* Stack Pointer (x31) */
lr: usize, /* Link Register (x30) */
fp: usize, /* Frame pointer Register (x29) */
x28: usize, /* Callee saved Register */
x27: usize, /* Callee saved Register */
x26: usize, /* Callee saved Register */
x25: usize, /* Callee saved Register */
x24: usize, /* Callee saved Register */
x23: usize, /* Callee saved Register */
x22: usize, /* Callee saved Register */
x21: usize, /* Callee saved Register */
x20: usize, /* Callee saved Register */
x19: usize, /* Callee saved Register */
}
impl Context {
@@ -92,7 +96,7 @@ impl Context {
self.tpidrro_el0
}
pub unsafe fn signal_stack(&mut self, handler: extern fn(usize), sig: u8) {
pub unsafe fn signal_stack(&mut self, handler: extern "C" fn(usize), sig: u8) {
let lr = self.lr.clone();
self.push_pair((sig as usize, lr));
self.push_pair((0 as usize, handler as usize));
@@ -148,9 +152,7 @@ impl super::Context {
panic!("TODO: make get_fx_regs always work");
}
unsafe {
ptr::read(self.kfx.as_ptr() as *const FloatRegisters)
}
unsafe { ptr::read(self.kfx.as_ptr() as *const FloatRegisters) }
}
pub fn set_fx_regs(&mut self, mut new: FloatRegisters) {
@@ -231,16 +233,22 @@ pub unsafe fn switch_to(prev: &mut super::Context, next: &mut super::Context) {
// Since Arc is essentially just wraps a pointer, in this case a regular pointer (as
// opposed to dyn or slice fat pointers), and NonNull optimization exists, map_or will
// hopefully be optimized down to checking prev and next pointers, as next cannot be null.
Some(ref next_space) => if prev.addr_space.as_ref().map_or(true, |prev_space| !Arc::ptr_eq(&prev_space, &next_space)) {
// Suppose we have two sibling threads A and B. A runs on CPU 0 and B on CPU 1. A
// recently called yield and is now here about to switch back. Meanwhile, B is
// currently creating a new mapping in their shared address space, for example a
// message on a channel.
//
// Unless we acquire this lock, it may be possible that the TLB will not contain new
// entries. While this can be caught and corrected in a page fault handler, this is not
// true when entries are removed from a page table!
next_space.read().table.utable.make_current();
Some(ref next_space) => {
if prev
.addr_space
.as_ref()
.map_or(true, |prev_space| !Arc::ptr_eq(&prev_space, &next_space))
{
// Suppose we have two sibling threads A and B. A runs on CPU 0 and B on CPU 1. A
// recently called yield and is now here about to switch back. Meanwhile, B is
// currently creating a new mapping in their shared address space, for example a
// message on a channel.
//
// Unless we acquire this lock, it may be possible that the TLB will not contain new
// entries. While this can be caught and corrected in a page fault handler, this is not
// true when entries are removed from a page table!
next_space.read().table.utable.make_current();
}
}
None => {
RmmA::set_table(TableKind::User, empty_cr3());
@@ -357,13 +365,13 @@ unsafe extern "C" fn switch_to_inner(_prev: &mut Context, _next: &mut Context) {
pub struct SignalHandlerStack {
scratch: ScratchRegisters,
padding: usize,
handler: extern fn(usize),
handler: extern "C" fn(usize),
sig: usize,
lr: usize,
}
#[naked]
unsafe extern fn signal_handler_wrapper() {
unsafe extern "C" fn signal_handler_wrapper() {
#[inline(never)]
unsafe extern "C" fn inner(stack: &SignalHandlerStack) {
(stack.handler)(stack.sig);
+26 -19
View File
@@ -1,13 +1,14 @@
use core::mem;
use core::sync::atomic::AtomicBool;
use core::{mem, sync::atomic::AtomicBool};
use alloc::sync::Arc;
use crate::{push_scratch, pop_scratch};
use crate::gdt::{pcr, GDT_USER_FS, GDT_USER_GS};
use crate::interrupt::handler::ScratchRegisters;
use crate::paging::{RmmA, RmmArch, TableKind};
use crate::syscall::FloatRegisters;
use crate::{
gdt::{pcr, GDT_USER_FS, GDT_USER_GS},
interrupt::handler::ScratchRegisters,
paging::{RmmA, RmmArch, TableKind},
pop_scratch, push_scratch,
syscall::FloatRegisters,
};
use core::mem::offset_of;
use spin::Once;
@@ -67,7 +68,7 @@ impl Context {
self.esp = address;
}
pub unsafe fn signal_stack(&mut self, handler: extern fn(usize), sig: u8) {
pub unsafe fn signal_stack(&mut self, handler: extern "C" fn(usize), sig: u8) {
self.push_stack(sig as usize);
self.push_stack(handler as usize);
self.push_stack(signal_handler_wrapper as usize);
@@ -148,16 +149,22 @@ pub unsafe fn switch_to(prev: &mut super::Context, next: &mut super::Context) {
// Since Arc is essentially just wraps a pointer, in this case a regular pointer (as
// opposed to dyn or slice fat pointers), and NonNull optimization exists, map_or will
// hopefully be optimized down to checking prev and next pointers, as next cannot be null.
Some(ref next_space) => if prev.addr_space.as_ref().map_or(true, |prev_space| !Arc::ptr_eq(&prev_space, &next_space)) {
// Suppose we have two sibling threads A and B. A runs on CPU 0 and B on CPU 1. A
// recently called yield and is now here about to switch back. Meanwhile, B is
// currently creating a new mapping in their shared address space, for example a
// message on a channel.
//
// Unless we acquire this lock, it may be possible that the TLB will not contain new
// entries. While this can be caught and corrected in a page fault handler, this is not
// true when entries are removed from a page table!
next_space.read().table.utable.make_current();
Some(ref next_space) => {
if prev
.addr_space
.as_ref()
.map_or(true, |prev_space| !Arc::ptr_eq(&prev_space, &next_space))
{
// Suppose we have two sibling threads A and B. A runs on CPU 0 and B on CPU 1. A
// recently called yield and is now here about to switch back. Meanwhile, B is
// currently creating a new mapping in their shared address space, for example a
// message on a channel.
//
// Unless we acquire this lock, it may be possible that the TLB will not contain new
// entries. While this can be caught and corrected in a page fault handler, this is not
// true when entries are removed from a page table!
next_space.read().table.utable.make_current();
}
}
None => {
RmmA::set_table(TableKind::User, empty_cr3());
@@ -238,7 +245,7 @@ unsafe extern "cdecl" fn switch_to_inner() {
#[repr(packed)]
pub struct SignalHandlerStack {
scratch: ScratchRegisters,
handler: extern fn(usize),
handler: extern "C" fn(usize),
sig: usize,
eip: usize,
}
+30 -20
View File
@@ -1,13 +1,17 @@
use core::mem;
use core::ptr::{addr_of, addr_of_mut};
use core::sync::atomic::AtomicBool;
use core::{
mem,
ptr::{addr_of, addr_of_mut},
sync::atomic::AtomicBool,
};
use alloc::sync::Arc;
use crate::{push_scratch, pop_scratch};
use crate::interrupt::handler::ScratchRegisters;
use crate::paging::{RmmA, RmmArch, TableKind};
use crate::syscall::FloatRegisters;
use crate::{
interrupt::handler::ScratchRegisters,
paging::{RmmA, RmmArch, TableKind},
pop_scratch, push_scratch,
syscall::FloatRegisters,
};
use core::mem::offset_of;
use spin::Once;
@@ -78,7 +82,7 @@ impl Context {
self.rsp = address;
}
pub unsafe fn signal_stack(&mut self, handler: extern fn(usize), sig: u8) {
pub unsafe fn signal_stack(&mut self, handler: extern "C" fn(usize), sig: u8) {
self.push_stack(sig as usize);
self.push_stack(handler as usize);
self.push_stack(signal_handler_wrapper as usize);
@@ -217,16 +221,22 @@ pub unsafe fn switch_to(prev: &mut super::Context, next: &mut super::Context) {
// Since Arc essentially just wraps a pointer, in this case a regular pointer (as opposed
// to dyn or slice fat pointers), and NonNull optimization exists, map_or will hopefully be
// optimized down to checking prev and next pointers, as next cannot be null.
Some(ref next_space) => if prev.addr_space.as_ref().map_or(true, |prev_space| !Arc::ptr_eq(prev_space, next_space)) {
// Suppose we have two sibling threads A and B. A runs on CPU 0 and B on CPU 1. A
// recently called yield and is now here about to switch back. Meanwhile, B is
// currently creating a new mapping in their shared address space, for example a
// message on a channel.
//
// Unless we acquire this lock, it may be possible that the TLB will not contain new
// entries. While this can be caught and corrected in a page fault handler, this is not
// true when entries are removed from a page table!
next_space.read().table.utable.make_current();
Some(ref next_space) => {
if prev
.addr_space
.as_ref()
.map_or(true, |prev_space| !Arc::ptr_eq(prev_space, next_space))
{
// Suppose we have two sibling threads A and B. A runs on CPU 0 and B on CPU 1. A
// recently called yield and is now here about to switch back. Meanwhile, B is
// currently creating a new mapping in their shared address space, for example a
// message on a channel.
//
// Unless we acquire this lock, it may be possible that the TLB will not contain new
// entries. While this can be caught and corrected in a page fault handler, this is not
// true when entries are removed from a page table!
next_space.read().table.utable.make_current();
}
}
None => {
RmmA::set_table(TableKind::User, empty_cr3());
@@ -308,13 +318,13 @@ unsafe extern "sysv64" fn switch_to_inner(_prev: &mut Context, _next: &mut Conte
#[repr(packed)]
pub struct SignalHandlerStack {
scratch: ScratchRegisters,
handler: extern fn(usize),
handler: extern "C" fn(usize),
sig: usize,
rip: usize,
}
#[naked]
unsafe extern fn signal_handler_wrapper() {
unsafe extern "C" fn signal_handler_wrapper() {
#[inline(never)]
unsafe extern "C" fn inner(stack: &SignalHandlerStack) {
(stack.handler)(stack.sig);
+94 -48
View File
@@ -1,31 +1,24 @@
use core::{
cmp::Ordering,
mem,
};
use alloc::{
boxed::Box,
collections::VecDeque,
sync::Arc,
vec::Vec, borrow::Cow,
};
use alloc::{borrow::Cow, boxed::Box, collections::VecDeque, sync::Arc, vec::Vec};
use core::{cmp::Ordering, mem};
use spin::RwLock;
use crate::{LogicalCpuId, LogicalCpuSet};
use crate::arch::{interrupt::InterruptStack, paging::PAGE_SIZE};
use crate::common::aligned_box::AlignedBox;
use crate::common::unique::Unique;
use crate::context::{self, arch};
use crate::context::file::FileDescriptor;
use crate::context::memory::AddrSpace;
use crate::ipi::{ipi, IpiKind, IpiTarget};
use crate::paging::{RmmA, RmmArch};
use crate::memory::{RaiiFrame, Frame};
use crate::scheme::{SchemeNamespace, FileHandle, CallerCtx};
use crate::sync::WaitMap;
use crate::{
arch::{interrupt::InterruptStack, paging::PAGE_SIZE},
common::{aligned_box::AlignedBox, unique::Unique},
context::{self, arch, file::FileDescriptor, memory::AddrSpace},
ipi::{ipi, IpiKind, IpiTarget},
memory::{Frame, RaiiFrame},
paging::{RmmA, RmmArch},
scheme::{CallerCtx, FileHandle, SchemeNamespace},
sync::WaitMap,
LogicalCpuId, LogicalCpuSet,
};
use crate::syscall::data::SigAction;
use crate::syscall::error::{Result, Error, EAGAIN, ESRCH};
use crate::syscall::flag::{SIG_DFL, SigActionFlags};
use crate::syscall::{
data::SigAction,
error::{Error, Result, EAGAIN, ESRCH},
flag::{SigActionFlags, SIG_DFL},
};
/// Unique identifier for a context (i.e. `pid`).
use ::core::sync::atomic::AtomicUsize;
@@ -40,14 +33,15 @@ pub enum Status {
Runnable,
// TODO: Rename to SoftBlocked and move status_reason to this variant.
/// Not currently runnable, typically due to some blocking syscall, but it can be trivially
/// unblocked by e.g. signals.
Blocked,
/// Not currently runnable, and cannot be runnable until manually unblocked, depending on what
/// reason.
HardBlocked { reason: HardBlockedReason },
HardBlocked {
reason: HardBlockedReason,
},
Stopped(usize),
Exited(usize),
@@ -188,11 +182,16 @@ pub struct Context {
/// The architecture specific context
pub arch: arch::Context,
/// Kernel FX - used to store SIMD and FPU registers on context switch
pub kfx: AlignedBox<[u8], {arch::KFX_ALIGN}>,
pub kfx: AlignedBox<[u8], { arch::KFX_ALIGN }>,
/// Kernel stack
pub kstack: Option<Box<[u8]>>,
/// Kernel signal backup: Registers, Kernel FX, Kernel Stack, Signal number
pub ksig: Option<(arch::Context, AlignedBox<[u8], {arch::KFX_ALIGN}>, Option<Box<[u8]>>, u8)>,
pub ksig: Option<(
arch::Context,
AlignedBox<[u8], { arch::KFX_ALIGN }>,
Option<Box<[u8]>>,
u8,
)>,
/// Restore ksig context on next switch
pub ksig_restore: bool,
/// Address space containing a page table lock, and grants. Normally this will have a value,
@@ -257,7 +256,7 @@ impl Context {
pending: VecDeque::new(),
wake: None,
arch: arch::Context::new(),
kfx: AlignedBox::<[u8], {arch::KFX_ALIGN}>::try_zeroed_slice(crate::arch::kfx_size())?,
kfx: AlignedBox::<[u8], { arch::KFX_ALIGN }>::try_zeroed_slice(crate::arch::kfx_size())?,
kstack: None,
ksig: None,
ksig_restore: false,
@@ -299,10 +298,10 @@ impl Context {
pub fn unblock(&mut self) -> bool {
if self.unblock_no_ipi() {
if let Some(cpu_id) = self.cpu_id {
if cpu_id != crate::cpu_id() {
if cpu_id != crate::cpu_id() {
// Send IPI if not on current CPU
ipi(IpiKind::Wakeup, IpiTarget::Other);
}
}
}
true
@@ -396,25 +395,37 @@ impl Context {
pub fn addr_space(&self) -> Result<&Arc<RwLock<AddrSpace>>> {
self.addr_space.as_ref().ok_or(Error::new(ESRCH))
}
pub fn set_addr_space(&mut self, addr_space: Arc<RwLock<AddrSpace>>) -> Option<Arc<RwLock<AddrSpace>>> {
pub fn set_addr_space(
&mut self,
addr_space: Arc<RwLock<AddrSpace>>,
) -> Option<Arc<RwLock<AddrSpace>>> {
if self.id == super::context_id() {
unsafe { addr_space.read().table.utable.make_current(); }
unsafe {
addr_space.read().table.utable.make_current();
}
}
self.addr_space.replace(addr_space)
}
pub fn empty_actions() -> Arc<RwLock<Vec<(SigAction, usize)>>> {
Arc::new(RwLock::new(vec![(
SigAction {
sa_handler: unsafe { mem::transmute(SIG_DFL) },
sa_mask: [0; 2],
sa_flags: SigActionFlags::empty(),
},
0
); 128]))
Arc::new(RwLock::new(vec![
(
SigAction {
sa_handler: unsafe { mem::transmute(SIG_DFL) },
sa_mask: [0; 2],
sa_flags: SigActionFlags::empty(),
},
0
);
128
]))
}
pub fn caller_ctx(&self) -> CallerCtx {
CallerCtx { pid: self.id.into(), uid: self.euid, gid: self.egid }
CallerCtx {
pid: self.id.into(),
uid: self.euid,
gid: self.egid,
}
}
}
@@ -427,21 +438,51 @@ pub struct BorrowedHtBuf {
impl BorrowedHtBuf {
pub fn head() -> Result<Self> {
Ok(Self {
inner: Some(context::current()?.write().syscall_head.take().ok_or(Error::new(EAGAIN))?),
inner: Some(
context::current()?
.write()
.syscall_head
.take()
.ok_or(Error::new(EAGAIN))?,
),
head_and_not_tail: true,
})
}
pub fn tail() -> Result<Self> {
Ok(Self {
inner: Some(context::current()?.write().syscall_tail.take().ok_or(Error::new(EAGAIN))?),
inner: Some(
context::current()?
.write()
.syscall_tail
.take()
.ok_or(Error::new(EAGAIN))?,
),
head_and_not_tail: false,
})
}
pub fn buf(&self) -> &[u8; PAGE_SIZE] {
unsafe { &*(RmmA::phys_to_virt(self.inner.as_ref().expect("must succeed").get().start_address()).data() as *const [u8; PAGE_SIZE]) }
unsafe {
&*(RmmA::phys_to_virt(
self.inner
.as_ref()
.expect("must succeed")
.get()
.start_address(),
)
.data() as *const [u8; PAGE_SIZE])
}
}
pub fn buf_mut(&mut self) -> &mut [u8; PAGE_SIZE] {
unsafe { &mut *(RmmA::phys_to_virt(self.inner.as_mut().expect("must succeed").get().start_address()).data() as *mut [u8; PAGE_SIZE]) }
unsafe {
&mut *(RmmA::phys_to_virt(
self.inner
.as_mut()
.expect("must succeed")
.get()
.start_address(),
)
.data() as *mut [u8; PAGE_SIZE])
}
}
pub fn frame(&self) -> Frame {
self.inner.as_ref().expect("must succeed").get()
@@ -477,7 +518,12 @@ impl Drop for BorrowedHtBuf {
};
match context.write() {
mut context => {
(if self.head_and_not_tail { &mut context.syscall_head } else { &mut context.syscall_tail }).get_or_insert(inner);
(if self.head_and_not_tail {
&mut context.syscall_head
} else {
&mut context.syscall_tail
})
.get_or_insert(inner);
}
}
}
+7 -4
View File
@@ -1,10 +1,12 @@
//! File structs
use crate::{
event,
scheme::{self, SchemeId, SchemeNamespace},
syscall::error::{Error, Result, EBADF},
};
use alloc::sync::Arc;
use crate::event;
use spin::RwLock;
use crate::scheme::{self, SchemeNamespace, SchemeId};
use crate::syscall::error::{Result, Error, EBADF};
/// A file description
#[derive(Clone, Copy, Debug)]
@@ -36,7 +38,8 @@ impl FileDescription {
event::unregister_file(self.scheme, self.number);
let scheme = scheme::schemes()
.get(self.scheme).ok_or(Error::new(EBADF))?
.get(self.scheme)
.ok_or(Error::new(EBADF))?
.clone();
scheme.close(self.number)
+29 -15
View File
@@ -1,17 +1,16 @@
use alloc::sync::Arc;
use alloc::collections::BTreeMap;
use alloc::{collections::BTreeMap, sync::Arc};
use core::{iter, mem};
use spin::RwLock;
use crate::syscall::error::{Result, Error, EAGAIN};
use super::context::{Context, ContextId};
use crate::syscall::error::{Error, Result, EAGAIN};
/// Context list type
pub struct ContextList {
// Using a BTreeMap for it's range method
map: BTreeMap<ContextId, Arc<RwLock<Context>>>,
next_id: usize
next_id: usize,
}
impl ContextList {
@@ -19,7 +18,7 @@ impl ContextList {
pub const fn new() -> Self {
ContextList {
map: BTreeMap::new(),
next_id: 1
next_id: 1,
}
}
@@ -29,12 +28,18 @@ impl ContextList {
}
/// Get an iterator of all parents
pub fn ancestors(&'_ self, id: ContextId) -> impl Iterator<Item = (ContextId, &Arc<RwLock<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))
})
pub fn ancestors(
&'_ self,
id: ContextId,
) -> impl Iterator<Item = (ContextId, &Arc<RwLock<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.
@@ -46,14 +51,23 @@ impl ContextList {
self.map.iter()
}
pub fn range(&self, range: impl core::ops::RangeBounds<ContextId>) -> ::alloc::collections::btree_map::Range<'_, ContextId, Arc<RwLock<Context>>> {
pub fn range(
&self,
range: impl core::ops::RangeBounds<ContextId>,
) -> ::alloc::collections::btree_map::Range<'_, ContextId, Arc<RwLock<Context>>> {
self.map.range(range)
}
pub(crate) fn insert_context_raw(&mut self, id: ContextId) -> Result<&Arc<RwLock<Context>>> {
assert!(self.map.insert(id, Arc::new(RwLock::new(Context::new(id)?))).is_none());
assert!(self
.map
.insert(id, Arc::new(RwLock::new(Context::new(id)?)))
.is_none());
Ok(self.map.get(&id).expect("Failed to insert new context. ID is out of bounds."))
Ok(self
.map
.get(&id)
.expect("Failed to insert new context. ID is out of bounds."))
}
/// Create a new context.
@@ -84,7 +98,7 @@ impl ContextList {
}
/// Spawn a context from a function.
pub fn spawn(&mut self, func: extern fn()) -> Result<&Arc<RwLock<Context>>> {
pub fn spawn(&mut self, func: extern "C" fn()) -> Result<&Arc<RwLock<Context>>> {
let context_lock = self.new_context()?;
{
let mut context = context_lock.write();
+860 -253
View File
File diff suppressed because it is too large Load Diff
+22 -12
View File
@@ -2,19 +2,22 @@
//!
//! 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;
use alloc::sync::Arc;
use alloc::{borrow::Cow, sync::Arc};
use spin::{RwLock, RwLockReadGuard, RwLockWriteGuard};
use crate::LogicalCpuSet;
use crate::paging::{RmmA, RmmArch, TableKind};
use crate::percpu::PercpuBlock;
use crate::syscall::error::{Error, ESRCH, Result};
use crate::{
paging::{RmmA, RmmArch, TableKind},
percpu::PercpuBlock,
syscall::error::{Error, Result, ESRCH},
LogicalCpuSet,
};
pub use self::context::{BorrowedHtBuf, Context, ContextId, Status, WaitpidKey};
pub use self::list::ContextList;
pub use self::switch::switch;
pub use self::{
context::{BorrowedHtBuf, Context, ContextId, Status, WaitpidKey},
list::ContextList,
switch::switch,
};
#[cfg(target_arch = "aarch64")]
#[path = "arch/aarch64.rs"]
@@ -65,7 +68,9 @@ 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 context_lock = contexts.insert_context_raw(id).expect("could not initialize first context");
let context_lock = contexts
.insert_context_raw(id)
.expect("could not initialize first context");
let mut context = context_lock.write();
context.sched_affinity = LogicalCpuSet::single(crate::cpu_id());
context.name = Cow::Borrowed("kmain");
@@ -77,7 +82,9 @@ pub fn init() {
context.cpu_id = Some(crate::cpu_id());
unsafe {
PercpuBlock::current().switch_internals.set_context_id(context.id);
PercpuBlock::current()
.switch_internals
.set_context_id(context.id);
}
}
@@ -96,5 +103,8 @@ pub fn context_id() -> ContextId {
}
pub fn current() -> Result<Arc<RwLock<Context>>> {
contexts().current().ok_or(Error::new(ESRCH)).map(Arc::clone)
contexts()
.current()
.ok_or(Error::new(ESRCH))
.map(Arc::clone)
}
+53 -25
View File
@@ -1,12 +1,19 @@
use alloc::sync::Arc;
use core::mem;
use syscall::flag::{PTRACE_FLAG_IGNORE, PTRACE_STOP_SIGNAL, SIG_DFL, SIG_IGN, SIGCHLD, SIGCONT, SIGKILL, SIGSTOP, SIGTSTP, SIGTTIN, SIGTTOU};
use syscall::ptrace_event;
use syscall::{
flag::{
PTRACE_FLAG_IGNORE, PTRACE_STOP_SIGNAL, SIGCHLD, SIGCONT, SIGKILL, SIGSTOP, SIGTSTP,
SIGTTIN, SIGTTOU, SIG_DFL, SIG_IGN,
},
ptrace_event,
};
use crate::context::{contexts, switch, Status, WaitpidKey};
use crate::start::usermode;
use crate::ptrace;
use crate::syscall::usercopy::UserSlice;
use crate::{
context::{contexts, switch, Status, WaitpidKey},
ptrace,
start::usermode,
syscall::usercopy::UserSlice,
};
pub fn is_user_handled(handler: Option<extern "C" fn(usize)>) -> bool {
let handler = handler.map(|ptr| ptr as usize).unwrap_or(0);
@@ -16,7 +23,9 @@ pub fn is_user_handled(handler: Option<extern "C" fn(usize)>) -> bool {
pub extern "C" fn signal_handler(sig: usize) {
let ((action, restorer), sigstack) = {
let contexts = contexts();
let context_lock = contexts.current().expect("context::signal_handler not inside of context");
let context_lock = contexts
.current()
.expect("context::signal_handler not inside of context");
let context = context_lock.read();
let actions = context.actions.read();
(actions[sig], context.sigstack)
@@ -24,8 +33,11 @@ pub extern "C" fn signal_handler(sig: usize) {
let handler = action.sa_handler.map(|ptr| ptr as usize).unwrap_or(0);
let thumbs_down = ptrace::breakpoint_callback(PTRACE_STOP_SIGNAL, Some(ptrace_event!(PTRACE_STOP_SIGNAL, sig, handler)))
.and_then(|_| ptrace::next_breakpoint().map(|f| f.contains(PTRACE_FLAG_IGNORE)));
let thumbs_down = ptrace::breakpoint_callback(
PTRACE_STOP_SIGNAL,
Some(ptrace_event!(PTRACE_STOP_SIGNAL, sig, handler)),
)
.and_then(|_| ptrace::next_breakpoint().map(|f| f.contains(PTRACE_FLAG_IGNORE)));
if sig != SIGKILL && thumbs_down.unwrap_or(false) {
// If signal can be and was ignored
@@ -37,7 +49,7 @@ pub extern "C" fn signal_handler(sig: usize) {
match sig {
SIGCHLD => {
// println!("SIGCHLD");
},
}
SIGCONT => {
// println!("Continue");
@@ -45,7 +57,9 @@ pub extern "C" fn signal_handler(sig: usize) {
let contexts = contexts();
let (pid, pgid, ppid) = {
let context_lock = contexts.current().expect("context::signal_handler not inside of context");
let context_lock = contexts
.current()
.expect("context::signal_handler not inside of context");
let mut context = context_lock.write();
context.status = Status::Runnable;
(context.id, context.pgid, context.ppid)
@@ -57,15 +71,18 @@ pub extern "C" fn signal_handler(sig: usize) {
Arc::clone(&parent.waitpid)
};
waitpid.send(WaitpidKey {
pid: Some(pid),
pgid: Some(pgid)
}, (pid, 0xFFFF));
waitpid.send(
WaitpidKey {
pid: Some(pid),
pgid: Some(pgid),
},
(pid, 0xFFFF),
);
} else {
println!("{}: {} not found for continue", pid.get(), ppid.get());
}
}
},
}
SIGSTOP | SIGTSTP | SIGTTIN | SIGTTOU => {
// println!("Stop {}", sig);
@@ -73,7 +90,9 @@ pub extern "C" fn signal_handler(sig: usize) {
let contexts = contexts();
let (pid, pgid, ppid) = {
let context_lock = contexts.current().expect("context::signal_handler not inside of context");
let context_lock = contexts
.current()
.expect("context::signal_handler not inside of context");
let mut context = context_lock.write();
context.status = Status::Stopped(sig);
(context.id, context.pgid, context.ppid)
@@ -85,17 +104,20 @@ pub extern "C" fn signal_handler(sig: usize) {
Arc::clone(&parent.waitpid)
};
waitpid.send(WaitpidKey {
pid: Some(pid),
pgid: Some(pgid)
}, (pid, (sig << 8) | 0x7F));
waitpid.send(
WaitpidKey {
pid: Some(pid),
pgid: Some(pgid),
},
(pid, (sig << 8) | 0x7F),
);
} else {
println!("{}: {} not found for stop", pid.get(), ppid.get());
}
}
unsafe { switch() };
},
}
_ => {
// println!("Exit {}", sig);
crate::syscall::exit(sig);
@@ -108,10 +130,14 @@ pub extern "C" fn signal_handler(sig: usize) {
let singlestep = {
let contexts = contexts();
let context = contexts.current().expect("context::signal_handler userspace not inside of context");
let context = contexts
.current()
.expect("context::signal_handler userspace not inside of context");
let context = context.read();
unsafe {
ptrace::regs_for(&context).map(|s| s.is_singlestep()).unwrap_or(false)
ptrace::regs_for(&context)
.map(|s| s.is_singlestep())
.unwrap_or(false)
}
};
@@ -123,7 +149,9 @@ pub extern "C" fn signal_handler(sig: usize) {
sp -= mem::size_of::<usize>();
match UserSlice::wo(sp, core::mem::size_of::<usize>()).and_then(|buf| buf.write_usize(restorer)) {
match UserSlice::wo(sp, core::mem::size_of::<usize>())
.and_then(|buf| buf.write_usize(restorer))
{
Ok(()) => usermode(handler, sp, sig, usize::from(singlestep)),
Err(error) => {
log::error!("Failed to signal: {}", error);
+47 -28
View File
@@ -1,17 +1,15 @@
use core::cell::Cell;
use core::ops::Bound;
use core::sync::atomic::Ordering;
use core::{cell::Cell, ops::Bound, sync::atomic::Ordering};
use alloc::sync::Arc;
use spin::{RwLock, RwLockWriteGuard};
use crate::context::signal::signal_handler;
use crate::context::{arch, contexts, Context};
use crate::{interrupt, LogicalCpuId};
use crate::percpu::PercpuBlock;
use crate::ptrace;
use crate::time;
use crate::{
context::{arch, contexts, signal::signal_handler, Context},
interrupt,
percpu::PercpuBlock,
ptrace, time, LogicalCpuId,
};
use super::ContextId;
@@ -33,15 +31,24 @@ unsafe fn update_runnable(context: &mut Context, cpu_id: LogicalCpuId) -> bool {
// Restore from signal, must only be done from another context to avoid overwriting the stack!
if context.ksig_restore {
let was_singlestep = ptrace::regs_for(context).map(|s| s.is_singlestep()).unwrap_or(false);
let was_singlestep = ptrace::regs_for(context)
.map(|s| s.is_singlestep())
.unwrap_or(false);
let ksig = context.ksig.take().expect("context::switch: ksig not set with ksig_restore");
let ksig = context
.ksig
.take()
.expect("context::switch: ksig not set with ksig_restore");
context.arch = ksig.0;
context.kfx.copy_from_slice(&*ksig.1);
if let Some(ref mut kstack) = context.kstack {
kstack.copy_from_slice(&ksig.2.expect("context::switch: ksig kstack not set with ksig_restore"));
kstack.copy_from_slice(
&ksig
.2
.expect("context::switch: ksig kstack not set with ksig_restore"),
);
} else {
panic!("context::switch: kstack not set with ksig_restore");
}
@@ -81,7 +88,6 @@ struct SwitchResult {
next_lock: Arc<RwLock<Context>>,
}
pub fn tick() {
let ticks_cell = &PercpuBlock::current().switch_internals.pit_ticks;
@@ -95,7 +101,11 @@ pub fn tick() {
}
pub unsafe extern "C" fn switch_finish_hook() {
if let Some(SwitchResult { prev_lock, next_lock }) = PercpuBlock::current().switch_internals.switch_result.take() {
if let Some(SwitchResult {
prev_lock,
next_lock,
}) = PercpuBlock::current().switch_internals.switch_result.take()
{
prev_lock.force_write_unlock();
next_lock.force_write_unlock();
} else {
@@ -118,7 +128,10 @@ pub unsafe fn switch() -> bool {
// Set the global lock to avoid the unsafe operations below from causing issues
// TODO: Better memory orderings?
while arch::CONTEXT_SWITCH_LOCK.compare_exchange_weak(false, true, Ordering::SeqCst, Ordering::Relaxed).is_err() {
while arch::CONTEXT_SWITCH_LOCK
.compare_exchange_weak(false, true, Ordering::SeqCst, Ordering::Relaxed)
.is_err()
{
interrupt::pause();
}
@@ -130,20 +143,21 @@ pub unsafe fn switch() -> bool {
let contexts = contexts();
// Lock previous context
let prev_context_lock = contexts.current().expect("context::switch: not inside of context");
let prev_context_lock = contexts
.current()
.expect("context::switch: not inside of context");
let prev_context_guard = prev_context_lock.write();
// Locate next context
for (_pid, next_context_lock) in contexts
// Include all contexts with IDs greater than the current...
.range(
(Bound::Excluded(prev_context_guard.id), Bound::Unbounded)
.range((Bound::Excluded(prev_context_guard.id), Bound::Unbounded))
.chain(
contexts
// ... and all contexts with IDs less than the current...
.range((Bound::Unbounded, Bound::Excluded(prev_context_guard.id))),
)
.chain(contexts
// ... and all contexts with IDs less than the current...
.range((Bound::Unbounded, Bound::Excluded(prev_context_guard.id)))
)
// ... but not the current context, which is already locked
// ... but not the current context, which is already locked
{
// Lock next context
let mut next_context_guard = next_context_lock.write();
@@ -165,7 +179,9 @@ pub unsafe fn switch() -> bool {
};
// Switch process states, TSS stack pointer, and store new context ID
if let Some((prev_context_lock, prev_context_ptr, next_context_lock, next_context_ptr)) = switch_context_opt {
if let Some((prev_context_lock, prev_context_ptr, next_context_lock, next_context_ptr)) =
switch_context_opt
{
// Set old context as not running and update CPU time
let prev_context = &mut *prev_context_ptr;
prev_context.running = false;
@@ -198,10 +214,13 @@ pub unsafe fn switch() -> bool {
}
}
percpu.switch_internals.switch_result.set(Some(SwitchResult {
prev_lock: prev_context_lock,
next_lock: next_context_lock,
}));
percpu
.switch_internals
.switch_result
.set(Some(SwitchResult {
prev_lock: prev_context_lock,
next_lock: next_context_lock,
}));
arch::switch_to(prev_context, next_context);
+13 -9
View File
@@ -1,11 +1,15 @@
use alloc::collections::VecDeque;
use spin::{Once, Mutex, MutexGuard};
use spin::{Mutex, MutexGuard, Once};
use crate::event;
use crate::scheme::SchemeId;
use crate::syscall::data::TimeSpec;
use crate::syscall::flag::{CLOCK_MONOTONIC, CLOCK_REALTIME, EVENT_READ};
use crate::time;
use crate::{
event,
scheme::SchemeId,
syscall::{
data::TimeSpec,
flag::{CLOCK_MONOTONIC, CLOCK_REALTIME, EVENT_READ},
},
time,
};
#[derive(Debug)]
struct Timeout {
@@ -35,7 +39,7 @@ pub fn register(scheme_id: SchemeId, event_id: usize, clock: usize, time: TimeSp
scheme_id,
event_id,
clock,
time: (time.tv_sec as u128 * time::NANOS_PER_SEC) + (time.tv_nsec as u128)
time: (time.tv_sec as u128 * time::NANOS_PER_SEC) + (time.tv_nsec as u128),
});
}
@@ -51,11 +55,11 @@ pub fn trigger() {
CLOCK_MONOTONIC => {
let time = registry[i].time;
mono >= time
},
}
CLOCK_REALTIME => {
let time = registry[i].time;
real >= time
},
}
clock => {
println!("timeout::trigger: unknown clock {}", clock);
true