1 use core::sync::atomic::{AtomicI32, Ordering};
2 
3 use crate::{arch::asm::current::current_pcb, kdebug, syscall::SystemError};
4 
5 use super::wait_queue::WaitQueue;
6 
7 /// @brief 信号量的结构体
8 #[derive(Debug)]
9 struct Semaphore {
10     counter: AtomicI32,
11     wait_queue: WaitQueue,
12 }
13 
14 impl Semaphore {
15     #[allow(dead_code)]
16     #[inline]
17     /// @brief 初始化信号量
18     ///
19     /// @param count 信号量的初始值
20     /// @return 条件满足返回semaphore对象,条件不满足返回err信息
new(counter: i32) -> Result<Self, SystemError>21     fn new(counter: i32) -> Result<Self, SystemError> {
22         if counter > 0 {
23             Ok(Self {
24                 counter: AtomicI32::new(counter),
25                 wait_queue: WaitQueue::INIT,
26             })
27         } else {
28             return Err(SystemError::EOVERFLOW);
29         }
30     }
31 
32     #[allow(dead_code)]
33     #[inline]
down(&self)34     fn down(&self) {
35         if self.counter.fetch_sub(1, Ordering::Release) <= 0 {
36             self.counter.fetch_add(1, Ordering::Relaxed);
37             self.wait_queue.sleep();
38             //资源不充足,信号量<=0, 此时进程睡眠
39         }
40     }
41 
42     #[allow(dead_code)]
43     #[inline]
up(&self)44     fn up(&self) {
45         // 判断有没有进程在等待资源
46         if self.wait_queue.len() > 0 {
47             self.counter.fetch_add(1, Ordering::Release);
48         } else {
49             //尝试唤醒
50             if !self.wait_queue.wakeup(0x_ffff_ffff_ffff_ffff) {
51                 //如果唤醒失败,打印错误信息
52                 kdebug!(
53                     "Semaphore wakeup failed: current pid= {}, semaphore={:?}",
54                     current_pcb().pid,
55                     self
56                 );
57             }
58         }
59     }
60 }
61