diff --git a/kernel/driver/interrupt/apic/apic.c b/kernel/driver/interrupt/apic/apic.c index 63454e8a..880639ab 100644 --- a/kernel/driver/interrupt/apic/apic.c +++ b/kernel/driver/interrupt/apic/apic.c @@ -479,9 +479,9 @@ void do_IRQ(struct pt_regs *rsp, ul number) } // kdebug("before softirq"); - // 检测是否有未处理的软中断 - if (softirq_status != 0) - do_softirq(); + // 进入软中断处理程序 + do_softirq(); + // kdebug("after softirq"); // 检测当前进程是否持有自旋锁,若持有自旋锁,则不进行抢占式的进程调度 if (current_pcb->preempt_count > 0) diff --git a/kernel/driver/timers/HPET/HPET.c b/kernel/driver/timers/HPET/HPET.c index d898a65b..6ab3fb48 100644 --- a/kernel/driver/timers/HPET/HPET.c +++ b/kernel/driver/timers/HPET/HPET.c @@ -66,7 +66,7 @@ void HPET_handler(uint64_t number, uint64_t param, struct pt_regs *regs) // 若当前时间比定时任务的时间间隔大,则进入中断下半部 if (container_of(list_next(&timer_func_head.list), struct timer_func_list_t, list)->expire_jiffies <= timer_jiffies) - set_softirq_status((1 << TIMER_SIRQ)); + raise_softirq((1 << TIMER_SIRQ)); // if (current_pcb->pid == 2) // kwarn("timer_jiffies = %ld video_refresh_expire_jiffies=%ld", timer_jiffies, video_refresh_expire_jiffies); diff --git a/kernel/driver/timers/timer.c b/kernel/driver/timers/timer.c index 857c8258..84f3e014 100644 --- a/kernel/driver/timers/timer.c +++ b/kernel/driver/timers/timer.c @@ -27,22 +27,19 @@ void timer_init() void do_timer_softirq(void *data) { - // if(current_pcb->pid==3) - // kdebug("pid3 timer irq"); + struct timer_func_list_t *tmp = container_of(list_next(&timer_func_head.list), struct timer_func_list_t, list); while ((!list_empty(&timer_func_head.list)) && (tmp->expire_jiffies <= timer_jiffies)) { - if (current_pcb->pid == 2) - kdebug("pid2 timer do"); + timer_func_del(tmp); tmp->func(tmp->data); kfree(tmp); tmp = container_of(list_next(&timer_func_head.list), struct timer_func_list_t, list); } - softirq_ack(TIMER_SIRQ); - // printk_color(ORANGE, BLACK, "(HPET%ld)", timer_jiffies); + } /** diff --git a/kernel/driver/video/video.c b/kernel/driver/video/video.c index 17295846..9b8ec6c4 100644 --- a/kernel/driver/video/video.c +++ b/kernel/driver/video/video.c @@ -78,7 +78,6 @@ void video_refresh_framebuffer(void *data) // 暂时设置一个很大的值作为屏障,防止二次进入该区域(造成#GP) video_refresh_expire_jiffies = timer_jiffies + 100000; video_last_refresh_pid = current_pcb->pid; - softirq_ack(VIDEO_REFRESH_SIRQ); memcpy((void *)sc_info.fb_vaddr, (void *)sc_info.double_fb_vaddr, (sc_info.length << 2)); video_refresh_expire_jiffies = cal_next_n_ms_jiffies(REFRESH_INTERVAL); diff --git a/kernel/exception/softirq.c b/kernel/exception/softirq.c index 14c8cfdc..846fb68e 100644 --- a/kernel/exception/softirq.c +++ b/kernel/exception/softirq.c @@ -2,17 +2,52 @@ #include #include #include -uint64_t softirq_status = 0; -void set_softirq_status(uint64_t status) +#include + +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) { - softirq_status |= status; + softirq_pending |= status; } -uint64_t get_softirq_status() +uint64_t get_softirq_pending() { - return softirq_status; + return softirq_pending; } +#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); + /** * @brief 软中断注册函数 * @@ -44,21 +79,36 @@ void unregister_softirq(uint32_t irq_num) void do_softirq() { sti(); - // video_refresh_framebuffer(); - for (uint32_t i = 0; i < MAX_SOFTIRQ_NUM && softirq_status; ++i) + + for (uint32_t i = 0; i < MAX_SOFTIRQ_NUM && softirq_pending; ++i) { - if (softirq_status & (1 << i) && softirq_vector[i].action != NULL) + if (softirq_pending & (1 << i) && softirq_vector[i].action != NULL && (!(get_softirq_running() & (1 << i)))) { - softirq_vector[i].action(softirq_vector[i].data); + 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); + } } } cli(); - } void softirq_init() { - softirq_status = 0; + softirq_pending = 0; memset(softirq_vector, 0, sizeof(struct softirq_t) * MAX_SOFTIRQ_NUM); + spin_init(&softirq_modify_lock); } diff --git a/kernel/exception/softirq.h b/kernel/exception/softirq.h index 5171526d..136f1794 100644 --- a/kernel/exception/softirq.h +++ b/kernel/exception/softirq.h @@ -24,20 +24,11 @@ #define raise_softirq(sirq_num) \ do \ { \ - set_softirq_status(1 << sirq_num); \ + set_softirq_pending(1 << sirq_num); \ } while (0); -/** - * @brief 清除软中断标志位(需要软中断处理程序手动调用) - * - */ -#define softirq_ack(sirq_num) \ - do \ - { \ - softirq_status &= (~(1 << sirq_num)); \ - } while (0); -extern uint64_t softirq_status; + struct softirq_t { @@ -63,8 +54,8 @@ void register_softirq(uint32_t irq_num, void (*action)(void *data), void *data); */ void unregister_softirq(uint32_t irq_num); -void set_softirq_status(uint64_t status); -uint64_t get_softirq_status(); +void set_softirq_pending(uint64_t status); +uint64_t get_softirq_pending(); /** * @brief 软中断处理程序