os/sync/
condvar.rs

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}