softirq.rs 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268
  1. use core::{ffi::c_void, ptr::null_mut};
  2. use alloc::boxed::Box;
  3. use crate::{
  4. arch::interrupt::{cli, sti},
  5. include::bindings::bindings::verify_area,
  6. kBUG,
  7. libs::spinlock::RawSpinlock,
  8. syscall::SystemError, kdebug,
  9. };
  10. const MAX_SOFTIRQ_NUM: u64 = 64;
  11. const MAX_LOCK_TRIAL_TIME: u64 = 50;
  12. pub static mut SOFTIRQ_HANDLER_PTR: *mut Softirq = null_mut();
  13. /// 软中断向量号码
  14. #[allow(dead_code)]
  15. #[repr(u8)]
  16. pub enum SoftirqNumber {
  17. TIMER = 0, //时钟软中断信号
  18. VideoRefresh = 1, //帧缓冲区刷新软中断
  19. }
  20. #[repr(C)]
  21. #[derive(Clone, Copy)]
  22. pub struct SoftirqVector {
  23. pub action: Option<unsafe extern "C" fn(data: *mut ::core::ffi::c_void)>, //软中断处理函数
  24. pub data: *mut c_void,
  25. }
  26. impl Default for SoftirqVector {
  27. fn default() -> Self {
  28. Self {
  29. action: None,
  30. data: null_mut(),
  31. }
  32. }
  33. }
  34. pub struct Softirq {
  35. modify_lock: RawSpinlock,
  36. pending: u64,
  37. running: u64,
  38. table: [SoftirqVector; MAX_SOFTIRQ_NUM as usize],
  39. }
  40. #[no_mangle]
  41. #[allow(dead_code)]
  42. /// @brief 提供给c的接口函数,用于初始化静态指针
  43. pub extern "C" fn softirq_init() {
  44. if unsafe { SOFTIRQ_HANDLER_PTR.is_null() } {
  45. unsafe {
  46. SOFTIRQ_HANDLER_PTR = Box::leak(Box::new(Softirq::default()));
  47. }
  48. } else {
  49. kBUG!("Try to init SOFTIRQ_HANDLER_PTR twice.");
  50. panic!("Try to init SOFTIRQ_HANDLER_PTR twice.");
  51. }
  52. }
  53. /// @brief 将raw pointer转换为指针,减少unsafe块
  54. #[inline]
  55. pub fn __get_softirq_handler_mut() -> &'static mut Softirq {
  56. return unsafe { SOFTIRQ_HANDLER_PTR.as_mut().unwrap() };
  57. }
  58. #[no_mangle]
  59. #[allow(dead_code)]
  60. pub extern "C" fn raise_softirq(sirq_num: u32) {
  61. let softirq_handler = __get_softirq_handler_mut();
  62. softirq_handler.set_softirq_pending(sirq_num);
  63. }
  64. /// @brief 软中断注册函数
  65. ///
  66. /// @param irq_num 软中断号
  67. /// @param action 响应函数
  68. /// @param data 响应数据结构体
  69. #[no_mangle]
  70. #[allow(dead_code)]
  71. pub extern "C" fn register_softirq(
  72. irq_num: u32,
  73. action: Option<unsafe extern "C" fn(data: *mut ::core::ffi::c_void)>,
  74. data: *mut c_void,
  75. ) {
  76. let softirq_handler = __get_softirq_handler_mut();
  77. softirq_handler.register_softirq(irq_num, action, data).expect(&format!("Softirq: Failed to register {}", irq_num));
  78. }
  79. /// @brief 卸载软中断
  80. /// @param irq_num 软中断号
  81. #[no_mangle]
  82. #[allow(dead_code)]
  83. pub extern "C" fn unregister_softirq(irq_num: u32) {
  84. let softirq_handler = __get_softirq_handler_mut();
  85. softirq_handler.unregister_softirq(irq_num).expect(&format!("Softirq: Failed to unregister {}", irq_num));
  86. }
  87. /// 设置软中断的运行状态(只应在do_softirq中调用此宏)
  88. #[no_mangle]
  89. #[allow(dead_code)]
  90. pub extern "C" fn set_softirq_pending(irq_num: u32) {
  91. let softirq_handler = __get_softirq_handler_mut();
  92. softirq_handler.set_softirq_pending(irq_num);
  93. }
  94. /// @brief 设置软中断运行结束
  95. ///
  96. /// @param softirq_num
  97. #[no_mangle]
  98. #[allow(dead_code)]
  99. pub extern "C" fn clear_softirq_pending(irq_num: u32) {
  100. let softirq_handler = __get_softirq_handler_mut();
  101. softirq_handler.clear_softirq_pending(irq_num);
  102. }
  103. /// @brief 软中断处理程序
  104. #[no_mangle]
  105. #[allow(dead_code)]
  106. pub extern "C" fn do_softirq() {
  107. let softirq_handler = __get_softirq_handler_mut();
  108. softirq_handler.do_softirq();
  109. }
  110. impl Default for Softirq {
  111. fn default() -> Self {
  112. Self {
  113. modify_lock: RawSpinlock::INIT,
  114. pending: (0),
  115. running: (0),
  116. table: [Default::default(); MAX_SOFTIRQ_NUM as usize],
  117. }
  118. }
  119. }
  120. impl Softirq {
  121. #[inline]
  122. #[allow(dead_code)]
  123. pub fn get_softirq_pending(&self) -> u64 {
  124. return self.pending;
  125. }
  126. #[inline]
  127. #[allow(dead_code)]
  128. pub fn get_softirq_running(&self) -> u64 {
  129. return self.running;
  130. }
  131. #[inline]
  132. pub fn set_softirq_pending(&mut self, softirq_num: u32) {
  133. self.pending |= 1 << softirq_num;
  134. }
  135. #[inline]
  136. pub fn set_softirq_running(&mut self, softirq_num: u32) {
  137. self.running |= 1 << softirq_num;
  138. }
  139. #[inline]
  140. pub fn clear_softirq_running(&mut self, softirq_num: u32) {
  141. self.running &= !(1 << softirq_num);
  142. }
  143. /// @brief 清除软中断pending标志位
  144. #[inline]
  145. pub fn clear_softirq_pending(&mut self, softirq_num: u32) {
  146. self.pending &= !(1 << softirq_num);
  147. }
  148. /// @brief 判断对应running标志位是否为0
  149. /// @return true: 标志位为1; false: 标志位为0
  150. #[inline]
  151. pub fn is_running(&mut self, softirq_num: u32) -> bool {
  152. return (self.running & (1 << softirq_num)).ne(&0);
  153. }
  154. /// @brief 判断对应pending标志位是否为0
  155. /// @return true: 标志位为1; false: 标志位为0
  156. #[inline]
  157. pub fn is_pending(&mut self, softirq_num: u32) -> bool {
  158. return (self.pending & (1 << softirq_num)).ne(&0);
  159. }
  160. /// @brief 注册软中断向量
  161. /// @param irq_num 中断向量号码
  162. /// @param action 中断函数的入口地址
  163. /// @param data 中断函数的操作数据
  164. pub fn register_softirq(
  165. &mut self,
  166. irq_num: u32,
  167. action: Option<unsafe extern "C" fn(data: *mut ::core::ffi::c_void)>,
  168. data: *mut c_void,
  169. ) -> Result<(), SystemError> {
  170. if self.table[irq_num as usize].action.is_some() {
  171. return Err(SystemError::EEXIST);
  172. }
  173. if unsafe { verify_area(action.unwrap() as u64, 1) } {
  174. return Err(SystemError::EPERM);
  175. }
  176. self.modify_lock.lock();
  177. self.table[irq_num as usize].action = action;
  178. self.table[irq_num as usize].data = data;
  179. self.modify_lock.unlock();
  180. return Ok(());
  181. }
  182. /// @brief 解注册软中断向量
  183. /// @param irq_num 中断向量号码
  184. pub fn unregister_softirq(&mut self, irq_num: u32) -> Result<(), SystemError> {
  185. for _trial_time in 0..MAX_LOCK_TRIAL_TIME {
  186. if self.is_running(irq_num) {
  187. continue; //running标志位为1
  188. }
  189. if self.modify_lock.try_lock() {
  190. if self.is_running(irq_num) {
  191. self.modify_lock.unlock();
  192. continue;
  193. }
  194. break;
  195. }
  196. }
  197. // 存在尝试加锁规定次数后仍加锁失败的情况,报告错误并退出
  198. if !self.modify_lock.is_locked() {
  199. return Err(SystemError::EBUSY);
  200. }
  201. kdebug!("SOftirq: unregister {irq_num}");
  202. self.clear_softirq_running(irq_num);
  203. self.clear_softirq_pending(irq_num);
  204. self.table[irq_num as usize].action = None;
  205. self.table[irq_num as usize].data = null_mut();
  206. self.modify_lock.unlock();
  207. return Ok(());
  208. }
  209. /// @brief 遍历执行软中断
  210. pub fn do_softirq(&mut self) {
  211. sti();
  212. let mut softirq_index: u32 = 0; //软中断向量号码
  213. while (softirq_index as u64) < MAX_SOFTIRQ_NUM && self.pending != 0 {
  214. if self.is_pending(softirq_index)
  215. && self.table[softirq_index as usize].action.is_some()
  216. && !self.is_running(softirq_index)
  217. {
  218. if self.modify_lock.try_lock() {
  219. if self.is_running(softirq_index)
  220. || self.table[softirq_index as usize].action.is_none()
  221. {
  222. self.modify_lock.unlock();
  223. continue;
  224. }
  225. self.clear_softirq_pending(softirq_index);
  226. self.set_softirq_running(softirq_index);
  227. self.modify_lock.unlock();
  228. unsafe {
  229. (self.table[softirq_index as usize].action.unwrap())(
  230. self.table[softirq_index as usize].data,
  231. );
  232. }
  233. self.clear_softirq_running(softirq_index);
  234. }
  235. }
  236. softirq_index += 1;
  237. }
  238. cli();
  239. }
  240. }