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