From: acevest Date: Wed, 24 May 2023 13:09:15 +0000 (+0800) Subject: bug: 中断程序耗时过长可能会导致task.ticks--时溢出 X-Git-Url: http://zhaoyanbai.com/repos/%22http:/www.isc.org/icons/dnssec-signzone.html?a=commitdiff_plain;h=001073af2176de114d8588124d665aad2b4f2995;p=kernel.git bug: 中断程序耗时过长可能会导致task.ticks--时溢出 --- diff --git a/drivers/ata.c b/drivers/ata.c index dc258aa..900822d 100644 --- a/drivers/ata.c +++ b/drivers/ata.c @@ -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读取,对硬盘而言是写出 diff --git a/drivers/ide.c b/drivers/ide.c index da78c5c..30fa230 100644 --- a/drivers/ide.c +++ b/drivers/ide.c @@ -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++; diff --git a/include/printk.h b/include/printk.h index 7337ed4..52747b2 100644 --- a/include/printk.h +++ b/include/printk.h @@ -33,6 +33,7 @@ enum { MPL_IDE, MPL_IDE_INTR, MPL_CURRENT, + MPL_FUCK, MPL_TEST, MPL_X, MPL_DEBUG, diff --git a/include/task.h b/include/task.h index 2e95097..5e5c2c0 100644 --- a/include/task.h +++ b/include/task.h @@ -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]; diff --git a/kernel/clock.c b/kernel/clock.c index f2ce282..c856101 100644 --- a/kernel/clock.c +++ b/kernel/clock.c @@ -15,10 +15,13 @@ #include #include -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); } diff --git a/kernel/fork.c b/kernel/fork.c index 6893710..1543c79 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -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; diff --git a/kernel/interrupts.S b/kernel/interrupts.S index 9be5a24..0af4f70 100644 --- a/kernel/interrupts.S +++ b/kernel/interrupts.S @@ -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 diff --git a/kernel/irq.c b/kernel/irq.c index 0dfb65c..9b4d6ae 100644 --- a/kernel/irq.c +++ b/kernel/irq.c @@ -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, diff --git a/kernel/sched.c b/kernel/sched.c index 4094b95..98b9044 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -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用完了 diff --git a/kernel/task_root.c b/kernel/task_root.c index 7c45487..f48d1c1 100644 --- a/kernel/task_root.c +++ b/kernel/task_root.c @@ -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;"); diff --git a/lib/string.c b/lib/string.c index 2bccb1f..0b227dd 100644 --- a/lib/string.c +++ b/lib/string.c @@ -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; }