]> Zhao Yanbai Git Server - kernel.git/commitdiff
bug: 中断程序耗时过长可能会导致task.ticks--时溢出
authoracevest <zhaoyanbai@126.com>
Wed, 24 May 2023 13:09:15 +0000 (21:09 +0800)
committeracevest <zhaoyanbai@126.com>
Wed, 24 May 2023 13:09:15 +0000 (21:09 +0800)
drivers/ata.c
drivers/ide.c
include/printk.h
include/task.h
kernel/clock.c
kernel/fork.c
kernel/interrupts.S
kernel/irq.c
kernel/sched.c
kernel/task_root.c
lib/string.c

index dc258aa2a857e1dc03ffea37a4e87a13a3de804e..900822d7958d038832fd91887f23384fa18271e1 100644 (file)
@@ -231,8 +231,9 @@ void ata_dma_read_ext(int dev, uint64_t pos, uint16_t count, void *dest) {
     ide_pci_controller.prdt[0].eot = 1;
     outl(va2pa(ide_pci_controller.prdt), ide_pci_controller.bus_prdt);
 
-    printk("paddr: %x prdt: %x %x prdte %x %x\n", dest_paddr, ide_pci_controller.prdt, va2pa(ide_pci_controller.prdt),
-           ide_pci_controller.prdt[0].phys_addr, *(((unsigned int *)ide_pci_controller.prdt) + 1));
+    // printk("paddr: %x prdt: %x %x prdte %x %x\n", dest_paddr, ide_pci_controller.prdt,
+    // va2pa(ide_pci_controller.prdt),
+    //        ide_pci_controller.prdt[0].phys_addr, *(((unsigned int *)ide_pci_controller.prdt) + 1));
 
     // 清除中断位和错误位
     // 这里清除的方式是是设置1后清除
@@ -277,7 +278,7 @@ void ata_dma_read_ext(int dev, uint64_t pos, uint16_t count, void *dest) {
     // Register)的值会一直是5 也就是INTERRUPT和和ACTIVE位是1,正常应该是4,也就是只有INTERRUPT位为1
     // 在bochs中则加不加这一句不会有影响,都能正常读到数据
     unsigned int v = pci_read_config_word(pci_cmd(ide_pci_controller.pci, PCI_COMMAND));
-    printk(" ide pci command %04x\n", v);
+    // printk(" ide pci command %04x\n", v);
     pci_write_config_word(v | PCI_COMMAND_MASTER, pci_cmd(ide_pci_controller.pci, PCI_COMMAND));
 
     // 指定DMA操作为读取硬盘操作,内核用DMA读取,对硬盘而言是写出
index da78c5cf3915975a1d1c92be8784e45b8ea2f6e8..30fa230279af8b72ca2de0fb00464bf42fa66eb0 100644 (file)
@@ -139,7 +139,7 @@ void ide_pci_init(pci_device_t *pci) {
     unsigned int v;
 
     v = pci_read_config_word(pci_cmd(pci, PCI_COMMAND));
-    printk(" ide pci command %04x\n", v);
+    // printk(" ide pci command %04x\n", v);
 
     v = pci_read_config_byte(pci_cmd(pci, PCI_PROGIF));
     printk(" ide pci program interface %02x\n", v);
@@ -558,7 +558,7 @@ volatile uint32_t disk_inter_cnt = 0;
 void ide_irq_handler(unsigned int irq, pt_regs_t *regs, void *devid) {
     // printk("ide irq handler %d \n", irq);
 
-    printk("ide irq %d handler pci status: 0x%02x\n", irq, ata_pci_bus_status());
+    // printk("ide irq %d handler pci status: 0x%02x\n", irq, ata_pci_bus_status());
 
 #if 1
     disk_inter_cnt++;
index 7337ed4e322cc9481108633826fa1f39e3e62ca5..52747b29372c9c3a71f49c50a99681b5fb74118b 100644 (file)
@@ -33,6 +33,7 @@ enum {
     MPL_IDE,
     MPL_IDE_INTR,
     MPL_CURRENT,
+    MPL_FUCK,
     MPL_TEST,
     MPL_X,
     MPL_DEBUG,
index 2e9509745aefe0f37f5d3b0d380397c3f1e1f613..5e5c2c0aeed9be1a0c7772b82ba7477ad29d9c59 100644 (file)
@@ -36,7 +36,9 @@ enum {
 
 #define TASK_NAME_SIZE 32
 
-#define TASK_MAX_PRIORITY 200
+#define TASK_MAX_PRIORITY 99
+
+#define TASK_MAGIC 0xAABBCCDD11223344
 
 typedef union task_union {
     struct {
@@ -71,6 +73,8 @@ typedef union task_union {
         uint32_t sched_keep_cnt;  // 时间片到了,但是没有被换出,又重新执行的次数
 
         uint64_t delay_jiffies;  // debug only
+
+        uint64_t magic;  // 栈溢出标志
     };
 
     unsigned char stack[TASK_SIZE];
index f2ce282341891528b528b4a50b7ad42597991202..c856101d370e33beccd79670b27c6decd8ac9674 100644 (file)
 #include <system.h>
 #include <wait.h>
 
-volatile uint32_t jiffies = 0;
+volatile uint32_t jiffies = 0;  // TODO uint64
 
 unsigned int sys_clock() { return jiffies; }
 
+void debug_print_all_tasks();
+
+void dump_irq_nr_stack();
 void clk_handler(unsigned int irq, pt_regs_t *regs, void *dev_id) {
     if (jiffies % 100 == 0) {
         printl(MPL_CLOCK, "clock irq: %d", jiffies);
@@ -30,7 +33,16 @@ void clk_handler(unsigned int irq, pt_regs_t *regs, void *dev_id) {
     jiffies++;
 
     current->jiffies = jiffies;
+    // 若clk_handler嵌套在其它中断函数中执行
+    // 那么这个变量减到0时,再退出中clk_handler并不会引起调度
+    //
+
     current->ticks--;
+    if (current->ticks > TASK_MAX_PRIORITY) {
+        printl(MPL_X, "current %08x ticks %u", current, current->ticks);
+        printk("DIE: ");
+        dump_irq_nr_stack();
+    }
     assert(current->ticks <= TASK_MAX_PRIORITY);  // 防止ticks被减到0后再减溢出
 
     task_union *p = 0;
@@ -44,5 +56,10 @@ void clk_handler(unsigned int irq, pt_regs_t *regs, void *dev_id) {
         }
     }
 
+    debug_print_all_tasks();
+    debug_print_all_tasks();
+    debug_print_all_tasks();
+    debug_print_all_tasks();
+
     irq_restore(iflags);
 }
index 6893710f40fadfdc41eec2895db4f842f20fa194..1543c79037981f52ea05e629b3d211ab5948175c 100644 (file)
@@ -88,8 +88,9 @@ int do_fork(pt_regs_t *regs, unsigned long flags) {
     tsk->priority = current->priority;
     tsk->ticks = tsk->priority;
     tsk->turn = 0;  //
-    root_task.sched_cnt = 0;
-    root_task.sched_keep_cnt = 0;
+    tsk->sched_cnt = 0;
+    tsk->sched_keep_cnt = 0;
+    assert(tsk->magic == TASK_MAGIC);
 
     pt_regs_t *child_regs = ((pt_regs_t *)(TASK_SIZE + (unsigned long)tsk)) - 1;
 
index 9be5a2457fe6d11fee5cf2990a0affb41e96989e..0af4f703080d698135a53cfa6b80ccf27ca67733 100644 (file)
@@ -72,8 +72,14 @@ _irq_handler:
 
     cmpl    $0, (irq_reenter)
     jnz     restore_regs
+
+
     call    schedule
 
+    RESTORE_REGS
+    addl    $4, %esp
+    iret
+
 restore_regs:
     RESTORE_REGS
     addl    $4, %esp
index 0dfb65c6c293c21c0db36a39025d92d4fd211d9e..9b4d6aeb08d97dc07c0091695272aa96970c8f15 100644 (file)
@@ -30,6 +30,52 @@ irq_chip_t no_irq_chip = {.name = "none", .enable = enable_no_irq_chip, .disable
 
 irq_desc_t no_irq_desc = {.chip = &no_irq_chip, .action = NULL, .status = 0, .depth = 0};
 
+unsigned int irq_nr_stack[64] = {1, 2, 3, 4};
+uint32_t irq_nr_jiffies_stack[64] = {
+    0,
+};
+int irq_nr_stack_pos = 0;
+
+extern uint32_t jiffies;
+void push_irq_nr_stack(unsigned int irq) {
+    irq_nr_stack[irq_nr_stack_pos] = irq;
+    irq_nr_jiffies_stack[irq_nr_stack_pos] = jiffies;
+    irq_nr_stack_pos++;
+}
+
+unsigned int pop_irq_nr_stack() {
+    irq_nr_stack_pos--;
+    return irq_nr_stack[irq_nr_stack_pos];
+}
+
+int vsprintf(char *buf, const char *fmt, char *args);
+void dump_irq_nr_stack() {
+    if (irq_nr_stack_pos == 0) {
+        printl(MPL_TEST, "irq nr stack empty");
+        return 0;
+    }
+
+    printl(MPL_FUCK, "irq nr stack pos %u", irq_nr_stack_pos);
+
+    char buf[128];
+
+    memset(buf, 0, 128);
+    strcpy(buf, "irq nr stack: ");
+    for (int i = 0; i < irq_nr_stack_pos; i++) {
+        char dbuf[64];
+        vsprintf(dbuf, "%02d:", irq_nr_stack + i);  // 这里vsprintf有坑,坑点在第三个参数不是标准参数
+        strcat(buf, dbuf);
+        vsprintf(dbuf, "%d ", irq_nr_jiffies_stack + i);
+        strcat(buf, dbuf);
+    }
+
+    printl(MPL_TEST, "                                                                               ");
+
+    printl(MPL_TEST, buf);
+    strcat(buf, "\n");
+    printk(buf);
+}
+
 __attribute__((regparm(1))) void irq_handler(pt_regs_t *regs) {
     unsigned int irq = regs->irq;
     if (irq >= NR_IRQS) {
@@ -52,25 +98,45 @@ __attribute__((regparm(1))) void irq_handler(pt_regs_t *regs) {
 
     irq_reenter++;
 
+    assert(current->magic == TASK_MAGIC);
+
+    push_irq_nr_stack(irq);
+
+    // if (irq_nr_stack_pos >= 2) {
+    dump_irq_nr_stack();
+    //     panic("sdfasd");
+    // }
     // 开中断执行中断处理函数
     enable_irq();
-
     unsigned long esp;
     asm("movl %%esp, %%eax" : "=a"(esp));
     printl(MPL_CURRENT, "current %08x cr3 %08x reenter %d esp %08x", current, current->cr3, irq_reenter, esp);
-
+    printk("2: %d r %d t %d\n", irq, irq_reenter, current->ticks);
     while (action && action->handler) {
+        if (irq == 14) {
+            printk("a: %d r %d t %d \n", irq, irq_reenter, current->ticks);
+        }
         action->handler(irq, regs, action->dev_id);
+        if (irq == 14) {
+            printk("b: %d r %d t %d \n", irq, irq_reenter, current->ticks);
+        }
         action = action->next;
     }
 
     // 关全局中断
+    if (irq == 14) {
+        printk("c: %d r %d t %d \n", irq, irq_reenter, current->ticks);
+    }
     disable_irq();
-
+    pop_irq_nr_stack();
     irq_reenter--;
-
+    if (irq == 14) {
+        printk("d: %d r %d t %d \n", irq, irq_reenter, current->ticks);
+    }
     // 解除屏蔽当前中断
     p->chip->enable(irq);
+
+    printk("x: %d r %d t %d \n", irq, irq_reenter, current->ticks);
 }
 
 int request_irq(unsigned int irq, void (*handler)(unsigned int, pt_regs_t *, void *), const char *devname,
index 4094b956177a94114cb94b477b5997cf5d0821f9..98b9044c85ecbdfdaabc554cecea9efad8d64015 100644 (file)
@@ -61,6 +61,7 @@ void init_root_task() {
     root_task.turn = 0;
     root_task.sched_cnt = 0;
     root_task.sched_keep_cnt = 0;
+    root_task.magic = TASK_MAGIC;
     strcpy(root_task.name, "root");
 
     list_add(&root_task.list, &all_tasks);
@@ -165,11 +166,24 @@ extern uint32_t disk_request_cnt;
 extern uint32_t disk_handled_cnt;
 extern uint32_t disk_inter_cnt;
 
+void debug_print_all_tasks() {
+    task_union *p = 0;
+    list_head_t *pos = 0, *t = 0;
+    printl(MPL_TASK_TITLE, "         NAME     STATE TK/PI TURN       SCHED      KEEP");
+    list_for_each_safe(pos, t, &all_tasks) {
+        p = list_entry(pos, task_union, list);
+        printl(MPL_TASK_0 + p->pid, "%08x%s%4s:%u %s %02u/%02u %-10u %-10u %-10u", p,
+               p->state == TASK_RUNNING ? ">" : " ", p->name, p->pid, task_state(p->state), p->ticks, p->priority,
+               p->turn, p->sched_cnt, p->sched_keep_cnt);
+    }
+}
+
 void schedule() {
     task_union *root = &root_task;
     task_union *sel = 0;
     task_union *p = 0;
     list_head_t *pos = 0, *t = 0;
+    printk("*");
 
     printl(MPL_X, "disk req %u consumed %u irq %u", disk_request_cnt, disk_handled_cnt, disk_inter_cnt);
 
@@ -207,7 +221,21 @@ void schedule() {
             sel = p;
             continue;
         }
-
+#if 1
+        // 考察三个量
+        // priority 越大越优先
+        // jiffies  越小越优先
+        // (priority - ticks) 表示已经使用的量,越小越优先
+        int64_t a = sel->jiffies - sel->priority + (sel->priority - sel->ticks);
+        int64_t b = p->jiffies - p->priority + (p->priority - p->ticks);
+        if (a > b) {
+            sel = p;
+        } else if (a == b) {
+            if (sel->priority < p->priority) {
+                sel = p;
+            }
+        }
+#else
         if (sel->jiffies < p->jiffies) {
             continue;
         }
@@ -223,23 +251,26 @@ void schedule() {
                 sel = p;
             }
         }
+#endif
     }
 
     task_union *prev = current;
     task_union *next = sel != 0 ? sel : root;
 
     next->state = TASK_RUNNING;
+
+#if 1
+    // debug_print_all_tasks();
+#else
+    printl(MPL_TASK_TITLE, "         NAME     STATE TK/PI TURN       SCHED      KEEP");
+    list_for_each_safe(pos, t, &all_tasks) {
+        p = list_entry(pos, task_union, list);
+        printl(MPL_TASK_0 + p->pid, "%08x%s%4s:%d %s %02u/%02d %-10u %-10u %-10u", p, next == p ? ">" : " ", p->name,
+               p->pid, task_state(p->state), p->ticks, p->priority, p->turn, p->sched_cnt, p->sched_keep_cnt);
+    }
+#endif
     if (prev != next) {
         next->sched_cnt++;
-
-        printl(MPL_TASK_TITLE, "         NAME     STATE TK/PI TURN       SCHED      KEEP");
-        list_for_each_safe(pos, t, &all_tasks) {
-            p = list_entry(pos, task_union, list);
-            printl(MPL_TASK_0 + p->pid, "%08x%s%4s:%d %s %02u/%02d %-10u %-10u %-10u", p, next == p ? ">" : " ",
-                   p->name, p->pid, task_state(p->state), p->ticks, p->priority, p->turn, p->sched_cnt,
-                   p->sched_keep_cnt);
-        }
-
         context_switch(prev, next);
     } else {
         // 这里可能是的情况是任务把时间片ticks用完了
index 7c454875062b32bdf61e16886932ae1fc6d55d99..f48d1c1df2b280885f13dca6109546cfaee5d7a8 100644 (file)
@@ -79,7 +79,7 @@ void verify_hd_data(uint64_t sect_nr, uint16_t *buf, const char *name) {
     uint16_t fp = buf[255];
 
     if (fp == vfp) {
-        printk("%s verification passed sect %lu fp %04x\n", name, sect_nr, fp);
+        // printk("%s verification passed sect %lu fp %04x\n", name, sect_nr, fp);
     } else {
         printk("%s verification failed sect %lu fp %04x right %04x\n", name, sect_nr, fp, vfp);
         panic("verify hd data fail");
@@ -139,7 +139,7 @@ void taskC_entry() {
     current->priority = 19;
 
     while (1) {
-        sysc_wait(2);
+        sysc_wait(1);
 
         for (int i = 0; i < 7; i++) {
             asm("hlt;");
index 2bccb1f4c0b57e7b1fe5b208573c8ac52c76ce0d..0b227ddcaced75eb41b04b81d4bc7b4b248b249d 100644 (file)
@@ -78,7 +78,7 @@ int strncmp(const char *a, const char *b, size_t count) {
 char *strcat(char *dest, const char *src) {
     char *tmp = dest;
     while (*dest) dest++;
-    while ((*dest++ = *src++) != '\0')
+    while (*dest++ = *src++)
         ;
     return tmp;
 }