1bacd691cSlogin use core::{
2bacd691cSlogin fmt::Debug,
3bacd691cSlogin intrinsics::unlikely,
4bacd691cSlogin mem::{self, MaybeUninit},
5bacd691cSlogin ptr::null_mut,
6f0c87a89SGnoCiYeH sync::atomic::{compiler_fence, fence, AtomicI16, Ordering},
7bacd691cSlogin };
862e46139SGou Ngai
90d6cf65aSLoGin use alloc::{boxed::Box, sync::Arc, vec::Vec};
10*2eab6dd7S曾俊 use log::{debug, info};
11bacd691cSlogin use num_traits::FromPrimitive;
1291e9d4abSLoGin use system_error::SystemError;
1362e46139SGou Ngai
1462e46139SGou Ngai use crate::{
150d6cf65aSLoGin arch::CurrentIrqArch,
160d6cf65aSLoGin exception::InterruptArch,
170d6cf65aSLoGin libs::rwlock::RwLock,
180d6cf65aSLoGin mm::percpu::{PerCpu, PerCpuVar},
190d6cf65aSLoGin process::ProcessManager,
20f0c87a89SGnoCiYeH sched::cputime::IrqTime,
21e2841179SLoGin smp::{core::smp_get_processor_id, cpu::ProcessorId},
2291e9d4abSLoGin time::timer::clock,
2362e46139SGou Ngai };
2462e46139SGou Ngai
2562e46139SGou Ngai const MAX_SOFTIRQ_NUM: u64 = 64;
26bacd691cSlogin const MAX_SOFTIRQ_RESTART: i32 = 20;
27bacd691cSlogin
28e2841179SLoGin static mut __CPU_PENDING: Option<Box<[VecStatus; PerCpu::MAX_CPU_NUM as usize]>> = None;
29bacd691cSlogin static mut __SORTIRQ_VECTORS: *mut Softirq = null_mut();
30bacd691cSlogin
31bacd691cSlogin #[no_mangle]
rs_softirq_init()32bacd691cSlogin pub extern "C" fn rs_softirq_init() {
33bacd691cSlogin softirq_init().expect("softirq_init failed");
34bacd691cSlogin }
35bacd691cSlogin
365b59005fSLoGin #[inline(never)]
softirq_init() -> Result<(), SystemError>37bacd691cSlogin pub fn softirq_init() -> Result<(), SystemError> {
38*2eab6dd7S曾俊 info!("Initializing softirq...");
39bacd691cSlogin unsafe {
40bacd691cSlogin __SORTIRQ_VECTORS = Box::leak(Box::new(Softirq::new()));
4146e234aeSLoGin __CPU_PENDING = Some(Box::new(
4246e234aeSLoGin [VecStatus::default(); PerCpu::MAX_CPU_NUM as usize],
4346e234aeSLoGin ));
44bacd691cSlogin let cpu_pending = __CPU_PENDING.as_mut().unwrap();
4546e234aeSLoGin for i in 0..PerCpu::MAX_CPU_NUM {
46bacd691cSlogin cpu_pending[i as usize] = VecStatus::default();
47bacd691cSlogin }
48bacd691cSlogin }
49*2eab6dd7S曾俊 info!("Softirq initialized.");
50bacd691cSlogin return Ok(());
51bacd691cSlogin }
52bacd691cSlogin
53bacd691cSlogin #[inline(always)]
softirq_vectors() -> &'static mut Softirq54bacd691cSlogin pub fn softirq_vectors() -> &'static mut Softirq {
55bacd691cSlogin unsafe {
56bacd691cSlogin return __SORTIRQ_VECTORS.as_mut().unwrap();
57bacd691cSlogin }
58bacd691cSlogin }
59bacd691cSlogin
60bacd691cSlogin #[inline(always)]
cpu_pending(cpu_id: ProcessorId) -> &'static mut VecStatus61e2841179SLoGin fn cpu_pending(cpu_id: ProcessorId) -> &'static mut VecStatus {
62bacd691cSlogin unsafe {
63e2841179SLoGin return &mut __CPU_PENDING.as_mut().unwrap()[cpu_id.data() as usize];
64bacd691cSlogin }
65bacd691cSlogin }
6662e46139SGou Ngai
6762e46139SGou Ngai /// 软中断向量号码
6862e46139SGou Ngai #[allow(dead_code)]
6962e46139SGou Ngai #[repr(u8)]
70bacd691cSlogin #[derive(FromPrimitive, Copy, Clone, Debug, PartialEq, Eq)]
7162e46139SGou Ngai pub enum SoftirqNumber {
72bacd691cSlogin /// 时钟软中断信号
73bacd691cSlogin TIMER = 0,
7462e46139SGou Ngai VideoRefresh = 1, //帧缓冲区刷新软中断
7562e46139SGou Ngai }
7662e46139SGou Ngai
77bacd691cSlogin impl From<u64> for SoftirqNumber {
from(value: u64) -> Self78bacd691cSlogin fn from(value: u64) -> Self {
79bacd691cSlogin return <Self as FromPrimitive>::from_u64(value).unwrap();
8062e46139SGou Ngai }
8162e46139SGou Ngai }
8262e46139SGou Ngai
83bacd691cSlogin bitflags! {
84bacd691cSlogin #[derive(Default)]
85bacd691cSlogin pub struct VecStatus: u64 {
86bacd691cSlogin const TIMER = 1 << 0;
87bacd691cSlogin const VIDEO_REFRESH = 1 << 1;
88bacd691cSlogin }
89bacd691cSlogin }
90bacd691cSlogin
91bacd691cSlogin impl From<SoftirqNumber> for VecStatus {
from(value: SoftirqNumber) -> Self92bacd691cSlogin fn from(value: SoftirqNumber) -> Self {
93bacd691cSlogin return Self::from_bits_truncate(1 << (value as u64));
94bacd691cSlogin }
95bacd691cSlogin }
96bacd691cSlogin
97bacd691cSlogin pub trait SoftirqVec: Send + Sync + Debug {
run(&self)98bacd691cSlogin fn run(&self);
99bacd691cSlogin }
100bacd691cSlogin
101bacd691cSlogin #[derive(Debug)]
10262e46139SGou Ngai pub struct Softirq {
103bacd691cSlogin table: RwLock<[Option<Arc<dyn SoftirqVec>>; MAX_SOFTIRQ_NUM as usize]>,
1040d6cf65aSLoGin /// 软中断嵌套层数(per cpu)
1050d6cf65aSLoGin cpu_running_count: PerCpuVar<AtomicI16>,
10662e46139SGou Ngai }
10762e46139SGou Ngai impl Softirq {
1080d6cf65aSLoGin /// 每个CPU最大嵌套的软中断数量
1090d6cf65aSLoGin const MAX_RUNNING_PER_CPU: i16 = 3;
new() -> Softirq110bacd691cSlogin fn new() -> Softirq {
111bacd691cSlogin let mut data: [MaybeUninit<Option<Arc<dyn SoftirqVec>>>; MAX_SOFTIRQ_NUM as usize] =
112bacd691cSlogin unsafe { MaybeUninit::uninit().assume_init() };
113bacd691cSlogin
114bacd691cSlogin for i in 0..MAX_SOFTIRQ_NUM {
115bacd691cSlogin data[i as usize] = MaybeUninit::new(None);
11662e46139SGou Ngai }
11762e46139SGou Ngai
118bacd691cSlogin let data: [Option<Arc<dyn SoftirqVec>>; MAX_SOFTIRQ_NUM as usize] = unsafe {
119bacd691cSlogin mem::transmute::<_, [Option<Arc<dyn SoftirqVec>>; MAX_SOFTIRQ_NUM as usize]>(data)
120bacd691cSlogin };
12162e46139SGou Ngai
1220d6cf65aSLoGin let mut percpu_count = Vec::with_capacity(PerCpu::MAX_CPU_NUM as usize);
1230d6cf65aSLoGin percpu_count.resize_with(PerCpu::MAX_CPU_NUM as usize, || AtomicI16::new(0));
1240d6cf65aSLoGin let cpu_running_count = PerCpuVar::new(percpu_count).unwrap();
1250d6cf65aSLoGin
126bacd691cSlogin return Softirq {
127bacd691cSlogin table: RwLock::new(data),
1280d6cf65aSLoGin cpu_running_count,
129bacd691cSlogin };
13062e46139SGou Ngai }
13162e46139SGou Ngai
cpu_running_count(&self) -> &PerCpuVar<AtomicI16>1320d6cf65aSLoGin fn cpu_running_count(&self) -> &PerCpuVar<AtomicI16> {
1330d6cf65aSLoGin return &self.cpu_running_count;
1340d6cf65aSLoGin }
1350d6cf65aSLoGin
13662e46139SGou Ngai /// @brief 注册软中断向量
137bacd691cSlogin ///
138bacd691cSlogin /// @param softirq_num 中断向量号
139bacd691cSlogin ///
140bacd691cSlogin /// @param hanlder 中断函数对应的结构体
register_softirq( &self, softirq_num: SoftirqNumber, handler: Arc<dyn SoftirqVec>, ) -> Result<i32, SystemError>14162e46139SGou Ngai pub fn register_softirq(
142bacd691cSlogin &self,
143bacd691cSlogin softirq_num: SoftirqNumber,
144bacd691cSlogin handler: Arc<dyn SoftirqVec>,
145bacd691cSlogin ) -> Result<i32, SystemError> {
146*2eab6dd7S曾俊 // debug!("register_softirq softirq_num = {:?}", softirq_num as u64);
14762e46139SGou Ngai
148bacd691cSlogin // let self = &mut SOFTIRQ_VECTORS.lock();
149bacd691cSlogin // 判断该软中断向量是否已经被注册
1500d6cf65aSLoGin let mut table_guard = self.table.write_irqsave();
151bacd691cSlogin if table_guard[softirq_num as usize].is_some() {
152*2eab6dd7S曾俊 // debug!("register_softirq failed");
153bacd691cSlogin
154bacd691cSlogin return Err(SystemError::EINVAL);
15562e46139SGou Ngai }
156bacd691cSlogin table_guard[softirq_num as usize] = Some(handler);
157bacd691cSlogin drop(table_guard);
158bacd691cSlogin
159*2eab6dd7S曾俊 // debug!(
160bacd691cSlogin // "register_softirq successfully, softirq_num = {:?}",
161bacd691cSlogin // softirq_num as u64
162bacd691cSlogin // );
163bacd691cSlogin compiler_fence(Ordering::SeqCst);
164bacd691cSlogin return Ok(0);
16562e46139SGou Ngai }
16662e46139SGou Ngai
16762e46139SGou Ngai /// @brief 解注册软中断向量
168bacd691cSlogin ///
16962e46139SGou Ngai /// @param irq_num 中断向量号码
170e2841179SLoGin #[allow(dead_code)]
unregister_softirq(&self, softirq_num: SoftirqNumber)171bacd691cSlogin pub fn unregister_softirq(&self, softirq_num: SoftirqNumber) {
172*2eab6dd7S曾俊 // debug!("unregister_softirq softirq_num = {:?}", softirq_num as u64);
1730d6cf65aSLoGin let mut table_guard = self.table.write_irqsave();
174bacd691cSlogin // 将软中断向量清空
175bacd691cSlogin table_guard[softirq_num as usize] = None;
176bacd691cSlogin drop(table_guard);
177bacd691cSlogin // 将对应位置的pending和runing都置0
178bacd691cSlogin // self.running.lock().set(VecStatus::from(softirq_num), false);
179bacd691cSlogin // 将对应CPU的pending置0
180bacd691cSlogin compiler_fence(Ordering::SeqCst);
181e2841179SLoGin cpu_pending(smp_get_processor_id()).set(VecStatus::from(softirq_num), false);
182bacd691cSlogin compiler_fence(Ordering::SeqCst);
18362e46139SGou Ngai }
184bacd691cSlogin
185e2841179SLoGin #[inline(never)]
do_softirq(&self)186bacd691cSlogin pub fn do_softirq(&self) {
1870d6cf65aSLoGin if self.cpu_running_count().get().load(Ordering::SeqCst) >= Self::MAX_RUNNING_PER_CPU {
1880d6cf65aSLoGin // 当前CPU的软中断嵌套层数已经达到最大值,不再执行
1890d6cf65aSLoGin return;
1900d6cf65aSLoGin }
1910d6cf65aSLoGin // 创建一个RunningCountGuard,当退出作用域时,会自动将cpu_running_count减1
1920d6cf65aSLoGin let _count_guard = RunningCountGuard::new(self.cpu_running_count());
1930d6cf65aSLoGin
194bacd691cSlogin // TODO pcb的flags未修改
195bacd691cSlogin let end = clock() + 500 * 2;
196bacd691cSlogin let cpu_id = smp_get_processor_id();
197bacd691cSlogin let mut max_restart = MAX_SOFTIRQ_RESTART;
198bacd691cSlogin loop {
199bacd691cSlogin compiler_fence(Ordering::SeqCst);
200e2841179SLoGin let pending = cpu_pending(cpu_id).bits;
201e2841179SLoGin cpu_pending(cpu_id).bits = 0;
202bacd691cSlogin compiler_fence(Ordering::SeqCst);
203bacd691cSlogin
20446e234aeSLoGin unsafe { CurrentIrqArch::interrupt_enable() };
205bacd691cSlogin if pending != 0 {
206bacd691cSlogin for i in 0..MAX_SOFTIRQ_NUM {
207bacd691cSlogin if pending & (1 << i) == 0 {
20862e46139SGou Ngai continue;
20962e46139SGou Ngai }
210bacd691cSlogin
2110d6cf65aSLoGin let table_guard = self.table.read_irqsave();
212bacd691cSlogin let softirq_func = table_guard[i as usize].clone();
213bacd691cSlogin drop(table_guard);
214bacd691cSlogin if softirq_func.is_none() {
215bacd691cSlogin continue;
216bacd691cSlogin }
217bacd691cSlogin
2181496ba7bSLoGin let prev_count: usize = ProcessManager::current_pcb().preempt_count();
219bacd691cSlogin
220bacd691cSlogin softirq_func.as_ref().unwrap().run();
2211496ba7bSLoGin if unlikely(prev_count != ProcessManager::current_pcb().preempt_count()) {
222*2eab6dd7S曾俊 debug!(
223bacd691cSlogin "entered softirq {:?} with preempt_count {:?},exited with {:?}",
224bacd691cSlogin i,
225bacd691cSlogin prev_count,
2261496ba7bSLoGin ProcessManager::current_pcb().preempt_count()
227bacd691cSlogin );
2281496ba7bSLoGin unsafe { ProcessManager::current_pcb().set_preempt_count(prev_count) };
229bacd691cSlogin }
230bacd691cSlogin }
231bacd691cSlogin }
23246e234aeSLoGin unsafe { CurrentIrqArch::interrupt_disable() };
233bacd691cSlogin max_restart -= 1;
234bacd691cSlogin compiler_fence(Ordering::SeqCst);
235e2841179SLoGin if cpu_pending(cpu_id).is_empty() {
236bacd691cSlogin compiler_fence(Ordering::SeqCst);
237bacd691cSlogin if clock() < end && max_restart > 0 {
238bacd691cSlogin continue;
239bacd691cSlogin } else {
240bacd691cSlogin break;
241bacd691cSlogin }
242bacd691cSlogin } else {
243bacd691cSlogin // TODO:当有softirqd时 唤醒它
24462e46139SGou Ngai break;
24562e46139SGou Ngai }
24662e46139SGou Ngai }
24762e46139SGou Ngai }
24862e46139SGou Ngai
raise_softirq(&self, softirq_num: SoftirqNumber)249bacd691cSlogin pub fn raise_softirq(&self, softirq_num: SoftirqNumber) {
2509550910aSChiichen let guard = unsafe { CurrentIrqArch::save_and_disable_irq() };
251e2841179SLoGin let processor_id = smp_get_processor_id();
252bacd691cSlogin
253bacd691cSlogin cpu_pending(processor_id).insert(VecStatus::from(softirq_num));
254bacd691cSlogin
255bacd691cSlogin compiler_fence(Ordering::SeqCst);
256bacd691cSlogin
2579550910aSChiichen drop(guard);
258*2eab6dd7S曾俊 // debug!("raise_softirq exited");
25962e46139SGou Ngai }
260e2841179SLoGin
261e2841179SLoGin #[allow(dead_code)]
clear_softirq_pending(&self, softirq_num: SoftirqNumber)2628fd71f27Shoumkh pub unsafe fn clear_softirq_pending(&self, softirq_num: SoftirqNumber) {
263bacd691cSlogin compiler_fence(Ordering::SeqCst);
264e2841179SLoGin cpu_pending(smp_get_processor_id()).remove(VecStatus::from(softirq_num));
265bacd691cSlogin compiler_fence(Ordering::SeqCst);
26662e46139SGou Ngai }
26762e46139SGou Ngai }
268bacd691cSlogin
2690d6cf65aSLoGin /// 当前CPU的软中断嵌套层数的计数器守卫
2700d6cf65aSLoGin ///
2710d6cf65aSLoGin /// 当进入作用域时,会自动将cpu_running_count加1,
2720d6cf65aSLoGin /// 当退出作用域时,会自动将cpu_running_count减1
2730d6cf65aSLoGin struct RunningCountGuard<'a> {
2740d6cf65aSLoGin cpu_running_count: &'a PerCpuVar<AtomicI16>,
2750d6cf65aSLoGin }
2760d6cf65aSLoGin
2770d6cf65aSLoGin impl<'a> RunningCountGuard<'a> {
new(cpu_running_count: &'a PerCpuVar<AtomicI16>) -> RunningCountGuard2780d6cf65aSLoGin fn new(cpu_running_count: &'a PerCpuVar<AtomicI16>) -> RunningCountGuard {
2790d6cf65aSLoGin cpu_running_count.get().fetch_add(1, Ordering::SeqCst);
2800d6cf65aSLoGin return RunningCountGuard { cpu_running_count };
2810d6cf65aSLoGin }
2820d6cf65aSLoGin }
2830d6cf65aSLoGin
2840d6cf65aSLoGin impl<'a> Drop for RunningCountGuard<'a> {
drop(&mut self)2850d6cf65aSLoGin fn drop(&mut self) {
2860d6cf65aSLoGin self.cpu_running_count.get().fetch_sub(1, Ordering::SeqCst);
2870d6cf65aSLoGin }
2880d6cf65aSLoGin }
2890d6cf65aSLoGin
290f0c87a89SGnoCiYeH #[inline(never)]
do_softirq()291e2841179SLoGin pub fn do_softirq() {
292f0c87a89SGnoCiYeH fence(Ordering::SeqCst);
293f0c87a89SGnoCiYeH IrqTime::irqtime_start();
294bacd691cSlogin softirq_vectors().do_softirq();
295f0c87a89SGnoCiYeH IrqTime::irqtime_account_irq(ProcessManager::current_pcb());
296f0c87a89SGnoCiYeH fence(Ordering::SeqCst);
297bacd691cSlogin }
298