1# 软中断 2 3  软件中断,也可以被称为中断的下半部,用于延迟处理硬中断(中断上半部)未完成的工作。将中断分为两个阶段可以有效解决中断处理时间过长和中断丢失的问题。 4 5## 1. 设计思路 6 7  每个cpu都有自己的pending,软中断是“哪个cpu发起,就哪个cpu执行”,每个cpu的pending不共享。同一个软中断向量可以在多核上同时运行。 8 9  当我们需要注册一个新的软中断时,需要为软中断处理程序实现`SoftirqVec`特征,然后调用`register_softirq`函数,将软中断处理程序注册到软中断机制内。 10 11  请注意,由于软中断的可重入、可并发性,所以软中断处理程序需要自己保证线程安全。 12 13## 2. 软中断向量号 14 15```rust 16pub enum SoftirqNumber { 17 /// 时钟软中断信号 18 TIMER = 0, 19 /// 帧缓冲区刷新软中断 20 VideoRefresh = 1, 21} 22``` 23 24## 3. 软中断API 25 26### 3.1. SoftirqVec特征 27 28```rust 29pub trait SoftirqVec: Send + Sync + Debug { 30 fn run(&self); 31} 32``` 33 34  软中断处理程序需要实现的特征,需要实现`run`函数,用于处理软中断。当软中断被执行时,会调用`run`函数。 35 36### 3.2. Softirq的API 37 38#### 3.2.1. 注册软中断向量 39```rust 40pub fn register_softirq(&self, 41 softirq_num: SoftirqNumber, 42 handler: Arc<dyn SoftirqVec>, 43 ) -> Result<i32, SystemError> 44``` 45 46- 参数: 47 48 - softirq_num:中断向量号 49 50 - hanlder:中断函数对应的结构体,需要指向实现了`SoftirqVec`特征的结构体变量 51 52- 返回: 53 54 - Ok(i32):0 55 56 - Err(SystemError):错误码 57 58#### 3.2.2. 解注册软中断向量 59 60```rust 61pub fn unregister_softirq(&self, softirq_num: SoftirqNumber) 62``` 63 64- 参数: 65 66 - softirq_num:中断向量号 67 68 69#### 3.2.3. 软中断执行 70 71```rust 72pub fn do_softirq(&self) 73``` 74 75- 作用:执行软中断函数(**只在硬中断执行后调用**) 76 77#### 3.2.4. 清除软中断的pending标志 78 79```rust 80pub unsafe fn clear_softirq_pending(&self, softirq_num: SoftirqNumber) 81``` 82 83- 作用:清除当前CPU上,指定软中断的pending标志。请注意,这个函数是unsafe的,因为它会直接修改pending标志,而没有加锁。 84 85- 参数: 86 87 - softirq_num:中断向量号 88 89#### 3.2.5. 标志软中断需要执行 90 91```rust 92pub fn raise_softirq(&self, softirq_num: SoftirqNumber) 93``` 94 95- 作用:标志当前CPU上,指定的软中断需要执行 96 97- 参数: 98 99 - softirq_num:中断向量号 100 101### 3.3. 使用实例 102 103```rust 104#[derive(Debug)] 105/// SoftirqExample中断结构体 106pub struct SoftirqExample { 107 running: AtomicBool, 108} 109/// SoftirqExample中断需要处理的逻辑 110fn softirq_example_func() { 111 println!("addressed SoftirqExample"); 112} 113impl SoftirqVec for SoftirqExample { 114 fn run(&self) { 115 if self.set_run() == false { 116 return; 117 } 118 119 softirq_example_func(); 120 121 self.clear_run(); 122 } 123} 124impl SoftirqExample { 125 pub fn new() -> SoftirqExample { 126 SoftirqExample { 127 running: AtomicBool::new(false), 128 } 129 } 130 131 fn set_run(&self) -> bool { 132 let x = self 133 .running 134 .compare_exchange(false, true, Ordering::Acquire, Ordering::Relaxed); 135 if x.is_ok() { 136 return true; 137 } else { 138 return false; 139 } 140 } 141 142 fn clear_run(&self) { 143 self.running.store(false, Ordering::Release); 144 } 145} 146fn main() { 147 let softirq_example = Arc::new(SoftirqExample::new()); 148 let softirq_num = 2; 149 // 注册SoftirqExample中断 150 softirq_vectors() 151 .register_softirq(SoftirqNumber::from(softirq_num as u64), softirq_example) 152 .expect("failed to register SoftirqExample"); 153 154 // 标志SoftirqExample中断需要执行 155 softirq_vectors().raise_softirq(SoftirqNumber::from(softirq_num as u64)); 156 157 // 标志SoftirqExample中断不需要执行 158 softirq_vectors().clear_softirq_pending(SoftirqNumber::from(softirq_num as u64)); 159 160 // 解注册SoftirqExample中断 161 softirq_vectors().unregister_softirq(SoftirqNumber::from(softirq_num as u64)); 162} 163``` 164 165### 3.4. 为C提供的接口 166 167```c 168extern void rs_softirq_init(); 169extern void rs_raise_softirq(uint32_t sirq_num); 170extern void rs_unregister_softirq(uint32_t sirq_num); 171extern void rs_do_softirq(); 172extern void rs_clear_softirq_pending(uint32_t softirq_num); 173``` 174