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::{ 14 asm::{ 15 current::current_pcb, 16 irqflags::{local_irq_restore, local_irq_save}, 17 }, 18 interrupt::{cli, sti}, 19 }, 20 include::bindings::bindings::MAX_CPU_NUM, 21 kdebug, kinfo, 22 libs::rwlock::RwLock, 23 smp::core::smp_get_processor_id, 24 syscall::SystemError, 25 time::timer::clock, 26 }; 27 28 const MAX_SOFTIRQ_NUM: u64 = 64; 29 const MAX_SOFTIRQ_RESTART: i32 = 20; 30 31 static mut __CPU_PENDING: Option<Box<[VecStatus; MAX_CPU_NUM as usize]>> = None; 32 static mut __SORTIRQ_VECTORS: *mut Softirq = null_mut(); 33 34 #[no_mangle] 35 pub extern "C" fn rs_softirq_init() { 36 softirq_init().expect("softirq_init failed"); 37 } 38 39 pub fn softirq_init() -> Result<(), SystemError> { 40 kinfo!("Initializing softirq..."); 41 unsafe { 42 __SORTIRQ_VECTORS = Box::leak(Box::new(Softirq::new())); 43 __CPU_PENDING = Some(Box::new([VecStatus::default(); MAX_CPU_NUM as usize])); 44 let cpu_pending = __CPU_PENDING.as_mut().unwrap(); 45 for i in 0..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: usize) -> &'static mut VecStatus { 62 unsafe { 63 return &mut __CPU_PENDING.as_mut().unwrap()[cpu_id]; 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 } 105 impl Softirq { 106 fn new() -> Softirq { 107 let mut data: [MaybeUninit<Option<Arc<dyn SoftirqVec>>>; MAX_SOFTIRQ_NUM as usize] = 108 unsafe { MaybeUninit::uninit().assume_init() }; 109 110 for i in 0..MAX_SOFTIRQ_NUM { 111 data[i as usize] = MaybeUninit::new(None); 112 } 113 114 let data: [Option<Arc<dyn SoftirqVec>>; MAX_SOFTIRQ_NUM as usize] = unsafe { 115 mem::transmute::<_, [Option<Arc<dyn SoftirqVec>>; MAX_SOFTIRQ_NUM as usize]>(data) 116 }; 117 118 return Softirq { 119 table: RwLock::new(data), 120 }; 121 } 122 123 /// @brief 注册软中断向量 124 /// 125 /// @param softirq_num 中断向量号 126 /// 127 /// @param hanlder 中断函数对应的结构体 128 pub fn register_softirq( 129 &self, 130 softirq_num: SoftirqNumber, 131 handler: Arc<dyn SoftirqVec>, 132 ) -> Result<i32, SystemError> { 133 // kdebug!("register_softirq softirq_num = {:?}", softirq_num as u64); 134 135 // let self = &mut SOFTIRQ_VECTORS.lock(); 136 // 判断该软中断向量是否已经被注册 137 let mut table_guard = self.table.write(); 138 if table_guard[softirq_num as usize].is_some() { 139 // kdebug!("register_softirq failed"); 140 141 return Err(SystemError::EINVAL); 142 } 143 table_guard[softirq_num as usize] = Some(handler); 144 drop(table_guard); 145 146 // kdebug!( 147 // "register_softirq successfully, softirq_num = {:?}", 148 // softirq_num as u64 149 // ); 150 compiler_fence(Ordering::SeqCst); 151 return Ok(0); 152 } 153 154 /// @brief 解注册软中断向量 155 /// 156 /// @param irq_num 中断向量号码 157 pub fn unregister_softirq(&self, softirq_num: SoftirqNumber) { 158 // kdebug!("unregister_softirq softirq_num = {:?}", softirq_num as u64); 159 let table_guard = &mut self.table.write(); 160 // 将软中断向量清空 161 table_guard[softirq_num as usize] = None; 162 drop(table_guard); 163 // 将对应位置的pending和runing都置0 164 // self.running.lock().set(VecStatus::from(softirq_num), false); 165 // 将对应CPU的pending置0 166 compiler_fence(Ordering::SeqCst); 167 cpu_pending(smp_get_processor_id() as usize).set(VecStatus::from(softirq_num), false); 168 compiler_fence(Ordering::SeqCst); 169 } 170 171 pub fn do_softirq(&self) { 172 // TODO pcb的flags未修改 173 // todo: 是否需要判断在当前cpu上面,该函数的嵌套层数?(防止爆栈) 174 let end = clock() + 500 * 2; 175 let cpu_id = smp_get_processor_id(); 176 let mut max_restart = MAX_SOFTIRQ_RESTART; 177 loop { 178 compiler_fence(Ordering::SeqCst); 179 let pending = cpu_pending(cpu_id as usize).bits; 180 cpu_pending(cpu_id as usize).bits = 0; 181 compiler_fence(Ordering::SeqCst); 182 183 sti(); 184 if pending != 0 { 185 for i in 0..MAX_SOFTIRQ_NUM { 186 if pending & (1 << i) == 0 { 187 continue; 188 } 189 190 let table_guard = self.table.read(); 191 let softirq_func = table_guard[i as usize].clone(); 192 drop(table_guard); 193 if softirq_func.is_none() { 194 continue; 195 } 196 197 let prev_count = current_pcb().preempt_count; 198 199 softirq_func.as_ref().unwrap().run(); 200 if unlikely(prev_count != current_pcb().preempt_count) { 201 kdebug!( 202 "entered softirq {:?} with preempt_count {:?},exited with {:?}", 203 i, 204 prev_count, 205 current_pcb().preempt_count 206 ); 207 current_pcb().preempt_count = prev_count; 208 } 209 } 210 } 211 cli(); 212 max_restart -= 1; 213 compiler_fence(Ordering::SeqCst); 214 if cpu_pending(cpu_id as usize).is_empty() { 215 compiler_fence(Ordering::SeqCst); 216 if clock() < end && max_restart > 0 { 217 continue; 218 } else { 219 break; 220 } 221 } else { 222 // TODO:当有softirqd时 唤醒它 223 break; 224 } 225 } 226 } 227 228 pub fn raise_softirq(&self, softirq_num: SoftirqNumber) { 229 let flags = local_irq_save(); 230 let processor_id = smp_get_processor_id() as usize; 231 232 cpu_pending(processor_id).insert(VecStatus::from(softirq_num)); 233 234 compiler_fence(Ordering::SeqCst); 235 236 local_irq_restore(flags); 237 // kdebug!("raise_softirq exited"); 238 } 239 pub unsafe fn clear_softirq_pending(&self, softirq_num: SoftirqNumber) { 240 compiler_fence(Ordering::SeqCst); 241 cpu_pending(smp_get_processor_id() as usize).remove(VecStatus::from(softirq_num)); 242 compiler_fence(Ordering::SeqCst); 243 } 244 } 245 246 // ======= 以下为给C提供的接口 ======= 247 #[no_mangle] 248 pub extern "C" fn rs_raise_softirq(softirq_num: u32) { 249 softirq_vectors().raise_softirq(SoftirqNumber::from(softirq_num as u64)); 250 } 251 252 #[no_mangle] 253 pub extern "C" fn rs_unregister_softirq(softirq_num: u32) { 254 softirq_vectors().unregister_softirq(SoftirqNumber::from(softirq_num as u64)); 255 } 256 257 #[no_mangle] 258 pub extern "C" fn rs_do_softirq() { 259 softirq_vectors().do_softirq(); 260 } 261 262 #[no_mangle] 263 pub extern "C" fn rs_clear_softirq_pending(softirq_num: u32) { 264 unsafe { 265 softirq_vectors().clear_softirq_pending(SoftirqNumber::from(softirq_num as u64)); 266 } 267 } 268