1 use core::{ 2 fmt::Debug, 3 intrinsics::unlikely, 4 mem::{self, MaybeUninit}, 5 ptr::null_mut, 6 sync::atomic::{compiler_fence, AtomicI16, Ordering}, 7 }; 8 9 use alloc::{boxed::Box, sync::Arc, vec::Vec}; 10 use num_traits::FromPrimitive; 11 use system_error::SystemError; 12 13 use crate::{ 14 arch::CurrentIrqArch, 15 exception::InterruptArch, 16 kdebug, kinfo, 17 libs::rwlock::RwLock, 18 mm::percpu::{PerCpu, PerCpuVar}, 19 process::ProcessManager, 20 smp::core::smp_get_processor_id, 21 time::timer::clock, 22 }; 23 24 const MAX_SOFTIRQ_NUM: u64 = 64; 25 const MAX_SOFTIRQ_RESTART: i32 = 20; 26 27 static mut __CPU_PENDING: Option<Box<[VecStatus; PerCpu::MAX_CPU_NUM]>> = None; 28 static mut __SORTIRQ_VECTORS: *mut Softirq = null_mut(); 29 30 #[no_mangle] 31 pub extern "C" fn rs_softirq_init() { 32 softirq_init().expect("softirq_init failed"); 33 } 34 35 pub fn softirq_init() -> Result<(), SystemError> { 36 kinfo!("Initializing softirq..."); 37 unsafe { 38 __SORTIRQ_VECTORS = Box::leak(Box::new(Softirq::new())); 39 __CPU_PENDING = Some(Box::new( 40 [VecStatus::default(); PerCpu::MAX_CPU_NUM as usize], 41 )); 42 let cpu_pending = __CPU_PENDING.as_mut().unwrap(); 43 for i in 0..PerCpu::MAX_CPU_NUM { 44 cpu_pending[i as usize] = VecStatus::default(); 45 } 46 } 47 kinfo!("Softirq initialized."); 48 return Ok(()); 49 } 50 51 #[inline(always)] 52 pub fn softirq_vectors() -> &'static mut Softirq { 53 unsafe { 54 return __SORTIRQ_VECTORS.as_mut().unwrap(); 55 } 56 } 57 58 #[inline(always)] 59 fn cpu_pending(cpu_id: usize) -> &'static mut VecStatus { 60 unsafe { 61 return &mut __CPU_PENDING.as_mut().unwrap()[cpu_id]; 62 } 63 } 64 65 /// 软中断向量号码 66 #[allow(dead_code)] 67 #[repr(u8)] 68 #[derive(FromPrimitive, Copy, Clone, Debug, PartialEq, Eq)] 69 pub enum SoftirqNumber { 70 /// 时钟软中断信号 71 TIMER = 0, 72 VideoRefresh = 1, //帧缓冲区刷新软中断 73 } 74 75 impl From<u64> for SoftirqNumber { 76 fn from(value: u64) -> Self { 77 return <Self as FromPrimitive>::from_u64(value).unwrap(); 78 } 79 } 80 81 bitflags! { 82 #[derive(Default)] 83 pub struct VecStatus: u64 { 84 const TIMER = 1 << 0; 85 const VIDEO_REFRESH = 1 << 1; 86 } 87 } 88 89 impl From<SoftirqNumber> for VecStatus { 90 fn from(value: SoftirqNumber) -> Self { 91 return Self::from_bits_truncate(1 << (value as u64)); 92 } 93 } 94 95 pub trait SoftirqVec: Send + Sync + Debug { 96 fn run(&self); 97 } 98 99 #[derive(Debug)] 100 pub struct Softirq { 101 table: RwLock<[Option<Arc<dyn SoftirqVec>>; MAX_SOFTIRQ_NUM as usize]>, 102 /// 软中断嵌套层数(per cpu) 103 cpu_running_count: PerCpuVar<AtomicI16>, 104 } 105 impl Softirq { 106 /// 每个CPU最大嵌套的软中断数量 107 const MAX_RUNNING_PER_CPU: i16 = 3; 108 fn new() -> Softirq { 109 let mut data: [MaybeUninit<Option<Arc<dyn SoftirqVec>>>; MAX_SOFTIRQ_NUM as usize] = 110 unsafe { MaybeUninit::uninit().assume_init() }; 111 112 for i in 0..MAX_SOFTIRQ_NUM { 113 data[i as usize] = MaybeUninit::new(None); 114 } 115 116 let data: [Option<Arc<dyn SoftirqVec>>; MAX_SOFTIRQ_NUM as usize] = unsafe { 117 mem::transmute::<_, [Option<Arc<dyn SoftirqVec>>; MAX_SOFTIRQ_NUM as usize]>(data) 118 }; 119 120 let mut percpu_count = Vec::with_capacity(PerCpu::MAX_CPU_NUM as usize); 121 percpu_count.resize_with(PerCpu::MAX_CPU_NUM as usize, || AtomicI16::new(0)); 122 let cpu_running_count = PerCpuVar::new(percpu_count).unwrap(); 123 124 return Softirq { 125 table: RwLock::new(data), 126 cpu_running_count, 127 }; 128 } 129 130 fn cpu_running_count(&self) -> &PerCpuVar<AtomicI16> { 131 return &self.cpu_running_count; 132 } 133 134 /// @brief 注册软中断向量 135 /// 136 /// @param softirq_num 中断向量号 137 /// 138 /// @param hanlder 中断函数对应的结构体 139 pub fn register_softirq( 140 &self, 141 softirq_num: SoftirqNumber, 142 handler: Arc<dyn SoftirqVec>, 143 ) -> Result<i32, SystemError> { 144 // kdebug!("register_softirq softirq_num = {:?}", softirq_num as u64); 145 146 // let self = &mut SOFTIRQ_VECTORS.lock(); 147 // 判断该软中断向量是否已经被注册 148 let mut table_guard = self.table.write_irqsave(); 149 if table_guard[softirq_num as usize].is_some() { 150 // kdebug!("register_softirq failed"); 151 152 return Err(SystemError::EINVAL); 153 } 154 table_guard[softirq_num as usize] = Some(handler); 155 drop(table_guard); 156 157 // kdebug!( 158 // "register_softirq successfully, softirq_num = {:?}", 159 // softirq_num as u64 160 // ); 161 compiler_fence(Ordering::SeqCst); 162 return Ok(0); 163 } 164 165 /// @brief 解注册软中断向量 166 /// 167 /// @param irq_num 中断向量号码 168 pub fn unregister_softirq(&self, softirq_num: SoftirqNumber) { 169 // kdebug!("unregister_softirq softirq_num = {:?}", softirq_num as u64); 170 let mut table_guard = self.table.write_irqsave(); 171 // 将软中断向量清空 172 table_guard[softirq_num as usize] = None; 173 drop(table_guard); 174 // 将对应位置的pending和runing都置0 175 // self.running.lock().set(VecStatus::from(softirq_num), false); 176 // 将对应CPU的pending置0 177 compiler_fence(Ordering::SeqCst); 178 cpu_pending(smp_get_processor_id() as usize).set(VecStatus::from(softirq_num), false); 179 compiler_fence(Ordering::SeqCst); 180 } 181 182 pub fn do_softirq(&self) { 183 if self.cpu_running_count().get().load(Ordering::SeqCst) >= Self::MAX_RUNNING_PER_CPU { 184 // 当前CPU的软中断嵌套层数已经达到最大值,不再执行 185 return; 186 } 187 // 创建一个RunningCountGuard,当退出作用域时,会自动将cpu_running_count减1 188 let _count_guard = RunningCountGuard::new(self.cpu_running_count()); 189 190 // TODO pcb的flags未修改 191 let end = clock() + 500 * 2; 192 let cpu_id = smp_get_processor_id(); 193 let mut max_restart = MAX_SOFTIRQ_RESTART; 194 loop { 195 compiler_fence(Ordering::SeqCst); 196 let pending = cpu_pending(cpu_id as usize).bits; 197 cpu_pending(cpu_id as usize).bits = 0; 198 compiler_fence(Ordering::SeqCst); 199 200 unsafe { CurrentIrqArch::interrupt_enable() }; 201 if pending != 0 { 202 for i in 0..MAX_SOFTIRQ_NUM { 203 if pending & (1 << i) == 0 { 204 continue; 205 } 206 207 let table_guard = self.table.read_irqsave(); 208 let softirq_func = table_guard[i as usize].clone(); 209 drop(table_guard); 210 if softirq_func.is_none() { 211 continue; 212 } 213 214 let prev_count: usize = ProcessManager::current_pcb().preempt_count(); 215 216 softirq_func.as_ref().unwrap().run(); 217 if unlikely(prev_count != ProcessManager::current_pcb().preempt_count()) { 218 kdebug!( 219 "entered softirq {:?} with preempt_count {:?},exited with {:?}", 220 i, 221 prev_count, 222 ProcessManager::current_pcb().preempt_count() 223 ); 224 unsafe { ProcessManager::current_pcb().set_preempt_count(prev_count) }; 225 } 226 } 227 } 228 unsafe { CurrentIrqArch::interrupt_disable() }; 229 max_restart -= 1; 230 compiler_fence(Ordering::SeqCst); 231 if cpu_pending(cpu_id as usize).is_empty() { 232 compiler_fence(Ordering::SeqCst); 233 if clock() < end && max_restart > 0 { 234 continue; 235 } else { 236 break; 237 } 238 } else { 239 // TODO:当有softirqd时 唤醒它 240 break; 241 } 242 } 243 } 244 245 pub fn raise_softirq(&self, softirq_num: SoftirqNumber) { 246 let guard = unsafe { CurrentIrqArch::save_and_disable_irq() }; 247 let processor_id = smp_get_processor_id() as usize; 248 249 cpu_pending(processor_id).insert(VecStatus::from(softirq_num)); 250 251 compiler_fence(Ordering::SeqCst); 252 253 drop(guard); 254 // kdebug!("raise_softirq exited"); 255 } 256 pub unsafe fn clear_softirq_pending(&self, softirq_num: SoftirqNumber) { 257 compiler_fence(Ordering::SeqCst); 258 cpu_pending(smp_get_processor_id() as usize).remove(VecStatus::from(softirq_num)); 259 compiler_fence(Ordering::SeqCst); 260 } 261 } 262 263 /// 当前CPU的软中断嵌套层数的计数器守卫 264 /// 265 /// 当进入作用域时,会自动将cpu_running_count加1, 266 /// 当退出作用域时,会自动将cpu_running_count减1 267 struct RunningCountGuard<'a> { 268 cpu_running_count: &'a PerCpuVar<AtomicI16>, 269 } 270 271 impl<'a> RunningCountGuard<'a> { 272 fn new(cpu_running_count: &'a PerCpuVar<AtomicI16>) -> RunningCountGuard { 273 cpu_running_count.get().fetch_add(1, Ordering::SeqCst); 274 return RunningCountGuard { cpu_running_count }; 275 } 276 } 277 278 impl<'a> Drop for RunningCountGuard<'a> { 279 fn drop(&mut self) { 280 self.cpu_running_count.get().fetch_sub(1, Ordering::SeqCst); 281 } 282 } 283 284 // ======= 以下为给C提供的接口 ======= 285 #[no_mangle] 286 pub extern "C" fn rs_raise_softirq(softirq_num: u32) { 287 softirq_vectors().raise_softirq(SoftirqNumber::from(softirq_num as u64)); 288 } 289 290 #[no_mangle] 291 pub extern "C" fn rs_unregister_softirq(softirq_num: u32) { 292 softirq_vectors().unregister_softirq(SoftirqNumber::from(softirq_num as u64)); 293 } 294 295 #[no_mangle] 296 pub extern "C" fn rs_do_softirq() { 297 softirq_vectors().do_softirq(); 298 } 299 300 #[no_mangle] 301 pub extern "C" fn rs_clear_softirq_pending(softirq_num: u32) { 302 unsafe { 303 softirq_vectors().clear_softirq_pending(SoftirqNumber::from(softirq_num as u64)); 304 } 305 } 306