tg_sync/
semaphore.rs

1use super::UPIntrFreeCell;
2use alloc::collections::VecDeque;
3use tg_task_manage::ThreadId;
4
5/// Semaphore
6pub struct Semaphore {
7    /// UPIntrFreeCell<SemaphoreInner>
8    pub inner: UPIntrFreeCell<SemaphoreInner>,
9}
10
11/// SemaphoreInner
12pub struct SemaphoreInner {
13    pub count: isize,
14    pub wait_queue: VecDeque<ThreadId>,
15}
16
17impl Semaphore {
18    /// 创建一个新的信号量,初始资源计数为 `res_count`。
19    pub fn new(res_count: usize) -> Self {
20        Self {
21            // SAFETY: 此信号量仅在单处理器内核环境中使用
22            inner: unsafe {
23                UPIntrFreeCell::new(SemaphoreInner {
24                    count: res_count as isize,
25                    wait_queue: VecDeque::new(),
26                })
27            },
28        }
29    }
30    /// 当前线程释放信号量表示的一个资源,并唤醒一个阻塞的线程
31    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    /// 当前线程试图获取信号量表示的资源,并返回结果
37    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}