Browse Source

bugfix: 当进程在内核态退出后,屏幕刷新软中断会一直保持在pending的状态的bug

fslongjin 2 years ago
parent
commit
eed9077675

+ 7 - 0
kernel/driver/timers/HPET/HPET.c

@@ -1,5 +1,6 @@
 #include "HPET.h"
 #include <common/kprint.h>
+#include <common/compiler.h>
 #include <mm/mm.h>
 #include <driver/interrupt/apic/apic.h>
 #include <exception/softirq.h>
@@ -74,6 +75,12 @@ void HPET_handler(uint64_t number, uint64_t param, struct pt_regs *regs)
         if (timer_jiffies >= video_refresh_expire_jiffies || (video_last_refresh_pid != current_pcb->pid))
         {
             raise_softirq(VIDEO_REFRESH_SIRQ);
+            // 超过130ms仍未刷新完成,则重新发起刷新(防止由于进程异常退出导致的屏幕无法刷新)
+            if (unlikely(timer_jiffies >= (video_refresh_expire_jiffies + (1 << 17))))
+            {
+                video_refresh_expire_jiffies = timer_jiffies + (1 << 20);
+                clear_softirq_pending(VIDEO_REFRESH_SIRQ);
+            }
         }
         break;
 

+ 2 - 6
kernel/driver/video/video.c

@@ -75,12 +75,8 @@ void init_frame_buffer(bool level)
  */
 void video_refresh_framebuffer(void *data)
 {
-    // 暂时设置一个很大的值作为屏障,防止二次进入该区域(造成#GP)
-    video_refresh_expire_jiffies = timer_jiffies + 100000;
-    video_last_refresh_pid = current_pcb->pid;
-
+    video_refresh_expire_jiffies = cal_next_n_ms_jiffies(REFRESH_INTERVAL << 1);
     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);
 }
 
 /**
@@ -103,7 +99,7 @@ int video_init(bool level)
         // timer_func_init(tmp, &video_refresh_framebuffer, NULL, 10*REFRESH_INTERVAL);
         // timer_func_add(tmp);
         register_softirq(VIDEO_REFRESH_SIRQ, &video_refresh_framebuffer, NULL);
-        
+
         video_refresh_expire_jiffies = cal_next_n_ms_jiffies(10 * REFRESH_INTERVAL);
 
         raise_softirq(VIDEO_REFRESH_SIRQ);

+ 5 - 0
kernel/exception/softirq.c

@@ -106,6 +106,11 @@ void do_softirq()
     cli();
 }
 
+int clear_softirq_pending(uint32_t irq_num)
+{
+    clear_softirq_running(irq_num);
+}
+
 void softirq_init()
 {
     softirq_pending = 0;

+ 1 - 0
kernel/exception/softirq.h

@@ -57,6 +57,7 @@ void unregister_softirq(uint32_t irq_num);
 void set_softirq_pending(uint64_t status);
 uint64_t get_softirq_pending();
 
+int clear_softirq_pending(uint32_t irq_num);
 /**
  * @brief 软中断处理程序
  *