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 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}