softirq.rs 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266
  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. use alloc::{boxed::Box, sync::Arc};
  9. use num_traits::FromPrimitive;
  10. use crate::{
  11. arch::CurrentIrqArch,
  12. arch::{
  13. asm::current::current_pcb,
  14. interrupt::{cli, sti},
  15. },
  16. exception::InterruptArch,
  17. include::bindings::bindings::MAX_CPU_NUM,
  18. kdebug, kinfo,
  19. libs::rwlock::RwLock,
  20. smp::core::smp_get_processor_id,
  21. syscall::SystemError,
  22. time::timer::clock,
  23. };
  24. const MAX_SOFTIRQ_NUM: u64 = 64;
  25. const MAX_SOFTIRQ_RESTART: i32 = 20;
  26. static mut __CPU_PENDING: Option<Box<[VecStatus; MAX_CPU_NUM as usize]>> = None;
  27. static mut __SORTIRQ_VECTORS: *mut Softirq = null_mut();
  28. #[no_mangle]
  29. pub extern "C" fn rs_softirq_init() {
  30. softirq_init().expect("softirq_init failed");
  31. }
  32. pub fn softirq_init() -> Result<(), SystemError> {
  33. kinfo!("Initializing softirq...");
  34. unsafe {
  35. __SORTIRQ_VECTORS = Box::leak(Box::new(Softirq::new()));
  36. __CPU_PENDING = Some(Box::new([VecStatus::default(); MAX_CPU_NUM as usize]));
  37. let cpu_pending = __CPU_PENDING.as_mut().unwrap();
  38. for i in 0..MAX_CPU_NUM {
  39. cpu_pending[i as usize] = VecStatus::default();
  40. }
  41. }
  42. kinfo!("Softirq initialized.");
  43. return Ok(());
  44. }
  45. #[inline(always)]
  46. pub fn softirq_vectors() -> &'static mut Softirq {
  47. unsafe {
  48. return __SORTIRQ_VECTORS.as_mut().unwrap();
  49. }
  50. }
  51. #[inline(always)]
  52. fn cpu_pending(cpu_id: usize) -> &'static mut VecStatus {
  53. unsafe {
  54. return &mut __CPU_PENDING.as_mut().unwrap()[cpu_id];
  55. }
  56. }
  57. /// 软中断向量号码
  58. #[allow(dead_code)]
  59. #[repr(u8)]
  60. #[derive(FromPrimitive, Copy, Clone, Debug, PartialEq, Eq)]
  61. pub enum SoftirqNumber {
  62. /// 时钟软中断信号
  63. TIMER = 0,
  64. VideoRefresh = 1, //帧缓冲区刷新软中断
  65. }
  66. impl From<u64> for SoftirqNumber {
  67. fn from(value: u64) -> Self {
  68. return <Self as FromPrimitive>::from_u64(value).unwrap();
  69. }
  70. }
  71. bitflags! {
  72. #[derive(Default)]
  73. pub struct VecStatus: u64 {
  74. const TIMER = 1 << 0;
  75. const VIDEO_REFRESH = 1 << 1;
  76. }
  77. }
  78. impl From<SoftirqNumber> for VecStatus {
  79. fn from(value: SoftirqNumber) -> Self {
  80. return Self::from_bits_truncate(1 << (value as u64));
  81. }
  82. }
  83. pub trait SoftirqVec: Send + Sync + Debug {
  84. fn run(&self);
  85. }
  86. #[derive(Debug)]
  87. pub struct Softirq {
  88. table: RwLock<[Option<Arc<dyn SoftirqVec>>; MAX_SOFTIRQ_NUM as usize]>,
  89. }
  90. impl Softirq {
  91. fn new() -> Softirq {
  92. let mut data: [MaybeUninit<Option<Arc<dyn SoftirqVec>>>; MAX_SOFTIRQ_NUM as usize] =
  93. unsafe { MaybeUninit::uninit().assume_init() };
  94. for i in 0..MAX_SOFTIRQ_NUM {
  95. data[i as usize] = MaybeUninit::new(None);
  96. }
  97. let data: [Option<Arc<dyn SoftirqVec>>; MAX_SOFTIRQ_NUM as usize] = unsafe {
  98. mem::transmute::<_, [Option<Arc<dyn SoftirqVec>>; MAX_SOFTIRQ_NUM as usize]>(data)
  99. };
  100. return Softirq {
  101. table: RwLock::new(data),
  102. };
  103. }
  104. /// @brief 注册软中断向量
  105. ///
  106. /// @param softirq_num 中断向量号
  107. ///
  108. /// @param hanlder 中断函数对应的结构体
  109. pub fn register_softirq(
  110. &self,
  111. softirq_num: SoftirqNumber,
  112. handler: Arc<dyn SoftirqVec>,
  113. ) -> Result<i32, SystemError> {
  114. // kdebug!("register_softirq softirq_num = {:?}", softirq_num as u64);
  115. // let self = &mut SOFTIRQ_VECTORS.lock();
  116. // 判断该软中断向量是否已经被注册
  117. let mut table_guard = self.table.write();
  118. if table_guard[softirq_num as usize].is_some() {
  119. // kdebug!("register_softirq failed");
  120. return Err(SystemError::EINVAL);
  121. }
  122. table_guard[softirq_num as usize] = Some(handler);
  123. drop(table_guard);
  124. // kdebug!(
  125. // "register_softirq successfully, softirq_num = {:?}",
  126. // softirq_num as u64
  127. // );
  128. compiler_fence(Ordering::SeqCst);
  129. return Ok(0);
  130. }
  131. /// @brief 解注册软中断向量
  132. ///
  133. /// @param irq_num 中断向量号码
  134. pub fn unregister_softirq(&self, softirq_num: SoftirqNumber) {
  135. // kdebug!("unregister_softirq softirq_num = {:?}", softirq_num as u64);
  136. let table_guard = &mut self.table.write();
  137. // 将软中断向量清空
  138. table_guard[softirq_num as usize] = None;
  139. drop(table_guard);
  140. // 将对应位置的pending和runing都置0
  141. // self.running.lock().set(VecStatus::from(softirq_num), false);
  142. // 将对应CPU的pending置0
  143. compiler_fence(Ordering::SeqCst);
  144. cpu_pending(smp_get_processor_id() as usize).set(VecStatus::from(softirq_num), false);
  145. compiler_fence(Ordering::SeqCst);
  146. }
  147. pub fn do_softirq(&self) {
  148. // TODO pcb的flags未修改
  149. // todo: 是否需要判断在当前cpu上面,该函数的嵌套层数?(防止爆栈)
  150. let end = clock() + 500 * 2;
  151. let cpu_id = smp_get_processor_id();
  152. let mut max_restart = MAX_SOFTIRQ_RESTART;
  153. loop {
  154. compiler_fence(Ordering::SeqCst);
  155. let pending = cpu_pending(cpu_id as usize).bits;
  156. cpu_pending(cpu_id as usize).bits = 0;
  157. compiler_fence(Ordering::SeqCst);
  158. sti();
  159. if pending != 0 {
  160. for i in 0..MAX_SOFTIRQ_NUM {
  161. if pending & (1 << i) == 0 {
  162. continue;
  163. }
  164. let table_guard = self.table.read();
  165. let softirq_func = table_guard[i as usize].clone();
  166. drop(table_guard);
  167. if softirq_func.is_none() {
  168. continue;
  169. }
  170. let prev_count = current_pcb().preempt_count;
  171. softirq_func.as_ref().unwrap().run();
  172. if unlikely(prev_count != current_pcb().preempt_count) {
  173. kdebug!(
  174. "entered softirq {:?} with preempt_count {:?},exited with {:?}",
  175. i,
  176. prev_count,
  177. current_pcb().preempt_count
  178. );
  179. current_pcb().preempt_count = prev_count;
  180. }
  181. }
  182. }
  183. cli();
  184. max_restart -= 1;
  185. compiler_fence(Ordering::SeqCst);
  186. if cpu_pending(cpu_id as usize).is_empty() {
  187. compiler_fence(Ordering::SeqCst);
  188. if clock() < end && max_restart > 0 {
  189. continue;
  190. } else {
  191. break;
  192. }
  193. } else {
  194. // TODO:当有softirqd时 唤醒它
  195. break;
  196. }
  197. }
  198. }
  199. pub fn raise_softirq(&self, softirq_num: SoftirqNumber) {
  200. let guard = unsafe { CurrentIrqArch::save_and_disable_irq() };
  201. let processor_id = smp_get_processor_id() as usize;
  202. cpu_pending(processor_id).insert(VecStatus::from(softirq_num));
  203. compiler_fence(Ordering::SeqCst);
  204. drop(guard);
  205. // kdebug!("raise_softirq exited");
  206. }
  207. pub unsafe fn clear_softirq_pending(&self, softirq_num: SoftirqNumber) {
  208. compiler_fence(Ordering::SeqCst);
  209. cpu_pending(smp_get_processor_id() as usize).remove(VecStatus::from(softirq_num));
  210. compiler_fence(Ordering::SeqCst);
  211. }
  212. }
  213. // ======= 以下为给C提供的接口 =======
  214. #[no_mangle]
  215. pub extern "C" fn rs_raise_softirq(softirq_num: u32) {
  216. softirq_vectors().raise_softirq(SoftirqNumber::from(softirq_num as u64));
  217. }
  218. #[no_mangle]
  219. pub extern "C" fn rs_unregister_softirq(softirq_num: u32) {
  220. softirq_vectors().unregister_softirq(SoftirqNumber::from(softirq_num as u64));
  221. }
  222. #[no_mangle]
  223. pub extern "C" fn rs_do_softirq() {
  224. softirq_vectors().do_softirq();
  225. }
  226. #[no_mangle]
  227. pub extern "C" fn rs_clear_softirq_pending(softirq_num: u32) {
  228. unsafe {
  229. softirq_vectors().clear_softirq_pending(SoftirqNumber::from(softirq_num as u64));
  230. }
  231. }