Browse Source

bugfix: 修复了无法在除pid=0的进程以外的进程刷新帧缓冲区的bug

fslongjin 2 years ago
parent
commit
cdbc4a316c

+ 2 - 2
kernel/driver/interrupt/8259A/8259A.c

@@ -8,9 +8,9 @@ extern void (*interrupt_table[24])(void);
 
 void init_8259A()
 {
-    // 初始化中断门, 中断使用第个ist
+    // 初始化中断门, 中断使用第0个ist
     for(int i=32;i<=55;++i)
-        set_intr_gate(i, 2, interrupt_table[i-32]);
+        set_intr_gate(i, 0, interrupt_table[i-32]);
     kinfo("Initializing 8259A...");
     
     // 初始化主芯片

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

@@ -68,6 +68,18 @@ 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));
 
+        // if (current_pcb->pid == 2)
+        //     kwarn("timer_jiffies = %ld video_refresh_expire_jiffies=%ld", timer_jiffies, video_refresh_expire_jiffies);
+        if (timer_jiffies >= video_refresh_expire_jiffies)
+        {
+            raise_softirq(VIDEO_REFRESH_SIRQ);
+        }
+        else
+        {
+            if (video_last_refresh_pid != current_pcb->pid)
+                raise_softirq(VIDEO_REFRESH_SIRQ);
+        }
+
         sched_update_jiffies();
 
         break;
@@ -142,6 +154,8 @@ int HPET_init()
     HPET_NUM_TIM_CAP = (tmp >> 8) & 0x1f; // 读取计时器数量
 
     // kinfo("HPET CLK_PERIOD=%#03lx Frequency=%f", HPET_COUNTER_CLK_PERIOD, (double)HPET_freq);
+    kdebug("HPET_freq=%ld", (long)HPET_freq);
+    // kdebug("HPET_freq=%lf", HPET_freq);
 
     struct apic_IO_APIC_RTE_entry entry;
     // 使用I/O APIC 的IRQ2接收hpet定时器0的中断
@@ -149,6 +163,7 @@ int HPET_init()
 
     // 计算HPET0间隔多少个时钟周期触发一次中断
     uint64_t clks_to_intr = 0.001 * HPET0_INTERVAL * HPET_freq;
