diff --git a/src/context/context.rs b/src/context/context.rs index ee24e14724..342ddc8e08 100644 --- a/src/context/context.rs +++ b/src/context/context.rs @@ -71,6 +71,14 @@ pub enum HardBlockedReason { const CONTEXT_NAME_CAPAC: usize = 32; +#[derive(Debug)] +pub enum SyscallFrame { + Free(RaiiFrame), + // The field is used by the consistency checker of the kernel debugger + Used { _frame: Frame }, + Dummy, +} + /// A context, which is typically mapped to a userspace thread #[derive(Debug)] pub struct Context { @@ -100,10 +108,10 @@ pub struct Context { /// Head buffer to use when system call buffers are not page aligned // TODO: Store in user memory? - pub syscall_head: Option, + pub syscall_head: SyscallFrame, /// Tail buffer to use when system call buffers are not page aligned // TODO: Store in user memory? - pub syscall_tail: Option, + pub syscall_tail: SyscallFrame, /// Context should wake up at specified time pub wake: Option, /// The architecture specific context @@ -168,8 +176,8 @@ impl Context { cpu_time: 0, sched_affinity: LogicalCpuSet::all(), inside_syscall: false, - syscall_head: Some(RaiiFrame::allocate()?), - syscall_tail: Some(RaiiFrame::allocate()?), + syscall_head: SyscallFrame::Free(RaiiFrame::allocate()?), + syscall_tail: SyscallFrame::Free(RaiiFrame::allocate()?), wake: None, arch: arch::Context::new(), kfx: AlignedBox::<[u8], { arch::KFX_ALIGN }>::try_zeroed_slice(crate::arch::kfx_size())?, @@ -430,28 +438,36 @@ pub struct BorrowedHtBuf { } impl BorrowedHtBuf { pub fn head(token: &mut CleanLockToken) -> Result { - Ok(Self { - inner: Some( - context::current() - .write(token.token()) - .syscall_head - .take() - .ok_or(Error::new(EAGAIN))?, - ), - head_and_not_tail: true, - }) + let current = context::current(); + let frame = &mut current.write(token.token()).syscall_head; + match mem::replace(frame, SyscallFrame::Dummy) { + SyscallFrame::Free(free_frame) => { + *frame = SyscallFrame::Used { + _frame: free_frame.get(), + }; + Ok(Self { + inner: Some(free_frame), + head_and_not_tail: true, + }) + } + SyscallFrame::Used { .. } | SyscallFrame::Dummy => Err(Error::new(EAGAIN)), + } } pub fn tail(token: &mut CleanLockToken) -> Result { - Ok(Self { - inner: Some( - context::current() - .write(token.token()) - .syscall_tail - .take() - .ok_or(Error::new(EAGAIN))?, - ), - head_and_not_tail: false, - }) + let current = context::current(); + let frame = &mut current.write(token.token()).syscall_tail; + match mem::replace(frame, SyscallFrame::Dummy) { + SyscallFrame::Free(free_frame) => { + *frame = SyscallFrame::Used { + _frame: free_frame.get(), + }; + Ok(Self { + inner: Some(free_frame), + head_and_not_tail: false, + }) + } + SyscallFrame::Used { .. } | SyscallFrame::Dummy => Err(Error::new(EAGAIN)), + } } pub fn buf(&self) -> &[u8; PAGE_SIZE] { unsafe { @@ -500,12 +516,11 @@ impl Drop for BorrowedHtBuf { let mut token = unsafe { CleanLockToken::new() }; match context.write(token.token()) { mut context => { - (if self.head_and_not_tail { + *(if self.head_and_not_tail { &mut context.syscall_head } else { &mut context.syscall_tail - }) - .get_or_insert(inner); + }) = SyscallFrame::Free(inner); } } } diff --git a/src/debugger.rs b/src/debugger.rs index 787a97161f..7e7e92b8d9 100644 --- a/src/debugger.rs +++ b/src/debugger.rs @@ -1,5 +1,5 @@ use crate::{ - context::{Context, ContextLock}, + context::{context::SyscallFrame, Context, ContextLock}, memory::{get_page_info, the_zeroed_frame, Frame, RefCount}, paging::{RmmA, RmmArch, TableKind, PAGE_SIZE}, sync::CleanLockToken, @@ -15,8 +15,6 @@ pub unsafe fn debugger(target_id: Option<*const ContextLock>, token: &mut CleanL let mut tree = HashMap::new(); let mut spaces = HashSet::new(); - let mut temporarily_taken_htbufs = 0; - tree.insert(the_zeroed_frame().0, (1, false)); let old_table = unsafe { RmmA::table(TableKind::User) }; @@ -30,15 +28,23 @@ pub unsafe fn debugger(target_id: Option<*const ContextLock>, token: &mut CleanL let context = context_lock.0.read(context_token.token()); println!("{:p}: {}", Arc::as_ptr(&context_lock.0), context.name); - if let Some(ref head) = context.syscall_head { - tree.insert(head.get(), (1, false)); - } else { - temporarily_taken_htbufs += 1; + match &context.syscall_head { + SyscallFrame::Free(head) => { + tree.insert(head.get(), (1, false)); + } + SyscallFrame::Used { _frame: head } => { + tree.insert(*head, (1, false)); + } + SyscallFrame::Dummy => {} } - if let Some(ref tail) = context.syscall_tail { - tree.insert(tail.get(), (1, false)); - } else { - temporarily_taken_htbufs += 1; + match &context.syscall_tail { + SyscallFrame::Free(tail) => { + tree.insert(tail.get(), (1, false)); + } + SyscallFrame::Used { _frame: tail } => { + tree.insert(*tail, (1, false)); + } + SyscallFrame::Dummy => {} } // Switch to context page table to ensure syscall debug and stack dump will work @@ -156,10 +162,6 @@ pub unsafe fn debugger(target_id: Option<*const ContextLock>, token: &mut CleanL ); } } - println!( - "({} kernel-owned references were not counted)", - temporarily_taken_htbufs - ); println!("DEBUGGER END"); } diff --git a/src/syscall/process.rs b/src/syscall/process.rs index bbcec2e33e..7775f3276b 100644 --- a/src/syscall/process.rs +++ b/src/syscall/process.rs @@ -6,6 +6,7 @@ use spin::RwLock; use crate::{ context::{ + context::SyscallFrame, memory::{AddrSpace, Grant, PageSpan}, ContextRef, }, @@ -37,8 +38,8 @@ pub fn exit_this_context(excp: Option, token: &mut CleanLock addrspace_opt = context .set_addr_space(None) .and_then(|a| Arc::try_unwrap(a).ok()); - drop(context.syscall_head.take()); - drop(context.syscall_tail.take()); + drop(mem::replace(&mut context.syscall_head, SyscallFrame::Dummy)); + drop(mem::replace(&mut context.syscall_tail, SyscallFrame::Dummy)); } // Files must be closed while context is valid so that messages can be passed