1use crate::sync::{Mutex, UPSafeCell};
2use crate::task::{TaskControlBlock, block_current_and_run_next, current_task, wakeup_task};
3use alloc::{collections::VecDeque, sync::Arc};
4
5pub struct Condvar {
6 pub inner: UPSafeCell<CondvarInner>,
7}
8
9pub struct CondvarInner {
10 pub wait_queue: VecDeque<Arc<TaskControlBlock>>,
11}
12
13impl Condvar {
14 pub fn new() -> Self {
15 Self {
16 inner: unsafe {
17 UPSafeCell::new(CondvarInner {
18 wait_queue: VecDeque::new(),
19 })
20 },
21 }
22 }
23
24 pub fn signal(&self) {
25 let mut inner = self.inner.exclusive_access();
26 if let Some(task) = inner.wait_queue.pop_front() {
27 wakeup_task(task);
28 }
29 }
30
31 pub fn wait(&self, mutex: Arc<dyn Mutex>) {
32 mutex.unlock();
33 let mut inner = self.inner.exclusive_access();
34 inner.wait_queue.push_back(current_task().unwrap());
35 drop(inner);
36 block_current_and_run_next();
37 mutex.lock();
38 }
39}