diff --git a/src/event.rs b/src/event.rs index 28763e6d77..3b3e475db2 100644 --- a/src/event.rs +++ b/src/event.rs @@ -34,8 +34,8 @@ impl EventQueue { } } - pub fn is_currently_empty(&self) -> bool { - self.queue.is_currently_empty() + pub fn is_currently_empty(&self, token: &mut CleanLockToken) -> bool { + self.queue.is_currently_empty(token) } 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 706d8f8c02..c3896d6336 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() { + if flags.contains(EventFlags::EVENT_READ) && !queue.is_currently_empty(token) { // 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 1382d6e171..02a50e4b86 100644 --- a/src/scheme/mod.rs +++ b/src/scheme/mod.rs @@ -312,7 +312,7 @@ impl KernelScheme for SchemeList { token: &mut CleanLockToken, ) -> Result { match self.get_user_inner(id, token) { - Some(inner) => inner.fevent(flags), + Some(inner) => inner.fevent(flags, token), _ => Err(Error::new(EBADF)), } } diff --git a/src/scheme/user.rs b/src/scheme/user.rs index fae4cdaaf9..94012a2ce7 100644 --- a/src/scheme/user.rs +++ b/src/scheme/user.rs @@ -973,10 +973,10 @@ impl UserInner { Ok(()) } - pub fn fevent(&self, flags: EventFlags) -> Result { + pub fn fevent(&self, flags: EventFlags, token: &mut CleanLockToken) -> Result { // TODO: Should the root scheme also suppress events if `flags` does not contain // `EVENT_READ`? - Ok(if self.todo.is_currently_empty() { + Ok(if self.todo.is_currently_empty(token) { EventFlags::empty() } else { EventFlags::EVENT_READ.intersection(flags) diff --git a/src/sync/wait_queue.rs b/src/sync/wait_queue.rs index e7cffa8b0c..52bd81734d 100644 --- a/src/sync/wait_queue.rs +++ b/src/sync/wait_queue.rs @@ -1,9 +1,8 @@ use alloc::collections::VecDeque; -use spin::Mutex; use syscall::{EAGAIN, EINTR}; use crate::{ - sync::{CleanLockToken, LockToken, WaitCondition, L1}, + sync::{CleanLockToken, LockToken, Mutex, WaitCondition, L1}, syscall::{ error::{Error, Result, EINVAL}, usercopy::UserSliceWo, @@ -12,7 +11,7 @@ use crate::{ #[derive(Debug)] pub struct WaitQueue { - pub inner: Mutex>, + inner: Mutex>, pub condition: WaitCondition, } @@ -23,8 +22,8 @@ impl WaitQueue { condition: WaitCondition::new(), } } - pub fn is_currently_empty(&self) -> bool { - self.inner.lock().is_empty() + pub fn is_currently_empty(&self, token: &mut CleanLockToken) -> bool { + self.inner.lock(token.token()).is_empty() } pub fn receive_into_user( &self, @@ -34,8 +33,8 @@ impl WaitQueue { token: &mut CleanLockToken, ) -> Result { loop { - let mut inner = self.inner.lock(); - let mut token = token.downgrade(); + let inner = self.inner.lock(token.token()); + let (mut inner, mut token) = inner.into_split(); if inner.is_empty() { if block { @@ -77,9 +76,9 @@ impl WaitQueue { self.send_locked(value, token.token().downgrade()) } - pub fn send_locked(&self, value: T, token: LockToken<'_, L1>) -> usize { + pub fn send_locked(&self, value: T, mut token: LockToken<'_, L1>) -> usize { let len = { - let mut inner = self.inner.lock(); + let mut inner = self.inner.lock(token.token()); inner.push_back(value); inner.len() };