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