tg_rcore_tutorial_sync/
mutex.rs1use super::UPIntrFreeCell;
2use alloc::collections::VecDeque;
3use tg_task_manage::ThreadId;
4
5pub trait Mutex: Sync + Send {
7 fn lock(&self, tid: ThreadId) -> bool;
9 fn unlock(&self) -> Option<ThreadId>;
11}
12
13pub struct MutexBlocking {
15 inner: UPIntrFreeCell<MutexBlockingInner>,
16}
17
18pub struct MutexBlockingInner {
20 locked: bool,
21 wait_queue: VecDeque<ThreadId>,
22}
23
24impl MutexBlocking {
25 pub fn new() -> Self {
27 Self {
28 inner: unsafe {
30 UPIntrFreeCell::new(MutexBlockingInner {
31 locked: false,
32 wait_queue: VecDeque::new(),
33 })
34 },
35 }
36 }
37}
38
39impl Mutex for MutexBlocking {
40 fn lock(&self, tid: ThreadId) -> bool {
42 let mut mutex_inner = self.inner.exclusive_access();
43 if mutex_inner.locked {
44 mutex_inner.wait_queue.push_back(tid);
46 drop(mutex_inner);
47 false
48 } else {
49 mutex_inner.locked = true;
51 true
52 }
53 }
54 fn unlock(&self) -> Option<ThreadId> {
56 let mut mutex_inner = self.inner.exclusive_access();
57 assert!(mutex_inner.locked);
58 if let Some(waking_task) = mutex_inner.wait_queue.pop_front() {
59 Some(waking_task)
61 } else {
62 mutex_inner.locked = false;
63 None
64 }
65 }
66}