Skip to main content

tg_sync/
semaphore.rs

1use super::UPIntrFreeCell;
2use alloc::collections::VecDeque;
3use tg_task_manage::ThreadId;
4
5// 教程说明:
6// `count` 含义采用经典信号量语义:
7// - count >= 0:可用资源数;
8// - count < 0:有 `-count` 个线程在等待队列中。
9
10/// Semaphore
11pub struct Semaphore {
12    /// UPIntrFreeCell<SemaphoreInner>
13    pub inner: UPIntrFreeCell<SemaphoreInner>,
14}
15
16/// SemaphoreInner
17pub struct SemaphoreInner {
18    pub count: isize,
19    pub wait_queue: VecDeque<ThreadId>,
20}
21
22impl Semaphore {
23    /// 创建一个新的信号量,初始资源计数为 `res_count`。
24    pub fn new(res_count: usize) -> Self {
25        Self {
26            // SAFETY: 此信号量仅在单处理器内核环境中使用
27            inner: unsafe {
28                UPIntrFreeCell::new(SemaphoreInner {
29                    count: res_count as isize,
30                    wait_queue: VecDeque::new(),
31                })
32            },
33        }
34    }
35    /// 当前线程释放信号量表示的一个资源,并唤醒一个阻塞的线程
36    pub fn up(&self) -> Option<ThreadId> {
37        let mut inner = self.inner.exclusive_access();
38        inner.count += 1;
39        // 若有等待者,交由调度器唤醒队首线程。
40        inner.wait_queue.pop_front()
41    }
42    /// 当前线程试图获取信号量表示的资源,并返回结果
43    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            // 资源不足:当前线程进入等待队列。
48            inner.wait_queue.push_back(tid);
49            drop(inner);
50            false
51        } else {
52            true
53        }
54    }
55}