1use super::UPIntrFreeCell;
2use alloc::collections::VecDeque;
3use tg_task_manage::ThreadId;
4
5pub struct Semaphore {
7 pub inner: UPIntrFreeCell<SemaphoreInner>,
9}
10
11pub struct SemaphoreInner {
13 pub count: isize,
14 pub wait_queue: VecDeque<ThreadId>,
15}
16
17impl Semaphore {
18 pub fn new(res_count: usize) -> Self {
20 Self {
21 inner: unsafe {
23 UPIntrFreeCell::new(SemaphoreInner {
24 count: res_count as isize,
25 wait_queue: VecDeque::new(),
26 })
27 },
28 }
29 }
30 pub fn up(&self) -> Option<ThreadId> {
32 let mut inner = self.inner.exclusive_access();
33 inner.count += 1;
34 inner.wait_queue.pop_front()
35 }
36 pub fn down(&self, tid: ThreadId) -> bool {
38 let mut inner = self.inner.exclusive_access();
39 inner.count -= 1;
40 if inner.count < 0 {
41 inner.wait_queue.push_back(tid);
42 drop(inner);
43 false
44 } else {
45 true
46 }
47 }
48}