Skip to main content

os/sync/
condvar.rs

1use crate::sync::{Mutex, UPIntrFreeCell};
2use crate::task::{
3    TaskContext, TaskControlBlock, block_current_and_run_next, block_current_task, current_task,
4    wakeup_task,
5};
6use alloc::{collections::VecDeque, sync::Arc};
7
8pub struct Condvar {
9    pub inner: UPIntrFreeCell<CondvarInner>,
10}
11
12pub struct CondvarInner {
13    pub wait_queue: VecDeque<Arc<TaskControlBlock>>,
14}
15
16impl Condvar {
17    pub fn new() -> Self {
18        Self {
19            inner: unsafe {
20                UPIntrFreeCell::new(CondvarInner {
21                    wait_queue: VecDeque::new(),
22                })
23            },
24        }
25    }
26
27    pub fn signal(&self) {
28        let mut inner = self.inner.exclusive_access();
29        if let Some(task) = inner.wait_queue.pop_front() {
30            wakeup_task(task);
31        }
32    }
33
34    /*
35    pub fn wait(&self) {
36        let mut inner = self.inner.exclusive_access();
37        inner.wait_queue.push_back(current_task().unwrap());
38        drop(inner);
39        block_current_and_run_next();
40    }
41    */
42
43    pub fn wait_no_sched(&self) -> *mut TaskContext {
44        self.inner.exclusive_session(|inner| {
45            inner.wait_queue.push_back(current_task().unwrap());
46        });
47        block_current_task()
48    }
49
50    pub fn wait_with_mutex(&self, mutex: Arc<dyn Mutex>) {
51        mutex.unlock();
52        self.inner.exclusive_session(|inner| {
53            inner.wait_queue.push_back(current_task().unwrap());
54        });
55        block_current_and_run_next();
56        mutex.lock();
57    }
58}