xref: /DragonOS/kernel/src/libs/notifier.rs (revision abe3a6ea3c543425e2cad12722e8a658b324d515)
1 #![allow(dead_code)]
2 use crate::{
3     kwarn,
4     libs::{rwlock::RwLock, spinlock::SpinLock},
5     syscall::SystemError,
6 };
7 use alloc::{sync::Arc, vec::Vec};
8 
9 /// @brief 通知链节点
10 pub trait NotifierBlock<T> {
11     /// @brief 通知链中注册的回调函数类型
12     fn notifier_call(&self, action: u64, data: Option<&T>) -> i32;
13     /// @brief 通知链节点的优先级
14     fn priority(&self) -> i32;
15 }
16 
17 /// @brief 通知链
18 // TODO: 考虑使用红黑树封装
19 struct NotifierChain<T>(Vec<Arc<dyn NotifierBlock<T>>>);
20 
21 impl<T> NotifierChain<T> {
22     pub fn new() -> Self {
23         Self(vec![])
24     }
25 
26     /// @brief 将节点注册到通知链
27     /// @param unique_priority 检查通知链中优先级的唯一性
28     pub fn register(
29         &mut self,
30         block: Arc<dyn NotifierBlock<T>>,
31         unique_priority: bool,
32     ) -> Result<(), SystemError> {
33         let mut index: usize = 0;
34 
35         // 在 notifier chain中寻找第一个优先级比要插入块低的块
36         for b in self.0.iter() {
37             // 判断之前是否已经注册过该节点
38             if Arc::as_ptr(&block) == Arc::as_ptr(b) {
39                 kwarn!(
40                     "notifier callback {:?} already registered",
41                     Arc::as_ptr(&block)
42                 );
43                 return Err(SystemError::EEXIST);
44             }
45 
46             if block.priority() > b.priority() {
47                 break;
48             }
49 
50             // 优先级唯一性检测
51             if block.priority() == b.priority() && unique_priority {
52                 return Err(SystemError::EBUSY);
53             }
54 
55             index += 1;
56         }
57 
58         // 插入 notifier chain
59         self.0.insert(index, block);
60         return Ok(());
61     }
62 
63     /// @brief 在通知链中取消注册节点
64     pub fn unregister(&mut self, block: Arc<dyn NotifierBlock<T>>) -> Result<(), SystemError> {
65         let remove = self
66             .0
67             .drain_filter(|b| Arc::as_ptr(&block) == Arc::as_ptr(b));
68         match remove.count() {
69             0 => return Err(SystemError::ENOENT),
70             _ => return Ok(()),
71         }
72     }
73 
74     /// @brief 通知链进行事件通知
75     /// @param nr_to_call 回调函数次数
76     /// @return (最后一次回调函数的返回值,回调次数)
77     // TODO: 增加 NOTIFIER_STOP_MASK 相关功能
78     pub fn call_chain(
79         &self,
80         action: u64,
81         data: Option<&T>,
82         nr_to_call: Option<usize>,
83     ) -> (i32, usize) {
84         let mut ret: i32 = 0;
85         let mut nr_calls: usize = 0;
86 
87         for b in self.0.iter() {
88             if nr_to_call.is_some_and(|x| nr_calls >= x) {
89                 break;
90             }
91             ret = b.notifier_call(action, data);
92             nr_calls += 1;
93         }
94         return (ret, nr_calls);
95     }
96 }
97 
98 /// @brief 原子的通知链,使用 SpinLock 进行同步
99 pub struct AtomicNotifierChain<T>(SpinLock<NotifierChain<T>>);
100 
101 impl<T> AtomicNotifierChain<T> {
102     pub fn new() -> Self {
103         Self(SpinLock::new(NotifierChain::<T>::new()))
104     }
105 
106     pub fn register(&mut self, block: Arc<dyn NotifierBlock<T>>) -> Result<(), SystemError> {
107         let mut notifier_chain_guard = self.0.lock();
108         return notifier_chain_guard.register(block, false);
109     }
110 
111     pub fn register_unique_prio(
112         &mut self,
113         block: Arc<dyn NotifierBlock<T>>,
114     ) -> Result<(), SystemError> {
115         let mut notifier_chain_guard = self.0.lock();
116         return notifier_chain_guard.register(block, true);
117     }
118 
119     pub fn unregister(&mut self, block: Arc<dyn NotifierBlock<T>>) -> Result<(), SystemError> {
120         let mut notifier_chain_guard = self.0.lock();
121         return notifier_chain_guard.unregister(block);
122     }
123 
124     pub fn call_chain(
125         &self,
126         action: u64,
127         data: Option<&T>,
128         nr_to_call: Option<usize>,
129     ) -> (i32, usize) {
130         let notifier_chain_guard = self.0.lock();
131         return notifier_chain_guard.call_chain(action, data, nr_to_call);
132     }
133 }
134 
135 /// @brief 可阻塞的通知链,使用 RwLock 进行同步
136 // TODO: 使用 semaphore 封装
137 pub struct BlockingNotifierChain<T>(RwLock<NotifierChain<T>>);
138 
139 impl<T> BlockingNotifierChain<T> {
140     pub fn new() -> Self {
141         Self(RwLock::new(NotifierChain::<T>::new()))
142     }
143 
144     pub fn register(&mut self, block: Arc<dyn NotifierBlock<T>>) -> Result<(), SystemError> {
145         let mut notifier_chain_guard = self.0.write();
146         return notifier_chain_guard.register(block, false);
147     }
148 
149     pub fn register_unique_prio(
150         &mut self,
151         block: Arc<dyn NotifierBlock<T>>,
152     ) -> Result<(), SystemError> {
153         let mut notifier_chain_guard = self.0.write();
154         return notifier_chain_guard.register(block, true);
155     }
156 
157     pub fn unregister(&mut self, block: Arc<dyn NotifierBlock<T>>) -> Result<(), SystemError> {
158         let mut notifier_chain_guard = self.0.write();
159         return notifier_chain_guard.unregister(block);
160     }
161 
162     pub fn call_chain(
163         &self,
164         action: u64,
165         data: Option<&T>,
166         nr_to_call: Option<usize>,
167     ) -> (i32, usize) {
168         let notifier_chain_guard = self.0.read();
169         return notifier_chain_guard.call_chain(action, data, nr_to_call);
170     }
171 }
172 
173 /// @brief 原始的通知链,由调用者自行考虑同步
174 pub struct RawNotifierChain<T>(NotifierChain<T>);
175 
176 impl<T> RawNotifierChain<T> {
177     pub fn new() -> Self {
178         Self(NotifierChain::<T>::new())
179     }
180 
181     pub fn register(&mut self, block: Arc<dyn NotifierBlock<T>>) -> Result<(), SystemError> {
182         return self.0.register(block, false);
183     }
184 
185     pub fn unregister(&mut self, block: Arc<dyn NotifierBlock<T>>) -> Result<(), SystemError> {
186         return self.0.unregister(block);
187     }
188 
189     pub fn call_chain(
190         &self,
191         action: u64,
192         data: Option<&T>,
193         nr_to_call: Option<usize>,
194     ) -> (i32, usize) {
195         return self.0.call_chain(action, data, nr_to_call);
196     }
197 }
198