mirror of
https://github.com/DragonOS-Community/DragonOS.git
synced 2025-06-18 12:16:31 +00:00
实现内核通知链 notifier chain (#316)
* 实现通知链块结构 * 实现通知链的基本功能 * 实现 atomic notifier chain * 实现 blocking notifier chain * 使用 rust 范式完成功能 * 支持回调次数 nr_to_call * 移动至 libs 目录 * 完善通知链相关方法 * 修正相关格式 * 文档编写 * 更改文档路径
This commit is contained in:
@ -7,6 +7,7 @@
|
||||
#![feature(core_intrinsics)]
|
||||
#![feature(c_void_variant)]
|
||||
#![feature(drain_filter)]
|
||||
#![feature(is_some_and)]
|
||||
#![feature(panic_info_message)]
|
||||
#![feature(ptr_internals)]
|
||||
#![feature(trait_upcasting)]
|
||||
|
@ -20,4 +20,5 @@ pub mod spinlock;
|
||||
pub mod vec_cursor;
|
||||
#[macro_use]
|
||||
pub mod volatile;
|
||||
pub mod notifier;
|
||||
pub mod wait_queue;
|
||||
|
196
kernel/src/libs/notifier.rs
Normal file
196
kernel/src/libs/notifier.rs
Normal file
@ -0,0 +1,196 @@
|
||||
use crate::{
|
||||
kwarn,
|
||||
libs::{rwlock::RwLock, spinlock::SpinLock},
|
||||
syscall::SystemError,
|
||||
};
|
||||
use alloc::{sync::Arc, vec::Vec};
|
||||
|
||||
/// @brief 通知链节点
|
||||
pub trait NotifierBlock<T> {
|
||||
/// @brief 通知链中注册的回调函数类型
|
||||
fn notifier_call(&self, action: u64, data: Option<&T>) -> i32;
|
||||
/// @brief 通知链节点的优先级
|
||||
fn priority(&self) -> i32;
|
||||
}
|
||||
|
||||
/// @brief 通知链
|
||||
// TODO: 考虑使用红黑树封装
|
||||
struct NotifierChain<T>(Vec<Arc<dyn NotifierBlock<T>>>);
|
||||
|
||||
impl<T> NotifierChain<T> {
|
||||
pub fn new() -> Self {
|
||||
Self(vec![])
|
||||
}
|
||||
|
||||
/// @brief 将节点注册到通知链
|
||||
/// @param unique_priority 检查通知链中优先级的唯一性
|
||||
pub fn register(
|
||||
&mut self,
|
||||
block: Arc<dyn NotifierBlock<T>>,
|
||||
unique_priority: bool,
|
||||
) -> Result<(), SystemError> {
|
||||
let mut index: usize = 0;
|
||||
|
||||
// 在 notifier chain中寻找第一个优先级比要插入块低的块
|
||||
for b in self.0.iter() {
|
||||
// 判断之前是否已经注册过该节点
|
||||
if Arc::as_ptr(&block) == Arc::as_ptr(b) {
|
||||
kwarn!(
|
||||
"notifier callback {:?} already registered",
|
||||
Arc::as_ptr(&block)
|
||||
);
|
||||
return Err(SystemError::EEXIST);
|
||||
}
|
||||
|
||||
if block.priority() > b.priority() {
|
||||
break;
|
||||
}
|
||||
|
||||
// 优先级唯一性检测
|
||||
if block.priority() == b.priority() && unique_priority {
|
||||
return Err(SystemError::EBUSY);
|
||||
}
|
||||
|
||||
index += 1;
|
||||
}
|
||||
|
||||
// 插入 notifier chain
|
||||
self.0.insert(index, block);
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
/// @brief 在通知链中取消注册节点
|
||||
pub fn unregister(&mut self, block: Arc<dyn NotifierBlock<T>>) -> Result<(), SystemError> {
|
||||
let remove = self
|
||||
.0
|
||||
.drain_filter(|b| Arc::as_ptr(&block) == Arc::as_ptr(b));
|
||||
match remove.count() {
|
||||
0 => return Err(SystemError::ENOENT),
|
||||
_ => return Ok(()),
|
||||
}
|
||||
}
|
||||
|
||||
/// @brief 通知链进行事件通知
|
||||
/// @param nr_to_call 回调函数次数
|
||||
/// @return (最后一次回调函数的返回值,回调次数)
|
||||
// TODO: 增加 NOTIFIER_STOP_MASK 相关功能
|
||||
pub fn call_chain(
|
||||
&self,
|
||||
action: u64,
|
||||
data: Option<&T>,
|
||||
nr_to_call: Option<usize>,
|
||||
) -> (i32, usize) {
|
||||
let mut ret: i32 = 0;
|
||||
let mut nr_calls: usize = 0;
|
||||
|
||||
for b in self.0.iter() {
|
||||
if nr_to_call.is_some_and(|x| nr_calls >= x) {
|
||||
break;
|
||||
}
|
||||
ret = b.notifier_call(action, data);
|
||||
nr_calls += 1;
|
||||
}
|
||||
return (ret, nr_calls);
|
||||
}
|
||||
}
|
||||
|
||||
/// @brief 原子的通知链,使用 SpinLock 进行同步
|
||||
pub struct AtomicNotifierChain<T>(SpinLock<NotifierChain<T>>);
|
||||
|
||||
impl<T> AtomicNotifierChain<T> {
|
||||
pub fn new() -> Self {
|
||||
Self(SpinLock::new(NotifierChain::<T>::new()))
|
||||
}
|
||||
|
||||
pub fn register(&mut self, block: Arc<dyn NotifierBlock<T>>) -> Result<(), SystemError> {
|
||||
let mut notifier_chain_guard = self.0.lock();
|
||||
return notifier_chain_guard.register(block, false);
|
||||
}
|
||||
|
||||
pub fn register_unique_prio(
|
||||
&mut self,
|
||||
block: Arc<dyn NotifierBlock<T>>,
|
||||
) -> Result<(), SystemError> {
|
||||
let mut notifier_chain_guard = self.0.lock();
|
||||
return notifier_chain_guard.register(block, true);
|
||||
}
|
||||
|
||||
pub fn unregister(&mut self, block: Arc<dyn NotifierBlock<T>>) -> Result<(), SystemError> {
|
||||
let mut notifier_chain_guard = self.0.lock();
|
||||
return notifier_chain_guard.unregister(block);
|
||||
}
|
||||
|
||||
pub fn call_chain(
|
||||
&self,
|
||||
action: u64,
|
||||
data: Option<&T>,
|
||||
nr_to_call: Option<usize>,
|
||||
) -> (i32, usize) {
|
||||
let notifier_chain_guard = self.0.lock();
|
||||
return notifier_chain_guard.call_chain(action, data, nr_to_call);
|
||||
}
|
||||
}
|
||||
|
||||
/// @brief 可阻塞的通知链,使用 RwLock 进行同步
|
||||
// TODO: 使用 semaphore 封装
|
||||
pub struct BlockingNotifierChain<T>(RwLock<NotifierChain<T>>);
|
||||
|
||||
impl<T> BlockingNotifierChain<T> {
|
||||
pub fn new() -> Self {
|
||||
Self(RwLock::new(NotifierChain::<T>::new()))
|
||||
}
|
||||
|
||||
pub fn register(&mut self, block: Arc<dyn NotifierBlock<T>>) -> Result<(), SystemError> {
|
||||
let mut notifier_chain_guard = self.0.write();
|
||||
return notifier_chain_guard.register(block, false);
|
||||
}
|
||||
|
||||
pub fn register_unique_prio(
|
||||
&mut self,
|
||||
block: Arc<dyn NotifierBlock<T>>,
|
||||
) -> Result<(), SystemError> {
|
||||
let mut notifier_chain_guard = self.0.write();
|
||||
return notifier_chain_guard.register(block, true);
|
||||
}
|
||||
|
||||
pub fn unregister(&mut self, block: Arc<dyn NotifierBlock<T>>) -> Result<(), SystemError> {
|
||||
let mut notifier_chain_guard = self.0.write();
|
||||
return notifier_chain_guard.unregister(block);
|
||||
}
|
||||
|
||||
pub fn call_chain(
|
||||
&self,
|
||||
action: u64,
|
||||
data: Option<&T>,
|
||||
nr_to_call: Option<usize>,
|
||||
) -> (i32, usize) {
|
||||
let notifier_chain_guard = self.0.read();
|
||||
return notifier_chain_guard.call_chain(action, data, nr_to_call);
|
||||
}
|
||||
}
|
||||
|
||||
/// @brief 原始的通知链,由调用者自行考虑同步
|
||||
pub struct RawNotifierChain<T>(NotifierChain<T>);
|
||||
|
||||
impl<T> RawNotifierChain<T> {
|
||||
pub fn new() -> Self {
|
||||
Self(NotifierChain::<T>::new())
|
||||
}
|
||||
|
||||
pub fn register(&mut self, block: Arc<dyn NotifierBlock<T>>) -> Result<(), SystemError> {
|
||||
return self.0.register(block, false);
|
||||
}
|
||||
|
||||
pub fn unregister(&mut self, block: Arc<dyn NotifierBlock<T>>) -> Result<(), SystemError> {
|
||||
return self.0.unregister(block);
|
||||
}
|
||||
|
||||
pub fn call_chain(
|
||||
&self,
|
||||
action: u64,
|
||||
data: Option<&T>,
|
||||
nr_to_call: Option<usize>,
|
||||
) -> (i32, usize) {
|
||||
return self.0.call_chain(action, data, nr_to_call);
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user