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