Add MutexBlocking.

This commit is contained in:
Yifan Wu 2021-10-07 14:33:44 -07:00
parent 8974a29245
commit db6a93e60d
11 changed files with 119 additions and 13 deletions

View file

@ -2,4 +2,4 @@ mod up;
mod mutex;
pub use up::UPSafeCell;
pub use mutex::{Mutex, MutexSpin};
pub use mutex::{Mutex, MutexSpin, MutexBlocking};

View file

@ -1,5 +1,8 @@
use super::UPSafeCell;
use crate::task::suspend_current_and_run_next;
use crate::task::{block_current_and_run_next, suspend_current_and_run_next};
use crate::task::TaskControlBlock;
use crate::task::{add_task, current_task};
use alloc::{sync::Arc, collections::VecDeque};
pub trait Mutex: Sync + Send {
fn lock(&self);
@ -38,3 +41,47 @@ impl Mutex for MutexSpin {
*locked = false;
}
}
pub struct MutexBlocking {
inner: UPSafeCell<MutexBlockingInner>,
}
pub struct MutexBlockingInner {
locked: bool,
wait_queue: VecDeque<Arc<TaskControlBlock>>,
}
impl MutexBlocking {
pub fn new() -> Self {
Self {
inner: unsafe {
UPSafeCell::new(MutexBlockingInner {
locked: false,
wait_queue: VecDeque::new(),
})
},
}
}
}
impl Mutex for MutexBlocking {
fn lock(&self) {
let mut mutex_inner = self.inner.exclusive_access();
if mutex_inner.locked {
mutex_inner.wait_queue.push_back(current_task().unwrap());
drop(mutex_inner);
block_current_and_run_next();
} else {
mutex_inner.locked = true;
}
}
fn unlock(&self) {
let mut mutex_inner = self.inner.exclusive_access();
assert_eq!(mutex_inner.locked, true);
mutex_inner.locked = false;
if let Some(waking_task) = mutex_inner.wait_queue.pop_front() {
add_task(waking_task);
}
}
}