From: acevest Date: Fri, 26 May 2023 16:52:37 +0000 (+0800) Subject: 中断处理不再允许嵌套执行;将不重要的中断处理逻辑归类为下半部分处理逻辑,并允许开中断执行,但在该部分逻辑在被中断打断的情况下也只允许执行一次. X-Git-Url: http://zhaoyanbai.com/repos/%22http:/www.isc.org/icons/zpipe.c?a=commitdiff_plain;h=92ca4828ee74f800ba3bdd132f162a739075d9f2;p=kernel.git 中断处理不再允许嵌套执行;将不重要的中断处理逻辑归类为下半部分处理逻辑,并允许开中断执行,但在该部分逻辑在被中断打断的情况下也只允许执行一次. --- diff --git a/drivers/ide.c b/drivers/ide.c index 30fa230..196952d 100644 --- a/drivers/ide.c +++ b/drivers/ide.c @@ -576,7 +576,7 @@ void ide_init() { void ide_ata_init(); ide_ata_init(); - request_irq(0x0E, ide_irq_handler, "hard", "IDE"); + request_irq(0x0E, ide_irq_handler, NULL, "hard", "IDE"); // init_pci_controller(0x0106); init_pci_controller(0x0101); diff --git a/include/irq.h b/include/irq.h index fc704c7..59b4471 100644 --- a/include/irq.h +++ b/include/irq.h @@ -32,6 +32,7 @@ typedef struct irq_chip { typedef struct irqaction { // void (*handler)(pt_regs_t * regs, unsigned int irq); void (*handler)(unsigned int irq, pt_regs_t *regs, void *dev_id); + void (*bh_handler)(); const char *dev_name; void *dev_id; struct irqaction *next; @@ -49,7 +50,8 @@ extern irq_desc_t irq_desc[]; extern irq_desc_t no_irq_desc; int request_irq(unsigned int irq, // void (*handler)(pt_regs_t *, unsigned int), - void (*handler)(unsigned int, pt_regs_t *, void *), const char *devname, void *dev_id); + void (*handler)(unsigned int, pt_regs_t *, void *), void (*bh_handler)(), const char *devname, + void *dev_id); int open_irq(unsigned int irq); int close_irq(unsigned int irq); @@ -60,6 +62,7 @@ int close_irq(unsigned int irq); #define irq_save(x) __asm__ __volatile__("pushfl; popl %0; cli" : "=g"(x)::"memory") bool irq_enabled(); +bool irq_disabled(); #define irq_restore(x) \ do { \ diff --git a/include/printk.h b/include/printk.h index 52747b2..f142ebe 100644 --- a/include/printk.h +++ b/include/printk.h @@ -33,7 +33,7 @@ enum { MPL_IDE, MPL_IDE_INTR, MPL_CURRENT, - MPL_FUCK, + MPL_TEST0, MPL_TEST, MPL_X, MPL_DEBUG, diff --git a/include/sched.h b/include/sched.h index 73883e3..ed00ce6 100644 --- a/include/sched.h +++ b/include/sched.h @@ -32,6 +32,7 @@ extern task_union root_task; extern void load_cr3(task_union *tsk); extern list_head_t all_tasks; +extern list_head_t delay_tasks; #define set_current_state(st) \ do { \ diff --git a/include/system.h b/include/system.h index e54d77d..a40cc79 100644 --- a/include/system.h +++ b/include/system.h @@ -270,7 +270,7 @@ void init_task_entry(); void disk_task_entry(); void user_task_entry(); -extern volatile int irq_reenter; +extern volatile int reenter; #endif #endif //_SYSTEM_H diff --git a/include/task.h b/include/task.h index 5e5c2c0..d246066 100644 --- a/include/task.h +++ b/include/task.h @@ -53,6 +53,8 @@ typedef union task_union { uint32_t priority; uint64_t jiffies; + volatile int need_resched; + pid_t pid; pid_t ppid; volatile unsigned int state; diff --git a/kernel/clock.c b/kernel/clock.c index c856101..d5aabed 100644 --- a/kernel/clock.c +++ b/kernel/clock.c @@ -27,24 +27,38 @@ void clk_handler(unsigned int irq, pt_regs_t *regs, void *dev_id) { printl(MPL_CLOCK, "clock irq: %d", jiffies); } +#if 0 unsigned long iflags; irq_save(iflags); - +#endif jiffies++; current->jiffies = jiffies; - // 若clk_handler嵌套在其它中断函数中执行 - // 那么这个变量减到0时,再退出中clk_handler并不会引起调度 - // - current->ticks--; + // 中断目前虽然不能嵌套,但依然可以打断前一个中断的下半部分处理 + // 若前一个时钟中断将这个值减到0 + // 同时其下半部分处理时间过长,直到这个时钟中断还没处理完 + // 那么这个时钟中断是完全可以打断它,且在这里把这个ticks从0减到负数 + // 而这个是uint32_t型,因此会溢出成0xFFFFFFFF + volatile uint32_t ticks; + + ticks = current->ticks; + if (current->ticks > 0) { + current->ticks--; + } + ticks = current->ticks; + +#if 0 if (current->ticks > TASK_MAX_PRIORITY) { printl(MPL_X, "current %08x ticks %u", current, current->ticks); printk("DIE: "); dump_irq_nr_stack(); } +#endif + assert(current->ticks <= TASK_MAX_PRIORITY); // 防止ticks被减到0后再减溢出 +#if 0 task_union *p = 0; list_head_t *t = 0; list_head_t *pos = 0; @@ -55,11 +69,41 @@ void clk_handler(unsigned int irq, pt_regs_t *regs, void *dev_id) { p->state = TASK_READY; } } +#endif +#if 0 debug_print_all_tasks(); debug_print_all_tasks(); debug_print_all_tasks(); debug_print_all_tasks(); +#endif +#if 0 irq_restore(iflags); +#endif } + +// 开中断执行这个函数 +const char *task_state(unsigned int state); +void clk_bh_handler() { + unsigned long iflags; + irq_save(iflags); + task_union *p = 0; + list_head_t *t = 0; + list_head_t *pos = 0; + list_for_each_safe(pos, t, &delay_tasks) { + p = list_entry(pos, task_union, pend); + // printk("%s state: %s\n", p->name, task_state(p->state)); + assert(p->state == TASK_WAIT); + assert(p->delay_jiffies != 0); + if (jiffies > p->delay_jiffies) { + list_del(&p->pend); + p->delay_jiffies = 0; + p->state = TASK_READY; + } + } + + // 此处调用这个还是有问题的 + debug_print_all_tasks(); + irq_restore(iflags); +} \ No newline at end of file diff --git a/kernel/fork.c b/kernel/fork.c index 1543c79..e49942a 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -88,6 +88,7 @@ int do_fork(pt_regs_t *regs, unsigned long flags) { tsk->priority = current->priority; tsk->ticks = tsk->priority; tsk->turn = 0; // + tsk->need_resched = 0; tsk->sched_cnt = 0; tsk->sched_keep_cnt = 0; assert(tsk->magic == TASK_MAGIC); diff --git a/kernel/interrupts.S b/kernel/interrupts.S index 0af4f70..f480ff3 100644 --- a/kernel/interrupts.S +++ b/kernel/interrupts.S @@ -52,8 +52,6 @@ DEF_IRQ(0,F) .global _irq_handler .extern irq_handler -.extern schedule -.extern irq_reenter _irq_handler: SAVE_REGS @@ -69,18 +67,7 @@ _irq_handler: movl %esp, %eax call irq_handler - - cmpl $0, (irq_reenter) - jnz restore_regs - - - call schedule - - RESTORE_REGS - addl $4, %esp - iret - -restore_regs: + RESTORE_REGS addl $4, %esp - iret + iret \ No newline at end of file diff --git a/kernel/irq.c b/kernel/irq.c index 9b4d6ae..b5e6834 100644 --- a/kernel/irq.c +++ b/kernel/irq.c @@ -52,10 +52,10 @@ 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; + return; } - printl(MPL_FUCK, "irq nr stack pos %u", irq_nr_stack_pos); + printl(MPL_TEST0, "irq nr stack pos %u", irq_nr_stack_pos); char buf[128]; @@ -79,68 +79,102 @@ void dump_irq_nr_stack() { __attribute__((regparm(1))) void irq_handler(pt_regs_t *regs) { unsigned int irq = regs->irq; if (irq >= NR_IRQS) { - printk("invalid irq %d\n", irq); - return; + panic("invalid irq %d\n", irq); } irq_desc_t *p = irq_desc + irq; irq_action_t *action = p->action; + assert(irq_disabled()); + reenter++; + // 屏蔽当前中断 p->chip->disable(irq); // 发送EOI p->chip->ack(irq); - if (irq_reenter == 0) { - // 可以切换到中断栈 - } - - irq_reenter++; - assert(current->magic == TASK_MAGIC); +#if 0 push_irq_nr_stack(irq); // if (irq_nr_stack_pos >= 2) { dump_irq_nr_stack(); // panic("sdfasd"); // } +#endif + +#if 0 // 开中断执行中断处理函数 enable_irq(); +#endif + +#if 1 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); + printl(MPL_CURRENT, "current %08x cr3 %08x reenter %d esp %08x %u", current, current->cr3, reenter, esp, + current->ticks); +#endif + 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 0 // 关全局中断 - if (irq == 14) { - printk("c: %d r %d t %d \n", irq, irq_reenter, current->ticks); - } disable_irq(); +#endif + +#if 0 pop_irq_nr_stack(); - irq_reenter--; - if (irq == 14) { - printk("d: %d r %d t %d \n", irq, irq_reenter, current->ticks); - } +#endif + // 解除屏蔽当前中断 p->chip->enable(irq); - printk("x: %d r %d t %d \n", irq, irq_reenter, current->ticks); + // 代表当前中断程序打断了前一个中断程序的“开中断处理的底半部分逻辑” + // 即前一个中断处理尚未完全完成 + assert(irq_disabled()); + if (reenter != 0) { + reenter--; + return; + } + // --以上逻辑CPU处于中断禁止状态-------------------------- + + // 此处执行中断函数的下半部分逻辑,开中断执行 + { + enable_irq(); + + action = p->action; + while (action) { + if (action->bh_handler != NULL) { + action->bh_handler(); + } + action = action->next; + } + + disable_irq(); + } + + // --以下逻辑CPU处于中断禁止状态-------------------------- + assert(irq_disabled()); + assert(reenter == 0); + reenter--; + assert(reenter == -1); + + // 考察如果不需要调度程序,直接退出 + if (current->ticks != 0) { + return; + } + + // 如果需要调度程序 + schedule(); } -int request_irq(unsigned int irq, void (*handler)(unsigned int, pt_regs_t *, void *), const char *devname, - void *dev_id) { +int request_irq(unsigned int irq, void (*handler)(unsigned int, pt_regs_t *, void *), void (*bh_handler)(), + const char *devname, void *dev_id) { irq_action_t *p; if (irq >= NR_IRQS) { @@ -167,6 +201,7 @@ int request_irq(unsigned int irq, void (*handler)(unsigned int, pt_regs_t *, voi p->dev_name = devname; p->dev_id = dev_id; p->handler = handler; + p->bh_handler = bh_handler; p->next = NULL; if (irq_desc[irq].action != NULL) { p->next = irq_desc[irq].action; @@ -190,4 +225,6 @@ bool irq_enabled() { } return false; -} \ No newline at end of file +} + +bool irq_disabled() { return !irq_enabled(); } \ No newline at end of file diff --git a/kernel/sched.c b/kernel/sched.c index 98b9044..82c272d 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -59,6 +59,7 @@ void init_root_task() { root_task.priority = 7; root_task.ticks = root_task.priority; root_task.turn = 0; + root_task.need_resched = 0; root_task.sched_cnt = 0; root_task.sched_keep_cnt = 0; root_task.magic = TASK_MAGIC; @@ -150,7 +151,7 @@ task_union *find_task(pid_t pid) { return p; } -static const char *task_state(unsigned int state) { +const char *task_state(unsigned int state) { static const char s[][16] = { " ERROR", "RUNNING", " READY", " WAIT", " INIT", " EXIT", }; @@ -183,7 +184,6 @@ void schedule() { 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); @@ -193,26 +193,25 @@ void schedule() { unsigned long iflags; irq_save(iflags); - if (TASK_RUNNING == current->state) { - if (0 == current->ticks) { - current->turn++; - current->ticks = current->priority; - current->state = TASK_READY; - } else { - irq_restore(iflags); - return; - } + if (0 == current->ticks) { + current->turn++; + current->ticks = current->priority; + current->state = TASK_READY; } + // printk("-----\n"); list_for_each_safe(pos, t, &all_tasks) { p = list_entry(pos, task_union, list); - assert(p->state != TASK_RUNNING); + // printk("%s state: %s ticks %u\n", current->name, task_state(current->state), current->ticks); + // printk("%s state: %s\n", p->name, task_state(p->state)); if (p == &root_task) { continue; } + assert(p->state != TASK_RUNNING); + if (TASK_READY != p->state) { continue; } diff --git a/kernel/syscall.S b/kernel/syscall.S index 6526d45..d922719 100644 --- a/kernel/syscall.S +++ b/kernel/syscall.S @@ -27,13 +27,14 @@ .global syscall_entry .global ret_from_fork_user .global ret_from_fork_krnl +.extern reenter //.global syscall_exit syscall_entry: #if FIX_SYSENTER_ESP_MODE movl (%esp),%esp #endif - + // sysenter have cleared IF, and sysexit will not set IF. sti diff --git a/kernel/system.c b/kernel/system.c index 56183d9..a0ff96a 100644 --- a/kernel/system.c +++ b/kernel/system.c @@ -107,13 +107,14 @@ void setup_irqs() { void kbd_handler(unsigned int irq, pt_regs_t *regs, void *dev_id); void clk_handler(unsigned int irq, pt_regs_t *regs, void *dev_id); + void clk_bh_handler(); - request_irq(0x00, clk_handler, "Intel 8254", "Clock Chip"); - request_irq(0x01, kbd_handler, "Intel 8042", "PS/2 Keyboard"); + request_irq(0x00, clk_handler, clk_bh_handler, "Intel 8254", "Clock Chip"); + request_irq(0x01, kbd_handler, NULL, "Intel 8042", "PS/2 Keyboard"); // request_irq(0x0E, default_ide_irq_handler, "hard", "IDE"); for (int i = 0; i < 16; i++) { if (i != 0 && i != 1 && i != 10 && i != 14) { - request_irq(i, default_irq_handler, "default", "default"); + request_irq(i, default_irq_handler, NULL, "default", "default"); } } @@ -192,4 +193,4 @@ Desc gdt[NGDT] __attribute__((__aligned__(8))); char gdtr[6] __attribute__((__aligned__(4))); char idtr[6] __attribute__((__aligned__(4))); -volatile int irq_reenter = 0x00; \ No newline at end of file +volatile int reenter = -1; \ No newline at end of file diff --git a/kernel/task_init.c b/kernel/task_init.c index 3e5e9bd..fbc0c03 100644 --- a/kernel/task_init.c +++ b/kernel/task_init.c @@ -19,7 +19,7 @@ void init_task_entry() { setup_under_irq(); while (1) { - asm("hlt;"); + asm("sti;hlt;"); sysc_wait(2); } } diff --git a/kernel/wait.c b/kernel/wait.c index acbc179..016792d 100644 --- a/kernel/wait.c +++ b/kernel/wait.c @@ -130,7 +130,7 @@ int sysc_wait(unsigned long cnt) { irq_save(flags); current->state = TASK_WAIT; current->delay_jiffies = jiffies + cnt; - + list_add(¤t->pend, &delay_tasks); irq_restore(flags); schedule();