实现内核通知链 notifier chain (#316)

* 实现通知链块结构

* 实现通知链的基本功能

* 实现 atomic notifier chain

* 实现 blocking notifier chain

* 使用 rust 范式完成功能

* 支持回调次数 nr_to_call

* 移动至 libs 目录

* 完善通知链相关方法

* 修正相关格式

* 文档编写

* 更改文档路径
This commit is contained in:
Xshine
2023-08-06 12:53:47 +08:00
committed by GitHub
parent be63f3b2b6
commit 729a96ef47
5 changed files with 232 additions and 0 deletions

View File

@ -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)]

View File

@ -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
View 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);
}
}