1 use core::{ffi::c_void, ptr::null_mut}; 2 3 use alloc::boxed::Box; 4 5 use crate::{ 6 arch::interrupt::{cli, sti}, 7 include::bindings::bindings::{verify_area, EBUSY, EEXIST, EPERM}, 8 kBUG, 9 libs::spinlock::RawSpinlock, 10 }; 11 12 const MAX_SOFTIRQ_NUM: u64 = 64; 13 const MAX_LOCK_TRIAL_TIME: u64 = 50; 14 pub static mut SOFTIRQ_HANDLER_PTR: *mut Softirq = null_mut(); 15 16 /// 软中断向量号码 17 #[allow(dead_code)] 18 #[repr(u8)] 19 pub enum SoftirqNumber { 20 TIMER = 0, //时钟软中断信号 21 VideoRefresh = 1, //帧缓冲区刷新软中断 22 } 23 24 #[repr(C)] 25 #[derive(Clone, Copy)] 26 pub struct SoftirqVector { 27 pub action: Option<unsafe extern "C" fn(data: *mut ::core::ffi::c_void)>, //软中断处理函数 28 pub data: *mut c_void, 29 } 30 31 impl Default for SoftirqVector { 32 fn default() -> Self { 33 Self { 34 action: None, 35 data: null_mut(), 36 } 37 } 38 } 39 40 pub struct Softirq { 41 modify_lock: RawSpinlock, 42 pending: u64, 43 running: u64, 44 table: [SoftirqVector; MAX_SOFTIRQ_NUM as usize], 45 } 46 47 #[no_mangle] 48 #[allow(dead_code)] 49 /// @brief 提供给c的接口函数,用于初始化静态指针 50 pub extern "C" fn softirq_init() { 51 if unsafe { SOFTIRQ_HANDLER_PTR.is_null() } { 52 unsafe { 53 SOFTIRQ_HANDLER_PTR = Box::leak(Box::new(Softirq::default())); 54 } 55 } else { 56 kBUG!("Try to init SOFTIRQ_HANDLER_PTR twice."); 57 panic!("Try to init SOFTIRQ_HANDLER_PTR twice."); 58 } 59 } 60 61 /// @brief 将raw pointer转换为指针,减少unsafe块 62 #[inline] 63 pub fn __get_softirq_handler_mut() -> &'static mut Softirq { 64 return unsafe { SOFTIRQ_HANDLER_PTR.as_mut().unwrap() }; 65 } 66 67 #[no_mangle] 68 #[allow(dead_code)] 69 pub extern "C" fn raise_softirq(sirq_num: u64) { 70 let softirq_handler = __get_softirq_handler_mut(); 71 softirq_handler.set_softirq_pending(1 << sirq_num); 72 } 73 74 /// @brief 软中断注册函数 75 /// 76 /// @param irq_num 软中断号 77 /// @param action 响应函数 78 /// @param data 响应数据结构体 79 #[no_mangle] 80 #[allow(dead_code)] 81 pub extern "C" fn register_softirq( 82 irq_num: u32, 83 action: Option<unsafe extern "C" fn(data: *mut ::core::ffi::c_void)>, 84 data: *mut c_void, 85 ) { 86 let softirq_handler = __get_softirq_handler_mut(); 87 softirq_handler.register_softirq(irq_num, action, data); 88 } 89 90 /// @brief 卸载软中断 91 /// @param irq_num 软中断号 92 #[no_mangle] 93 #[allow(dead_code)] 94 pub extern "C" fn unregister_softirq(irq_num: u32) { 95 let softirq_handler = __get_softirq_handler_mut(); 96 softirq_handler.unregister_softirq(irq_num); 97 } 98 99 /// 设置软中断的运行状态(只应在do_softirq中调用此宏) 100 #[no_mangle] 101 #[allow(dead_code)] 102 pub extern "C" fn set_softirq_pending(irq_num: u32) { 103 let softirq_handler = __get_softirq_handler_mut(); 104 softirq_handler.set_softirq_pending(irq_num); 105 } 106 107 /// @brief 设置软中断运行结束 108 /// 109 /// @param softirq_num 110 #[no_mangle] 111 #[allow(dead_code)] 112 pub extern "C" fn clear_softirq_pending(irq_num: u32) { 113 let softirq_handler = __get_softirq_handler_mut(); 114 softirq_handler.clear_softirq_pending(irq_num); 115 } 116 117 /// @brief 软中断处理程序 118 #[no_mangle] 119 #[allow(dead_code)] 120 pub extern "C" fn do_softirq() { 121 let softirq_handler = __get_softirq_handler_mut(); 122 softirq_handler.do_softirq(); 123 } 124 125 impl Default for Softirq { 126 fn default() -> Self { 127 Self { 128 modify_lock: RawSpinlock::INIT, 129 pending: (0), 130 running: (0), 131 table: [Default::default(); MAX_SOFTIRQ_NUM as usize], 132 } 133 } 134 } 135 136 impl Softirq { 137 #[inline] 138 #[allow(dead_code)] 139 pub fn get_softirq_pending(&self) -> u64 { 140 return self.pending; 141 } 142 143 #[inline] 144 #[allow(dead_code)] 145 pub fn get_softirq_running(&self) -> u64 { 146 return self.running; 147 } 148 149 #[inline] 150 pub fn set_softirq_pending(&mut self, softirq_num: u32) { 151 self.pending |= 1 << softirq_num; 152 } 153 154 #[inline] 155 pub fn set_softirq_running(&mut self, softirq_num: u32) { 156 self.running |= 1 << softirq_num; 157 } 158 159 #[inline] 160 pub fn clear_softirq_running(&mut self, softirq_num: u32) { 161 self.running &= !(1 << softirq_num); 162 } 163 164 /// @brief 清除软中断pending标志位 165 #[inline] 166 pub fn clear_softirq_pending(&mut self, softirq_num: u32) { 167 self.pending &= !(1 << softirq_num); 168 } 169 170 /// @brief 判断对应running标志位是否为0 171 /// @return true: 标志位为1; false: 标志位为0 172 #[inline] 173 pub fn is_running(&mut self, softirq_num: u32) -> bool { 174 return (self.running & (1 << softirq_num)).ne(&0); 175 } 176 177 /// @brief 判断对应pending标志位是否为0 178 /// @return true: 标志位为1; false: 标志位为0 179 #[inline] 180 pub fn is_pending(&mut self, softirq_num: u32) -> bool { 181 return (self.pending & (1 << softirq_num)).ne(&0); 182 } 183 184 /// @brief 注册软中断向量 185 /// @param irq_num 中断向量号码 186 /// @param action 中断函数的入口地址 187 /// @param data 中断函数的操作数据 188 pub fn register_softirq( 189 &mut self, 190 irq_num: u32, 191 action: Option<unsafe extern "C" fn(data: *mut ::core::ffi::c_void)>, 192 data: *mut c_void, 193 ) -> i32 { 194 if self.table[irq_num as usize].action.is_some() { 195 return -(EEXIST as i32); 196 } 197 198 if unsafe { verify_area(action.unwrap() as u64, 1) } { 199 return -(EPERM as i32); 200 } 201 self.modify_lock.lock(); 202 self.table[irq_num as usize].action = action; 203 self.table[irq_num as usize].data = data; 204 self.modify_lock.unlock(); 205 return 0; 206 } 207 208 /// @brief 解注册软中断向量 209 /// @param irq_num 中断向量号码 210 pub fn unregister_softirq(&mut self, irq_num: u32) -> i32 { 211 for _trial_time in 0..MAX_LOCK_TRIAL_TIME { 212 if self.is_running(irq_num) { 213 continue; //running标志位为1 214 } 215 if self.modify_lock.try_lock() { 216 if self.is_running(irq_num) { 217 self.modify_lock.unlock(); 218 continue; 219 } 220 break; 221 } 222 } 223 // 存在尝试加锁规定次数后仍加锁失败的情况,报告错误并退出 224 if !self.modify_lock.is_locked() { 225 return -(EBUSY as i32); 226 } 227 self.clear_softirq_running(irq_num); 228 self.clear_softirq_pending(irq_num); 229 self.table[irq_num as usize].action = None; 230 self.table[irq_num as usize].data = null_mut(); 231 self.modify_lock.unlock(); 232 return 0; 233 } 234 235 /// @brief 遍历执行软中断 236 pub fn do_softirq(&mut self) { 237 sti(); 238 let mut softirq_index: u32 = 0; //软中断向量号码 239 while (softirq_index as u64) < MAX_SOFTIRQ_NUM && self.pending != 0 { 240 if self.is_pending(softirq_index) 241 && self.table[softirq_index as usize].action.is_some() 242 && !self.is_running(softirq_index) 243 { 244 if self.modify_lock.try_lock() { 245 if self.is_running(softirq_index) 246 || self.table[softirq_index as usize].action.is_none() 247 { 248 self.modify_lock.unlock(); 249 continue; 250 } 251 self.clear_softirq_pending(softirq_index); 252 self.set_softirq_running(softirq_index); 253 self.modify_lock.unlock(); 254 unsafe { 255 (self.table[softirq_index as usize].action.unwrap())( 256 self.table[softirq_index as usize].data, 257 ); 258 } 259 self.clear_softirq_running(softirq_index); 260 } 261 } 262 softirq_index += 1; 263 } 264 cli(); 265 } 266 } 267