DragonOS/kernel/exception/softirq.c

120 lines
2.9 KiB
C
Raw Normal View History

2022-04-08 12:04:12 +00:00
#include "softirq.h"
#include <common/kprint.h>
#include <process/process.h>
#include <driver/video/video.h>
#include <common/spinlock.h>
static spinlock_t softirq_modify_lock; // 软中断状态status
static volatile uint64_t softirq_pending = 0;
static volatile uint64_t softirq_running = 0;
void set_softirq_pending(uint64_t status)
2022-04-08 12:04:12 +00:00
{
softirq_pending |= status;
2022-04-08 12:04:12 +00:00
}
uint64_t get_softirq_pending()
2022-04-08 12:04:12 +00:00
{
return softirq_pending;
2022-04-08 12:04:12 +00:00
}
#define get_softirq_running() (softirq_running)
/**
* @brief
*
* @param softirq_num
*/
#define clear_softirq_running(softirq_num) \
do \
{ \
softirq_running &= (~(1 << softirq_num)); \
} while (0)
// 设置软中断的运行状态只应在do_softirq中调用此宏
#define set_softirq_running(softirq_num) \
do \
{ \
softirq_running |= (1 << softirq_num); \
} while (0)
/**
* @brief pending标志位
*
*/
#define softirq_ack(sirq_num) \
do \
{ \
softirq_pending &= (~(1 << sirq_num)); \
} while (0);
2022-04-08 12:04:12 +00:00
/**
* @brief
*
* @param irq_num
* @param action
* @param data
*/
void register_softirq(uint32_t irq_num, void (*action)(void *data), void *data)
{
softirq_vector[irq_num].action = action;
softirq_vector[irq_num].data = data;
}
/**
* @brief
*
* @param irq_num
*/
void unregister_softirq(uint32_t irq_num)
{
softirq_vector[irq_num].action = NULL;
softirq_vector[irq_num].data = NULL;
}
/**
* @brief
2022-04-08 13:26:42 +00:00
*
2022-04-08 12:04:12 +00:00
*/
void do_softirq()
{
sti();
for (uint32_t i = 0; i < MAX_SOFTIRQ_NUM && softirq_pending; ++i)
2022-04-08 12:04:12 +00:00
{
if (softirq_pending & (1 << i) && softirq_vector[i].action != NULL && (!(get_softirq_running() & (1 << i))))
{
if (spin_trylock(&softirq_modify_lock))
{
// 检测该软中断是否已经被其他进程执行
if(get_softirq_running() & (1 << i))
{
spin_unlock(&softirq_modify_lock);
continue;
}
softirq_ack(i);
set_softirq_running(i);
spin_unlock(&softirq_modify_lock);
softirq_vector[i].action(softirq_vector[i].data);
clear_softirq_running(i);
}
2022-04-08 12:04:12 +00:00
}
}
cli();
2022-04-08 12:04:12 +00:00
}
int clear_softirq_pending(uint32_t irq_num)
{
clear_softirq_running(irq_num);
}
2022-04-08 12:04:12 +00:00
void softirq_init()
{
softirq_pending = 0;
2022-04-08 12:04:12 +00:00
memset(softirq_vector, 0, sizeof(struct softirq_t) * MAX_SOFTIRQ_NUM);
spin_init(&softirq_modify_lock);
2022-04-08 12:04:12 +00:00
}