diff --git a/src/context/signal.rs b/src/context/signal.rs index d9f29d14ae..19f4ebc01f 100644 --- a/src/context/signal.rs +++ b/src/context/signal.rs @@ -78,7 +78,7 @@ pub fn excp_handler(excp: syscall::Exception) { let context = current.write(token.token()); - let Some(_eh) = context.sig.as_ref().and_then(|s| s.excp_handler) else { + let Some(eh) = context.sig.as_ref().and_then(|s| s.excp_handler) else { // TODO: Let procmgr print this? info!( "UNHANDLED EXCEPTION, CPU {}, PID {}, NAME {}, CONTEXT {current:p}", diff --git a/src/event.rs b/src/event.rs index b1db2cff5f..44d61fa27b 100644 --- a/src/event.rs +++ b/src/event.rs @@ -34,8 +34,8 @@ impl EventQueue { } } - pub fn is_currently_empty(&self, token: &mut CleanLockToken) -> bool { - self.queue.is_currently_empty(token) + pub fn is_currently_empty(&self) -> bool { + self.queue.is_currently_empty() } pub fn read(&self, buf: UserSliceWo, block: bool, token: &mut CleanLockToken) -> Result { diff --git a/src/scheme/event.rs b/src/scheme/event.rs index 7f111ec5de..4f4bf763c2 100644 --- a/src/scheme/event.rs +++ b/src/scheme/event.rs @@ -122,7 +122,7 @@ impl KernelScheme for EventScheme { // It is always possible to write events ready |= EventFlags::EVENT_WRITE; } - if flags.contains(EventFlags::EVENT_READ) && !queue.is_currently_empty(token) { + if flags.contains(EventFlags::EVENT_READ) && !queue.is_currently_empty() { // It is possible to read if queue is not empty ready |= EventFlags::EVENT_READ; } diff --git a/src/scheme/mod.rs b/src/scheme/mod.rs index 75f9c0bfca..3c155f97fb 100644 --- a/src/scheme/mod.rs +++ b/src/scheme/mod.rs @@ -312,8 +312,8 @@ impl KernelScheme for SchemeList { token: &mut CleanLockToken, ) -> Result { match self.get_user_inner(id, token) { - Some(inner) => inner.fevent(flags, token), - _ => return Err(Error::new(EBADF)), + Some(inner) => inner.fevent(flags), + _ => Err(Error::new(EBADF)), } } diff --git a/src/scheme/sys/mod.rs b/src/scheme/sys/mod.rs index 8ca47e85f4..32e57a35f5 100644 --- a/src/scheme/sys/mod.rs +++ b/src/scheme/sys/mod.rs @@ -5,7 +5,7 @@ use ::syscall::{ dirent::{DirEntry, DirentBuf, DirentKind}, - EACCES, EINVAL, EIO, EISDIR, ENOTDIR, EPERM, + EACCES, EBADFD, EINVAL, EIO, EISDIR, ENOTDIR, EPERM, }; use alloc::{sync::Arc, vec::Vec}; use core::{ diff --git a/src/scheme/user.rs b/src/scheme/user.rs index ef0804686c..1737964172 100644 --- a/src/scheme/user.rs +++ b/src/scheme/user.rs @@ -965,10 +965,10 @@ impl UserInner { Ok(()) } - pub fn fevent(&self, flags: EventFlags, token: &mut CleanLockToken) -> Result { + pub fn fevent(&self, flags: EventFlags) -> Result { // TODO: Should the root scheme also suppress events if `flags` does not contain // `EVENT_READ`? - Ok(if self.todo.is_currently_empty(token) { + Ok(if self.todo.is_currently_empty() { EventFlags::empty() } else { EventFlags::EVENT_READ.intersection(flags) diff --git a/src/sync/wait_condition.rs b/src/sync/wait_condition.rs index 6c7a59fd51..ce56ca7bb1 100644 --- a/src/sync/wait_condition.rs +++ b/src/sync/wait_condition.rs @@ -7,12 +7,12 @@ use alloc::{ use crate::{ context::{self, ContextLock, PreemptGuard}, - sync::{CleanLockToken, LockToken, Lower, Mutex, L1, L2, L3}, + sync::{CleanLockToken, Mutex, L1}, }; #[derive(Debug)] pub struct WaitCondition { - contexts: Mutex>>, + contexts: Mutex>>, } impl WaitCondition { @@ -48,8 +48,7 @@ impl WaitCondition { len } - /// Wait until notified. Unlocks guard when blocking is ready. Returns false if resumed by a signal or the notify_signal function. - /// Wrapper to wait_setup -> drop(guard) -> context::switch -> wait_cleanup without currently holding lock for guard. + // Wait until notified. Unlocks guard when blocking is ready. Returns false if resumed by a signal or the notify_signal function pub fn wait(&self, guard: T, reason: &'static str, token: &mut CleanLockToken) -> bool { let current_context_ref = context::current(); { @@ -59,68 +58,36 @@ impl WaitCondition { // to deadlock if we were woken up immediately. let mut preempt = PreemptGuard::new(¤t_context_ref, token); let token = preempt.token(); - if !self.wait_setup(¤t_context_ref, reason, token.token()) { - return false; + { + let mut context = current_context_ref.write(token.token()); + if let Some((control, pctl, _)) = context.sigcontrol() + && control.currently_pending_unblocked(pctl) != 0 + { + return false; + } + context.block(reason); } + self.contexts + .lock(token.token()) + .push(Arc::downgrade(¤t_context_ref)); + drop(guard); } context::switch(token); - self.wait_cleanup(¤t_context_ref, token.token()) - } - - /// Enqueues the context and sets it to blocked. - /// Returns true if successfully blocked, false if a signal is pending. - pub fn wait_setup<'a, LP>( - &self, - current_context_ref: &Arc, - reason: &'static str, - mut lock_token: LockToken<'a, LP>, - ) -> bool - where - LP: Lower, - { - { - let mut context = current_context_ref.write(LockToken::downgraded(lock_token.token())); - if let Some((control, pctl, _)) = context.sigcontrol() - && control.currently_pending_unblocked(pctl) != 0 - { - return false; - } - context.block(reason); - } - - self.contexts - .lock(LockToken::downgraded(lock_token)) - .push(Arc::downgrade(current_context_ref)); - - true - } - - /// Cleans up the wait list after waking up. - /// Returns true if we actually waited, false if we were removed by signal/notify_signal. - pub fn wait_cleanup<'a, LP>( - &self, - current_context_ref: &Arc, - lock_token: LockToken<'a, LP>, - ) -> bool - where - LP: Lower, - { let mut waited = true; - let mut contexts = self.contexts.lock(LockToken::downgraded(lock_token)); - // TODO: retain - let mut i = 0; - while i < contexts.len() { - if Weak::as_ptr(&contexts[i]) == Arc::as_ptr(current_context_ref) { - contexts.remove(i); + { + let mut contexts = self.contexts.lock(token.token()); + + if let Some(index) = contexts + .iter() + .position(|c| Weak::as_ptr(c) == Arc::as_ptr(¤t_context_ref)) + { + contexts.remove(index); waited = false; - break; - } else { - i += 1; } } diff --git a/src/sync/wait_queue.rs b/src/sync/wait_queue.rs index fd2fbf809a..a997109111 100644 --- a/src/sync/wait_queue.rs +++ b/src/sync/wait_queue.rs @@ -1,9 +1,9 @@ use alloc::collections::VecDeque; +use spin::Mutex; use syscall::{EAGAIN, EINTR}; use crate::{ - context::{self, PreemptGuard}, - sync::{CleanLockToken, Mutex, WaitCondition, L1}, + sync::{CleanLockToken, WaitCondition}, syscall::{ error::{Error, Result, EINVAL}, usercopy::UserSliceWo, @@ -12,7 +12,7 @@ use crate::{ #[derive(Debug)] pub struct WaitQueue { - inner: Mutex>, + pub inner: Mutex>, pub condition: WaitCondition, } @@ -23,8 +23,8 @@ impl WaitQueue { condition: WaitCondition::new(), } } - pub fn is_currently_empty(&self, token: &mut CleanLockToken) -> bool { - self.inner.lock(token.token()).is_empty() + pub fn is_currently_empty(&self) -> bool { + self.inner.lock().is_empty() } pub fn receive_into_user( &self, @@ -33,31 +33,14 @@ impl WaitQueue { reason: &'static str, token: &mut CleanLockToken, ) -> Result { - let current_context_ref = context::current(); - loop { - let mut preempt = PreemptGuard::new(¤t_context_ref, token); - - let mut inner = self.inner.lock(preempt.token().token()); + let mut inner = self.inner.lock(); if inner.is_empty() { if block { - let (_, mut inner_token) = inner.token_split(); - if !self - .condition - .wait_setup(¤t_context_ref, reason, inner_token.token()) - { + if !self.condition.wait(inner, reason, token) { return Err(Error::new(EINTR)); } - - drop(inner); - drop(preempt); - - context::switch(token); - - self.condition - .wait_cleanup(¤t_context_ref, token.token()); - continue; } else if buf.is_empty() { return Ok(0); @@ -91,7 +74,7 @@ impl WaitQueue { pub fn send(&self, value: T, token: &mut CleanLockToken) -> usize { let len = { - let mut inner = self.inner.lock(token.token()); + let mut inner = self.inner.lock(); inner.push_back(value); inner.len() };