1use super::UPIntrFreeCell;
2use alloc::collections::VecDeque;
3use tg_task_manage::ThreadId;
4
5pub struct Semaphore {
12 pub inner: UPIntrFreeCell<SemaphoreInner>,
14}
15
16pub struct SemaphoreInner {
18 pub count: isize,
19 pub wait_queue: VecDeque<ThreadId>,
20}
21
22impl Semaphore {
23 pub fn new(res_count: usize) -> Self {
25 Self {
26 inner: unsafe {
28 UPIntrFreeCell::new(SemaphoreInner {
29 count: res_count as isize,
30 wait_queue: VecDeque::new(),
31 })
32 },
33 }
34 }
35 pub fn up(&self) -> Option<ThreadId> {
37 let mut inner = self.inner.exclusive_access();
38 inner.count += 1;
39 inner.wait_queue.pop_front()
41 }
42 pub fn down(&self, tid: ThreadId) -> bool {
44 let mut inner = self.inner.exclusive_access();
45 inner.count -= 1;
46 if inner.count < 0 {
47 inner.wait_queue.push_back(tid);
49 drop(inner);
50 false
51 } else {
52 true
53 }
54 }
55}