+    // kdebug("clks_to_intr=%#ld", clks_to_intr);
     if (clks_to_intr <= 0 || clks_to_intr > (HPET_freq * 8))
     {
         kBUG("HPET0: Numof clocks to generate interrupt is INVALID! value=%lld", clks_to_intr);

+ 1 - 1
kernel/driver/timers/timer.h

@@ -7,7 +7,7 @@
 uint64_t volatile timer_jiffies = 0; // 系统时钟计数
 
 // 计算接下来n毫秒对应的系统时间片
-#define cal_next_n_ms_jiffies(expire_ms) (timer_jiffies + expire_ms / 5 + expire_ms % HPET0_INTERVAL ? 1 : 0)
+#define cal_next_n_ms_jiffies(expire_ms) (timer_jiffies + expire_ms / 5 + (expire_ms % HPET0_INTERVAL ? 1 : 0))
 
 void timer_init();
 

+ 22 - 14
kernel/driver/video/video.c

@@ -7,10 +7,15 @@
 #include <mm/mm.h>
 #include <mm/slab.h>
 #include <process/spinlock.h>
+#include <exception/softirq.h>
+
 // 每个时刻只能有1个进程新增定时任务
 spinlock_t video_timer_func_add_lock;
 
-#define REFRESH_INTERVAL 15 // 启动刷新帧缓冲区任务的时间间隔
+uint64_t video_refresh_expire_jiffies = 0;
+uint64_t video_last_refresh_pid = -1;
+
+#define REFRESH_INTERVAL 15UL // 启动刷新帧缓冲区任务的时间间隔
 
 ul VBE_FB_phys_addr; // 由bootloader传来的帧缓存区的物理地址
 struct screen_info_t
@@ -68,19 +73,15 @@ void init_frame_buffer(bool level)
  * @brief 刷新帧缓冲区
  *
  */
-static void video_refresh_framebuffer()
+void video_refresh_framebuffer(void *data)
 {
-
-    // kdebug("pid%d flush fb", current_pcb->pid);
+    // 暂时设置一个很大的值作为屏障,防止二次进入该区域(造成#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));
-
-    // 新增下一个刷新定时任务
-    struct timer_func_list_t *tmp = (struct timer_func_list_t *)kmalloc(sizeof(struct timer_func_list_t), 0);
-    spin_lock(&video_timer_func_add_lock);
-    timer_func_init(tmp, &video_refresh_framebuffer, NULL, 10 * REFRESH_INTERVAL);
-    timer_func_add(tmp);
-    spin_unlock(&video_timer_func_add_lock);
+    video_refresh_expire_jiffies = cal_next_n_ms_jiffies(REFRESH_INTERVAL);
 }
 
 /**
@@ -99,8 +100,15 @@ int video_init(bool level)
         // 启用双缓冲后,使能printk滚动动画
         // printk_enable_animation();
         // 初始化第一个屏幕刷新任务
-        struct timer_func_list_t *tmp = (struct timer_func_list_t *)kmalloc(sizeof(struct timer_func_list_t), 0);
-        timer_func_init(tmp, &video_refresh_framebuffer, NULL, REFRESH_INTERVAL);
-        timer_func_add(tmp);
+        // struct timer_func_list_t *tmp = (struct timer_func_list_t *)kmalloc(sizeof(struct timer_func_list_t), 0);
+        // timer_func_init(tmp, &video_refresh_framebuffer, NULL, 10*REFRESH_INTERVAL);
+        // timer_func_add(tmp);
+        register_softirq(VIDEO_REFRESH_SIRQ, &video_refresh_framebuffer, NULL);
+        kdebug("15/5=%#ld", 15 / 5);
+        kdebug("1212121=%#ld", REFRESH_INTERVAL / 5);
+        kdebug("sdds21=%#ld", REFRESH_INTERVAL / 5 + (REFRESH_INTERVAL % HPET0_INTERVAL ? 1 : 0));
+        video_refresh_expire_jiffies = cal_next_n_ms_jiffies(10 * REFRESH_INTERVAL);
+        kdebug("video_refresh_expire_jiffies=%ld", video_refresh_expire_jiffies);
+        raise_softirq(VIDEO_REFRESH_SIRQ);
     }
 }

+ 6 - 1
kernel/driver/video/video.h

@@ -9,4 +9,9 @@
  * true ->高级初始化:增加double buffer的支持
  * @return int
  */
-int video_init(bool level);
+int video_init(bool level);
+
+extern uint64_t video_refresh_expire_jiffies;
+extern uint64_t video_last_refresh_pid;
+
+extern void video_refresh_framebuffer();

+ 4 - 2
kernel/exception/softirq.c

@@ -1,6 +1,7 @@
 #include "softirq.h"
 #include <common/kprint.h>
 #include <process/process.h>
+#include <driver/video/video.h>
 uint64_t softirq_status = 0;
 void set_softirq_status(uint64_t status)
 {
@@ -42,17 +43,18 @@ 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)
     {
         if (softirq_status & (1 << i) && softirq_vector[i].action != NULL)
-        {            
+        {
             softirq_vector[i].action(softirq_vector[i].data);
         }
     }
 
     cli();
+    
 }
 
 void softirq_init()

+ 5 - 8
kernel/process/process.c

@@ -16,7 +16,6 @@
 spinlock_t process_global_pid_write_lock; // 增加pid的写锁
 long process_global_pid = 1;              // 系统中最大的pid
 
-
 extern void system_call(void);
 extern void kernel_thread_func(void);
 
@@ -132,7 +131,6 @@ struct vfs_file_t *process_open_exec_file(char *path)
 
     dentry = vfs_path_walk(path, 0);
 
-
     if (dentry == NULL)
         return (void *)-ENOENT;
 
@@ -164,7 +162,7 @@ static int process_load_elf_file(struct pt_regs *regs, char *path)
     int retval = 0;
     struct vfs_file_t *filp = process_open_exec_file(path);
 
-    if ((long)filp <= 0 && (long)filp >=-255)
+    if ((long)filp <= 0 && (long)filp >= -255)
     {
         // kdebug("(long)filp=%ld", (long)filp);
         return (unsigned long)filp;
@@ -276,12 +274,10 @@ static int process_load_elf_file(struct pt_regs *regs, char *path)
     uint64_t pa = alloc_pages(ZONE_NORMAL, 1, PAGE_PGT_MAPPED)->addr_phys;
 
     mm_map_proc_page_table((uint64_t)current_pcb->mm->pgd, true, current_pcb->mm->stack_start - PAGE_2M_SIZE, pa, PAGE_2M_SIZE, PAGE_USER_PAGE, true, true);
-    
+
     // 清空栈空间
     memset((void *)(current_pcb->mm->stack_start - PAGE_2M_SIZE), 0, PAGE_2M_SIZE);
 
-    
-
 load_elf_failed:;
     if (buf != NULL)
         kfree(buf);
@@ -565,13 +561,14 @@ void process_init()
 */
     // 初始化pid的写锁
     spin_init(&process_global_pid_write_lock);
-
     // 初始化进程的循环链表
     list_init(&initial_proc_union.pcb.list);
     kernel_thread(initial_kernel_thread, 10, CLONE_FS | CLONE_SIGNAL); // 初始化内核进程
     initial_proc_union.pcb.state = PROC_RUNNING;
     initial_proc_union.pcb.preempt_count = 0;
     initial_proc_union.pcb.cpu_id = 0;
+    initial_proc_union.pcb.virtual_runtime = (1UL << 60);
+    current_pcb->virtual_runtime = (1UL << 60);
 }
 
 /**
@@ -625,7 +622,7 @@ unsigned long do_fork(struct pt_regs *regs, unsigned long clone_flags, unsigned
     spin_unlock(&process_global_pid_write_lock);
 
     tsk->cpu_id = proc_current_cpu_id;
-    tsk->state = PROC_UNINTERRUPTIBLE;
+    tsk->state = PROC_RUNNING;
 
     tsk->parent_pcb = current_pcb;
     wait_queue_init(&tsk->wait_child_proc_exit, NULL);

+ 1 - 1
kernel/process/process.h

@@ -125,7 +125,7 @@ struct process_control_block
 
 	long pid;
 	long priority;		  // 优先级
-	long virtual_runtime; // 虚拟运行时间
+	int64_t virtual_runtime; // 虚拟运行时间
 
 	// 进程拥有的文件描述符的指针数组
 	// todo: 改用动态指针数组

+ 7 - 0
kernel/sched/sched.c

@@ -78,6 +78,13 @@ void sched_cfs()
                 break;
             }
         }
+
+        // if (proc->pid == 0)
+        // {
+        //     kdebug("switch to pid0, current pid%ld, vrt=%ld      pid0 vrt=%ld", current_pcb->pid, current_pcb->virtual_runtime, proc->virtual_runtime);
+        //     if(current_pcb->state != PROC_RUNNING)
+        //         kdebug("current_pcb->state!=PROC_RUNNING");
+        // }
         
         process_switch_mm(proc);