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