123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268 |
- use core::{ffi::c_void, ptr::null_mut};
- use alloc::boxed::Box;
- use crate::{
- arch::interrupt::{cli, sti},
- include::bindings::bindings::verify_area,
- kBUG,
- libs::spinlock::RawSpinlock,
- syscall::SystemError, kdebug,
- };
- const MAX_SOFTIRQ_NUM: u64 = 64;
- const MAX_LOCK_TRIAL_TIME: u64 = 50;
- pub static mut SOFTIRQ_HANDLER_PTR: *mut Softirq = null_mut();
- /// 软中断向量号码
- #[allow(dead_code)]
- #[repr(u8)]
- pub enum SoftirqNumber {
- TIMER = 0, //时钟软中断信号
- VideoRefresh = 1, //帧缓冲区刷新软中断
- }
- #[repr(C)]
- #[derive(Clone, Copy)]
- pub struct SoftirqVector {
- pub action: Option<unsafe extern "C" fn(data: *mut ::core::ffi::c_void)>, //软中断处理函数
- pub data: *mut c_void,
- }
- impl Default for SoftirqVector {
- fn default() -> Self {
- Self {
- action: None,
- data: null_mut(),
- }
- }
- }
- pub struct Softirq {
- modify_lock: RawSpinlock,
- pending: u64,
- running: u64,
- table: [SoftirqVector; MAX_SOFTIRQ_NUM as usize],
- }
- #[no_mangle]
- #[allow(dead_code)]
- /// @brief 提供给c的接口函数,用于初始化静态指针
- pub extern "C" fn softirq_init() {
- if unsafe { SOFTIRQ_HANDLER_PTR.is_null() } {
- unsafe {
- SOFTIRQ_HANDLER_PTR = Box::leak(Box::new(Softirq::default()));
- }
- } else {
- kBUG!("Try to init SOFTIRQ_HANDLER_PTR twice.");
- panic!("Try to init SOFTIRQ_HANDLER_PTR twice.");
- }
- }
- /// @brief 将raw pointer转换为指针,减少unsafe块
- #[inline]
- pub fn __get_softirq_handler_mut() -> &'static mut Softirq {
- return unsafe { SOFTIRQ_HANDLER_PTR.as_mut().unwrap() };
- }
- #[no_mangle]
- #[allow(dead_code)]
- pub extern "C" fn raise_softirq(sirq_num: u32) {
- let softirq_handler = __get_softirq_handler_mut();
- softirq_handler.set_softirq_pending(sirq_num);
- }
- /// @brief 软中断注册函数
- ///
- /// @param irq_num 软中断号
- /// @param action 响应函数
- /// @param data 响应数据结构体
- #[no_mangle]
- #[allow(dead_code)]
- pub extern "C" fn register_softirq(
- irq_num: u32,
- action: Option<unsafe extern "C" fn(data: *mut ::core::ffi::c_void)>,
- data: *mut c_void,
- ) {
- let softirq_handler = __get_softirq_handler_mut();
- softirq_handler.register_softirq(irq_num, action, data).expect(&format!("Softirq: Failed to register {}", irq_num));
- }
- /// @brief 卸载软中断
- /// @param irq_num 软中断号
- #[no_mangle]
- #[allow(dead_code)]
- pub extern "C" fn unregister_softirq(irq_num: u32) {
- let softirq_handler = __get_softirq_handler_mut();
- softirq_handler.unregister_softirq(irq_num).expect(&format!("Softirq: Failed to unregister {}", irq_num));
- }
- /// 设置软中断的运行状态(只应在do_softirq中调用此宏)
- #[no_mangle]
- #[allow(dead_code)]
- pub extern "C" fn set_softirq_pending(irq_num: u32) {
- let softirq_handler = __get_softirq_handler_mut();
- softirq_handler.set_softirq_pending(irq_num);
- }
- /// @brief 设置软中断运行结束
- ///
- /// @param softirq_num
- #[no_mangle]
- #[allow(dead_code)]
- pub extern "C" fn clear_softirq_pending(irq_num: u32) {
- let softirq_handler = __get_softirq_handler_mut();
- softirq_handler.clear_softirq_pending(irq_num);
- }
- /// @brief 软中断处理程序
- #[no_mangle]
- #[allow(dead_code)]
- pub extern "C" fn do_softirq() {
- let softirq_handler = __get_softirq_handler_mut();
- softirq_handler.do_softirq();
- }
- impl Default for Softirq {
- fn default() -> Self {
- Self {
- modify_lock: RawSpinlock::INIT,
- pending: (0),
- running: (0),
- table: [Default::default(); MAX_SOFTIRQ_NUM as usize],
- }
- }
- }
- impl Softirq {
- #[inline]
- #[allow(dead_code)]
- pub fn get_softirq_pending(&self) -> u64 {
- return self.pending;
- }
- #[inline]
- #[allow(dead_code)]
- pub fn get_softirq_running(&self) -> u64 {
- return self.running;
- }
- #[inline]
- pub fn set_softirq_pending(&mut self, softirq_num: u32) {
- self.pending |= 1 << softirq_num;
- }
- #[inline]
- pub fn set_softirq_running(&mut self, softirq_num: u32) {
- self.running |= 1 << softirq_num;
- }
- #[inline]
- pub fn clear_softirq_running(&mut self, softirq_num: u32) {
- self.running &= !(1 << softirq_num);
- }
- /// @brief 清除软中断pending标志位
- #[inline]
- pub fn clear_softirq_pending(&mut self, softirq_num: u32) {
- self.pending &= !(1 << softirq_num);
- }
- /// @brief 判断对应running标志位是否为0
- /// @return true: 标志位为1; false: 标志位为0
- #[inline]
- pub fn is_running(&mut self, softirq_num: u32) -> bool {
- return (self.running & (1 << softirq_num)).ne(&0);
- }
- /// @brief 判断对应pending标志位是否为0
- /// @return true: 标志位为1; false: 标志位为0
- #[inline]
- pub fn is_pending(&mut self, softirq_num: u32) -> bool {
- return (self.pending & (1 << softirq_num)).ne(&0);
- }
- /// @brief 注册软中断向量
- /// @param irq_num 中断向量号码
- /// @param action 中断函数的入口地址
- /// @param data 中断函数的操作数据
- pub fn register_softirq(
- &mut self,
- irq_num: u32,
- action: Option<unsafe extern "C" fn(data: *mut ::core::ffi::c_void)>,
- data: *mut c_void,
- ) -> Result<(), SystemError> {
- if self.table[irq_num as usize].action.is_some() {
- return Err(SystemError::EEXIST);
- }
- if unsafe { verify_area(action.unwrap() as u64, 1) } {
- return Err(SystemError::EPERM);
- }
- self.modify_lock.lock();
- self.table[irq_num as usize].action = action;
- self.table[irq_num as usize].data = data;
- self.modify_lock.unlock();
- return Ok(());
- }
- /// @brief 解注册软中断向量
- /// @param irq_num 中断向量号码
- pub fn unregister_softirq(&mut self, irq_num: u32) -> Result<(), SystemError> {
- for _trial_time in 0..MAX_LOCK_TRIAL_TIME {
- if self.is_running(irq_num) {
- continue; //running标志位为1
- }
- if self.modify_lock.try_lock() {
- if self.is_running(irq_num) {
- self.modify_lock.unlock();
- continue;
- }
- break;
- }
- }
- // 存在尝试加锁规定次数后仍加锁失败的情况,报告错误并退出
- if !self.modify_lock.is_locked() {
- return Err(SystemError::EBUSY);
- }
- kdebug!("SOftirq: unregister {irq_num}");
- self.clear_softirq_running(irq_num);
- self.clear_softirq_pending(irq_num);
- self.table[irq_num as usize].action = None;
- self.table[irq_num as usize].data = null_mut();
- self.modify_lock.unlock();
- return Ok(());
- }
- /// @brief 遍历执行软中断
- pub fn do_softirq(&mut self) {
- sti();
- let mut softirq_index: u32 = 0; //软中断向量号码
- while (softirq_index as u64) < MAX_SOFTIRQ_NUM && self.pending != 0 {
- if self.is_pending(softirq_index)
- && self.table[softirq_index as usize].action.is_some()
- && !self.is_running(softirq_index)
- {
- if self.modify_lock.try_lock() {
- if self.is_running(softirq_index)
- || self.table[softirq_index as usize].action.is_none()
- {
- self.modify_lock.unlock();
- continue;
- }
- self.clear_softirq_pending(softirq_index);
- self.set_softirq_running(softirq_index);
- self.modify_lock.unlock();
- unsafe {
- (self.table[softirq_index as usize].action.unwrap())(
- self.table[softirq_index as usize].data,
- );
- }
- self.clear_softirq_running(softirq_index);
- }
- }
- softirq_index += 1;
- }
- cli();
- }
- }
|