|
|
|
@ -1,4 +1,6 @@
|
|
|
|
|
use super::*;
|
|
|
|
|
use crate::arch::cpu;
|
|
|
|
|
use crate::process::processor;
|
|
|
|
|
use crate::thread;
|
|
|
|
|
use alloc::collections::VecDeque;
|
|
|
|
|
use alloc::sync::Arc;
|
|
|
|
@ -26,26 +28,44 @@ impl Condvar {
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[deprecated(note = "this may leads to lost wakeup problem. please use `wait` instead.")]
|
|
|
|
|
pub fn wait_any(condvars: &[&Condvar]) {
|
|
|
|
|
let token = Arc::new(thread::current());
|
|
|
|
|
// Avoid racing in the same way as the function above
|
|
|
|
|
let mut locks = Vec::new();
|
|
|
|
|
locks.reserve(condvars.len());
|
|
|
|
|
fn add_to_wait_queue(&self) -> MutexGuard<VecDeque<Arc<thread::Thread>>, SpinNoIrq> {
|
|
|
|
|
let mut lock = self.wait_queue.lock();
|
|
|
|
|
lock.push_back(Arc::new(thread::current()));
|
|
|
|
|
return lock;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn wait_event<T>(condvar: &Condvar, mut condition: impl FnMut() -> Option<T>) -> T {
|
|
|
|
|
Self::wait_events(&[condvar], condition)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn wait_events<T>(condvars: &[&Condvar], mut condition: impl FnMut() -> Option<T>) -> T {
|
|
|
|
|
let thread = thread::current();
|
|
|
|
|
let tid = thread.id();
|
|
|
|
|
let token = Arc::new(thread);
|
|
|
|
|
for condvar in condvars {
|
|
|
|
|
let mut lock = condvar.wait_queue.lock();
|
|
|
|
|
lock.push_back(token.clone());
|
|
|
|
|
locks.push(lock);
|
|
|
|
|
}
|
|
|
|
|
thread::park_action(move || {
|
|
|
|
|
drop(locks);
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
let mut locks = Vec::with_capacity(condvars.len());
|
|
|
|
|
loop {
|
|
|
|
|
for condvar in condvars {
|
|
|
|
|
let mut lock = condvar.wait_queue.lock();
|
|
|
|
|
locks.push(lock);
|
|
|
|
|
}
|
|
|
|
|
processor().manager().sleep(tid, 0);
|
|
|
|
|
locks.clear();
|
|
|
|
|
|
|
|
|
|
fn add_to_wait_queue(&self) -> MutexGuard<VecDeque<Arc<thread::Thread>>, SpinNoIrq> {
|
|
|
|
|
let mut lock = self.wait_queue.lock();
|
|
|
|
|
lock.push_back(Arc::new(thread::current()));
|
|
|
|
|
return lock;
|
|
|
|
|
if let Some(res) = condition() {
|
|
|
|
|
let _ = FlagsGuard::no_irq_region();
|
|
|
|
|
processor().manager().cancel_sleeping(tid);
|
|
|
|
|
for condvar in condvars {
|
|
|
|
|
let mut lock = condvar.wait_queue.lock();
|
|
|
|
|
lock.retain(|t| !Arc::ptr_eq(t, &token));
|
|
|
|
|
}
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
processor().yield_now();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Park current thread and wait for this condvar to be notified.
|
|
|
|
@ -54,21 +74,28 @@ impl Condvar {
|
|
|
|
|
S: MutexSupport,
|
|
|
|
|
{
|
|
|
|
|
let mutex = guard.mutex;
|
|
|
|
|
let lock = self.add_to_wait_queue();
|
|
|
|
|
let token = Arc::new(thread::current());
|
|
|
|
|
let mut lock = self.wait_queue.lock();
|
|
|
|
|
lock.push_back(token.clone());
|
|
|
|
|
|
|
|
|
|
thread::park_action(move || {
|
|
|
|
|
drop(lock);
|
|
|
|
|
drop(guard);
|
|
|
|
|
});
|
|
|
|
|
mutex.lock()
|
|
|
|
|
let ret = mutex.lock();
|
|
|
|
|
let mut lock = self.wait_queue.lock();
|
|
|
|
|
lock.retain(|t| !Arc::ptr_eq(&t, &token));
|
|
|
|
|
ret
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn notify_one(&self) {
|
|
|
|
|
if let Some(t) = self.wait_queue.lock().pop_front() {
|
|
|
|
|
if let Some(t) = self.wait_queue.lock().front() {
|
|
|
|
|
t.unpark();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
pub fn notify_all(&self) {
|
|
|
|
|
while let Some(t) = self.wait_queue.lock().pop_front() {
|
|
|
|
|
let queue = self.wait_queue.lock();
|
|
|
|
|
for t in queue.iter() {
|
|
|
|
|
t.unpark();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -76,14 +103,15 @@ impl Condvar {
|
|
|
|
|
/// Return the number of waiters that were woken up.
|
|
|
|
|
pub fn notify_n(&self, n: usize) -> usize {
|
|
|
|
|
let mut count = 0;
|
|
|
|
|
while count < n {
|
|
|
|
|
if let Some(t) = self.wait_queue.lock().pop_front() {
|
|
|
|
|
t.unpark();
|
|
|
|
|
count += 1;
|
|
|
|
|
} else {
|
|
|
|
|
let queue = self.wait_queue.lock();
|
|
|
|
|
for t in queue.iter() {
|
|
|
|
|
if (count >= n) {
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
t.unpark();
|
|
|
|
|
count += 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
count
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|