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