1 use core::{
2 fmt::Debug,
3 intrinsics::unlikely,
4 mem::{self, MaybeUninit},
5 ptr::null_mut,
6 sync::atomic::{compiler_fence, fence, AtomicI16, Ordering},
7 };
8
9 use alloc::{boxed::Box, sync::Arc, vec::Vec};
10 use log::{debug, info};
11 use num_traits::FromPrimitive;
12 use system_error::SystemError;
13
14 use crate::{
15 arch::CurrentIrqArch,
16 exception::InterruptArch,
17 libs::rwlock::RwLock,
18 mm::percpu::{PerCpu, PerCpuVar},
19 process::ProcessManager,
20 sched::cputime::IrqTime,
21 smp::{core::smp_get_processor_id, cpu::ProcessorId},
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; PerCpu::MAX_CPU_NUM as usize]>> = None;
29 static mut __SORTIRQ_VECTORS: *mut Softirq = null_mut();
30
31 #[no_mangle]
rs_softirq_init()32 pub extern "C" fn rs_softirq_init() {
33 softirq_init().expect("softirq_init failed");
34 }
35
36 #[inline(never)]
softirq_init() -> Result<(), SystemError>37 pub fn softirq_init() -> Result<(), SystemError> {
38 info!("Initializing softirq...");
39 unsafe {
40 __SORTIRQ_VECTORS = Box::leak(Box::new(Softirq::new()));
41 __CPU_PENDING = Some(Box::new(
42 [VecStatus::default(); PerCpu::MAX_CPU_NUM as usize],
43 ));
44 let cpu_pending = __CPU_PENDING.as_mut().unwrap();
45 for i in 0..PerCpu::MAX_CPU_NUM {
46 cpu_pending[i as usize] = VecStatus::default();
47 }
48 }
49 info!("Softirq initialized.");
50 return Ok(());
51 }
52
53 #[inline(always)]
softirq_vectors() -> &'static mut Softirq54 pub fn softirq_vectors() -> &'static mut Softirq {
55 unsafe {
56 return __SORTIRQ_VECTORS.as_mut().unwrap();
57 }
58 }
59
60 #[inline(always)]
cpu_pending(cpu_id: ProcessorId) -> &'static mut VecStatus61 fn cpu_pending(cpu_id: ProcessorId) -> &'static mut VecStatus {
62 unsafe {
63 return &mut __CPU_PENDING.as_mut().unwrap()[cpu_id.data() as usize];
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 {
from(value: u64) -> Self78 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 {
from(value: SoftirqNumber) -> Self92 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 {
run(&self)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 /// 软中断嵌套层数(per cpu)
105 cpu_running_count: PerCpuVar<AtomicI16>,
106 }
107 impl Softirq {
108 /// 每个CPU最大嵌套的软中断数量
109 const MAX_RUNNING_PER_CPU: i16 = 3;
new() -> Softirq110 fn new() -> Softirq {
111 let mut data: [MaybeUninit<Option<Arc<dyn SoftirqVec>>>; MAX_SOFTIRQ_NUM as usize] =
112 unsafe { MaybeUninit::uninit().assume_init() };
113
114 for i in 0..MAX_SOFTIRQ_NUM {
115 data[i as usize] = MaybeUninit::new(None);
116 }
117
118 let data: [Option<Arc<dyn SoftirqVec>>; MAX_SOFTIRQ_NUM as usize] = unsafe {
119 mem::transmute::<_, [Option<Arc<dyn SoftirqVec>>; MAX_SOFTIRQ_NUM as usize]>(data)
120 };
121
122 let mut percpu_count = Vec::with_capacity(PerCpu::MAX_CPU_NUM as usize);
123 percpu_count.resize_with(PerCpu::MAX_CPU_NUM as usize, || AtomicI16::new(0));
124 let cpu_running_count = PerCpuVar::new(percpu_count).unwrap();
125
126 return Softirq {
127 table: RwLock::new(data),
128 cpu_running_count,
129 };
130 }
131
cpu_running_count(&self) -> &PerCpuVar<AtomicI16>132 fn cpu_running_count(&self) -> &PerCpuVar<AtomicI16> {
133 return &self.cpu_running_count;
134 }
135
136 /// @brief 注册软中断向量
137 ///
138 /// @param softirq_num 中断向量号
139 ///
140 /// @param hanlder 中断函数对应的结构体
register_softirq( &self, softirq_num: SoftirqNumber, handler: Arc<dyn SoftirqVec>, ) -> Result<i32, SystemError>141 pub fn register_softirq(
142 &self,
143 softirq_num: SoftirqNumber,
144 handler: Arc<dyn SoftirqVec>,
145 ) -> Result<i32, SystemError> {
146 // debug!("register_softirq softirq_num = {:?}", softirq_num as u64);
147
148 // let self = &mut SOFTIRQ_VECTORS.lock();
149 // 判断该软中断向量是否已经被注册
150 let mut table_guard = self.table.write_irqsave();
151 if table_guard[softirq_num as usize].is_some() {
152 // debug!("register_softirq failed");
153
154 return Err(SystemError::EINVAL);
155 }
156 table_guard[softirq_num as usize] = Some(handler);
157 drop(table_guard);
158
159 // debug!(
160 // "register_softirq successfully, softirq_num = {:?}",
161 // softirq_num as u64
162 // );
163 compiler_fence(Ordering::SeqCst);
164 return Ok(0);
165 }
166
167 /// @brief 解注册软中断向量
168 ///
169 /// @param irq_num 中断向量号码
170 #[allow(dead_code)]
unregister_softirq(&self, softirq_num: SoftirqNumber)171 pub fn unregister_softirq(&self, softirq_num: SoftirqNumber) {
172 // debug!("unregister_softirq softirq_num = {:?}", softirq_num as u64);
173 let mut table_guard = self.table.write_irqsave();
174 // 将软中断向量清空
175 table_guard[softirq_num as usize] = None;
176 drop(table_guard);
177 // 将对应位置的pending和runing都置0
178 // self.running.lock().set(VecStatus::from(softirq_num), false);
179 // 将对应CPU的pending置0
180 compiler_fence(Ordering::SeqCst);
181 cpu_pending(smp_get_processor_id()).set(VecStatus::from(softirq_num), false);
182 compiler_fence(Ordering::SeqCst);
183 }
184
185 #[inline(never)]
do_softirq(&self)186 pub fn do_softirq(&self) {
187 if self.cpu_running_count().get().load(Ordering::SeqCst) >= Self::MAX_RUNNING_PER_CPU {
188 // 当前CPU的软中断嵌套层数已经达到最大值,不再执行
189 return;
190 }
191 // 创建一个RunningCountGuard,当退出作用域时,会自动将cpu_running_count减1
192 let _count_guard = RunningCountGuard::new(self.cpu_running_count());
193
194 // TODO pcb的flags未修改
195 let end = clock() + 500 * 2;
196 let cpu_id = smp_get_processor_id();
197 let mut max_restart = MAX_SOFTIRQ_RESTART;
198 loop {
199 compiler_fence(Ordering::SeqCst);
200 let pending = cpu_pending(cpu_id).bits;
201 cpu_pending(cpu_id).bits = 0;
202 compiler_fence(Ordering::SeqCst);
203
204 unsafe { CurrentIrqArch::interrupt_enable() };
205 if pending != 0 {
206 for i in 0..MAX_SOFTIRQ_NUM {
207 if pending & (1 << i) == 0 {
208 continue;
209 }
210
211 let table_guard = self.table.read_irqsave();
212 let softirq_func = table_guard[i as usize].clone();
213 drop(table_guard);
214 if softirq_func.is_none() {
215 continue;
216 }
217
218 let prev_count: usize = ProcessManager::current_pcb().preempt_count();
219
220 softirq_func.as_ref().unwrap().run();
221 if unlikely(prev_count != ProcessManager::current_pcb().preempt_count()) {
222 debug!(
223 "entered softirq {:?} with preempt_count {:?},exited with {:?}",
224 i,
225 prev_count,
226 ProcessManager::current_pcb().preempt_count()
227 );
228 unsafe { ProcessManager::current_pcb().set_preempt_count(prev_count) };
229 }
230 }
231 }
232 unsafe { CurrentIrqArch::interrupt_disable() };
233 max_restart -= 1;
234 compiler_fence(Ordering::SeqCst);
235 if cpu_pending(cpu_id).is_empty() {
236 compiler_fence(Ordering::SeqCst);
237 if clock() < end && max_restart > 0 {
238 continue;
239 } else {
240 break;
241 }
242 } else {
243 // TODO:当有softirqd时 唤醒它
244 break;
245 }
246 }
247 }
248
raise_softirq(&self, softirq_num: SoftirqNumber)249 pub fn raise_softirq(&self, softirq_num: SoftirqNumber) {
250 let guard = unsafe { CurrentIrqArch::save_and_disable_irq() };
251 let processor_id = smp_get_processor_id();
252
253 cpu_pending(processor_id).insert(VecStatus::from(softirq_num));
254
255 compiler_fence(Ordering::SeqCst);
256
257 drop(guard);
258 // debug!("raise_softirq exited");
259 }
260
261 #[allow(dead_code)]
clear_softirq_pending(&self, softirq_num: SoftirqNumber)262 pub unsafe fn clear_softirq_pending(&self, softirq_num: SoftirqNumber) {
263 compiler_fence(Ordering::SeqCst);
264 cpu_pending(smp_get_processor_id()).remove(VecStatus::from(softirq_num));
265 compiler_fence(Ordering::SeqCst);
266 }
267 }
268
269 /// 当前CPU的软中断嵌套层数的计数器守卫
270 ///
271 /// 当进入作用域时,会自动将cpu_running_count加1,
272 /// 当退出作用域时,会自动将cpu_running_count减1
273 struct RunningCountGuard<'a> {
274 cpu_running_count: &'a PerCpuVar<AtomicI16>,
275 }
276
277 impl<'a> RunningCountGuard<'a> {
new(cpu_running_count: &'a PerCpuVar<AtomicI16>) -> RunningCountGuard<'a>278 fn new(cpu_running_count: &'a PerCpuVar<AtomicI16>) -> RunningCountGuard<'a> {
279 cpu_running_count.get().fetch_add(1, Ordering::SeqCst);
280 return RunningCountGuard { cpu_running_count };
281 }
282 }
283
284 impl Drop for RunningCountGuard<'_> {
drop(&mut self)285 fn drop(&mut self) {
286 self.cpu_running_count.get().fetch_sub(1, Ordering::SeqCst);
287 }
288 }
289
290 #[inline(never)]
do_softirq()291 pub fn do_softirq() {
292 fence(Ordering::SeqCst);
293 IrqTime::irqtime_start();
294 softirq_vectors().do_softirq();
295 IrqTime::irqtime_account_irq(ProcessManager::current_pcb());
296 fence(Ordering::SeqCst);
297 }
298