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