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