1 #include "softirq.h"
2 #include <common/kprint.h>
3 #include <process/process.h>
4 #include <driver/video/video.h>
5 #include <common/spinlock.h>
6 
7 static spinlock_t softirq_modify_lock; // 软中断状态(status)
8 static volatile uint64_t softirq_pending = 0;
9 static volatile uint64_t softirq_running = 0;
10 
set_softirq_pending(uint64_t status)11 void set_softirq_pending(uint64_t status)
12 {
13     softirq_pending |= status;
14 }
15 
get_softirq_pending()16 uint64_t get_softirq_pending()
17 {
18     return softirq_pending;
19 }
20 
21 #define get_softirq_running() (softirq_running)
22 
23 /**
24  * @brief 设置软中断运行结束
25  *
26  * @param softirq_num
27  */
28 #define clear_softirq_running(softirq_num)        \
29     do                                            \
30     {                                             \
31         softirq_running &= (~(1 << softirq_num)); \
32     } while (0)
33 
34 // 设置软中断的运行状态(只应在do_softirq中调用此宏)
35 #define set_softirq_running(softirq_num)       \
36     do                                         \
37     {                                          \
38         softirq_running |= (1 << softirq_num); \
39     } while (0)
40 
41 /**
42  * @brief 清除软中断pending标志位
43  *
44  */
45 #define softirq_ack(sirq_num)                  \
46     do                                         \
47     {                                          \
48         softirq_pending &= (~(1 << sirq_num)); \
49     } while (0);
50 
51 /**
52  * @brief 软中断注册函数
53  *
54  * @param irq_num 软中断号
55  * @param action 响应函数
56  * @param data 响应数据结构体
57  */
register_softirq(uint32_t irq_num,void (* action)(void * data),void * data)58 void register_softirq(uint32_t irq_num, void (*action)(void *data), void *data)
59 {
60     softirq_vector[irq_num].action = action;
61     softirq_vector[irq_num].data = data;
62 }
63 
64 /**
65  * @brief 卸载软中断
66  *
67  * @param irq_num 软中断号
68  */
unregister_softirq(uint32_t irq_num)69 void unregister_softirq(uint32_t irq_num)
70 {
71     softirq_vector[irq_num].action = NULL;
72     softirq_vector[irq_num].data = NULL;
73 }
74 
75 /**
76  * @brief 软中断处理程序
77  *
78  */
do_softirq()79 void do_softirq()
80 {
81     sti();
82 
83     for (uint32_t i = 0; i < MAX_SOFTIRQ_NUM && softirq_pending; ++i)
84     {
85         if (softirq_pending & (1 << i) && softirq_vector[i].action != NULL && (!(get_softirq_running() & (1 << i))))
86         {
87             if (spin_trylock(&softirq_modify_lock))
88             {
89                 // 检测该软中断是否已经被其他进程执行
90                 if(get_softirq_running() & (1 << i))
91                 {
92                     spin_unlock(&softirq_modify_lock);
93                     continue;
94                 }
95                 softirq_ack(i);
96                 set_softirq_running(i);
97                 spin_unlock(&softirq_modify_lock);
98 
99                 softirq_vector[i].action(softirq_vector[i].data);
100 
101                 clear_softirq_running(i);
102             }
103         }
104     }
105 
106     cli();
107 }
108 
clear_softirq_pending(uint32_t irq_num)109 int clear_softirq_pending(uint32_t irq_num)
110 {
111     clear_softirq_running(irq_num);
112 }
113 
softirq_init()114 void softirq_init()
115 {
116     softirq_pending = 0;
117     memset(softirq_vector, 0, sizeof(struct softirq_t) * MAX_SOFTIRQ_NUM);
118     spin_init(&softirq_modify_lock);
119 }
120