diff --git a/src/context/context.rs b/src/context/context.rs index 958f5fefd4..4a44d392e8 100644 --- a/src/context/context.rs +++ b/src/context/context.rs @@ -453,12 +453,11 @@ impl Context { let kstack = self.kstack.as_ref()?; Some(unsafe { &mut *kstack.initial_top().sub(size_of::()).cast() }) } - pub fn sigcontrol(&mut self) -> Option<(&Sigcontrol, &SigProcControl, &mut SignalState)> { - Some(Self::sigcontrol_raw(self.sig.as_mut()?)) + pub fn sigcontrol(&self) -> Option<(&Sigcontrol, &SigProcControl, &SignalState)> { + let (for_thread, for_proc) = Self::sigcontrol_raw(self.sig.as_ref()?); + Some((for_thread, for_proc, self.sig.as_ref()?)) } - pub fn sigcontrol_raw( - sig: &mut SignalState, - ) -> (&Sigcontrol, &SigProcControl, &mut SignalState) { + pub fn sigcontrol_raw(sig: &SignalState) -> (&Sigcontrol, &SigProcControl) { let check = |off| { assert_eq!(usize::from(off) % align_of::(), 0); assert!(usize::from(off).saturating_add(size_of::()) < PAGE_SIZE); @@ -475,7 +474,7 @@ impl Context { .byte_add(usize::from(sig.procctl_off)) }; - (for_thread, for_proc, sig) + (for_thread, for_proc) } pub fn caller_ctx(&self) -> CallerCtx { CallerCtx { diff --git a/src/context/signal.rs b/src/context/signal.rs index 19f4ebc01f..99aab364b1 100644 --- a/src/context/signal.rs +++ b/src/context/signal.rs @@ -4,13 +4,12 @@ use crate::{context, sync::CleanLockToken, syscall::flag::SigcontrolFlags}; pub fn signal_handler(token: &mut CleanLockToken) { let context_lock = context::current(); - let mut context_guard = context_lock.write(token.token()); - let context = &mut *context_guard; + let context = context_lock.upgradeable_read(token.token()); let being_sigkilled = context.being_sigkilled; if being_sigkilled { - drop(context_guard); + drop(context); drop(context_lock); crate::syscall::process::exit_this_context(None, token); } @@ -48,6 +47,7 @@ pub fn signal_handler(token: &mut CleanLockToken) { let sigh_instr_ptr = st.user_handler.get(); + let mut context = context.upgrade(); let Some(regs) = context.regs_mut() else { // TODO: is this even reachable? trace!("No registers, returning"); @@ -59,6 +59,7 @@ pub fn signal_handler(token: &mut CleanLockToken) { regs.set_instr_pointer(sigh_instr_ptr); + let mut context = context.downgrade(); let (thread_ctl, _, _) = context .sigcontrol() .expect("cannot have been unset while holding the lock"); diff --git a/src/scheme/acpi.rs b/src/scheme/acpi.rs index ab2c333440..6b941625c9 100644 --- a/src/scheme/acpi.rs +++ b/src/scheme/acpi.rs @@ -181,7 +181,7 @@ impl KernelScheme for AcpiScheme { Ok(OpenResult::SchemeLocal(fd, int_flags)) } fn fsize(&self, id: usize, token: &mut CleanLockToken) -> Result { - let mut handles = HANDLES.read(token.token()); + let handles = HANDLES.read(token.token()); let handle = handles.get(id)?; if handle.stat { diff --git a/src/scheme/proc.rs b/src/scheme/proc.rs index d45c8d2144..6e739e1882 100644 --- a/src/scheme/proc.rs +++ b/src/scheme/proc.rs @@ -633,7 +633,7 @@ impl KernelScheme for ProcScheme { ) -> Result { // TODO: simplify let handle = { - let mut handles = HANDLES.read(token.token()); + let handles = HANDLES.read(token.token()); let handle = handles.get(&id).ok_or(Error::new(EBADF))?; handle.clone() }; @@ -667,7 +667,7 @@ impl KernelScheme for ProcScheme { // Don't hold a global lock during the context switch later on let handle = { - let mut handles = HANDLES.read(token.token()); + let handles = HANDLES.read(token.token()); let handle = handles.get(&id).ok_or(Error::new(EBADF))?; handle.clone() }; @@ -696,7 +696,7 @@ impl KernelScheme for ProcScheme { } fn fsize(&self, id: usize, token: &mut CleanLockToken) -> Result { - let mut handles = HANDLES.read(token.token()); + let handles = HANDLES.read(token.token()); let handle = handles.get(&id).ok_or(Error::new(EBADF))?; handle.fsize() diff --git a/src/sync/ordered.rs b/src/sync/ordered.rs index 91d46158db..9b2c024ad4 100644 --- a/src/sync/ordered.rs +++ b/src/sync/ordered.rs @@ -620,6 +620,14 @@ impl<'a, L: Level, T> RwLockWriteGuard<'a, L, T> { drop(self.inner); self.lock_token } + + /// Upgrade to RO lock + pub fn downgrade(self) -> RwLockReadGuard<'a, L, T> { + RwLockReadGuard { + inner: self.inner.downgrade(), + lock_token: self.lock_token, + } + } } impl core::ops::Deref for RwLockWriteGuard<'_, L, T> { diff --git a/src/sync/wait_condition.rs b/src/sync/wait_condition.rs index c508eb64fe..d31c4e0744 100644 --- a/src/sync/wait_condition.rs +++ b/src/sync/wait_condition.rs @@ -80,13 +80,13 @@ impl WaitCondition { let mut preempt = PreemptGuardL2::new(¤t_context_ref, &mut token); let token = preempt.token(); { - let mut context = current_context_ref.write(token.token()); + let context = current_context_ref.upgradeable_read(token.token()); if let Some((control, pctl, _)) = context.sigcontrol() && control.currently_pending_unblocked(pctl) != 0 { return false; } - context.block(reason); + context.upgrade().block(reason); } self.contexts diff --git a/src/syscall/time.rs b/src/syscall/time.rs index aa6763f5b0..e9f4c2e3ed 100644 --- a/src/syscall/time.rs +++ b/src/syscall/time.rs @@ -41,14 +41,14 @@ pub fn nanosleep( let current_context = context::current(); { - let mut context = current_context.write(token.token()); + let context = current_context.upgradeable_read(token.token()); if let Some((tctl, pctl, _)) = context.sigcontrol() && tctl.currently_pending_unblocked(pctl) != 0 { return Err(Error::new(EINTR)); } - + let mut context = context.upgrade(); context.wake = Some(end); context.block("nanosleep"); }