From: acevest Date: Sun, 28 May 2023 14:33:35 +0000 (+0800) Subject: 避免嵌套情况下底半处理丢失的问题 X-Git-Url: http://zhaoyanbai.com/repos/%22http:/www.isc.org/icons/named.html?a=commitdiff_plain;h=cc3f986cd5208859d12b127cd117c7b187be8748;p=kernel.git 避免嵌套情况下底半处理丢失的问题 --- diff --git a/drivers/ide.c b/drivers/ide.c index 196952d..30fa230 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, NULL, "hard", "IDE"); + request_irq(0x0E, ide_irq_handler, "hard", "IDE"); // init_pci_controller(0x0106); init_pci_controller(0x0101); diff --git a/include/irq.h b/include/irq.h index 59b4471..034ca1a 100644 --- a/include/irq.h +++ b/include/irq.h @@ -32,7 +32,6 @@ 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; @@ -45,13 +44,19 @@ typedef struct irq_desc { unsigned int depth; } irq_desc_t; +typedef struct irq_bh_action { + void (*handler)(); + struct irq_bh_action *next; +} irq_bh_action_t; + extern irq_chip_t i8259_chip; 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 *), void (*bh_handler)(), const char *devname, - void *dev_id); + void (*handler)(unsigned int, pt_regs_t *, void *), const char *devname, void *dev_id); + +void add_irq_bh_handler(void (*handler)()); int open_irq(unsigned int irq); int close_irq(unsigned int irq); diff --git a/kernel/clock.c b/kernel/clock.c index 731cf60..7b58c5e 100644 --- a/kernel/clock.c +++ b/kernel/clock.c @@ -23,6 +23,7 @@ unsigned int sys_clock() { return jiffies; } void debug_print_all_tasks(); void dump_irq_nr_stack(); +void clk_bh_handler(); void clk_handler(unsigned int irq, pt_regs_t *regs, void *dev_id) { // if (jiffies % 100 == 0) { printl(MPL_CLOCK, "clock irq: %d", jiffies); @@ -42,6 +43,8 @@ void clk_handler(unsigned int irq, pt_regs_t *regs, void *dev_id) { } assert(current->ticks <= TASK_MAX_PRIORITY); // 防止ticks被减到0后再减溢出 + + add_irq_bh_handler(clk_bh_handler); } // 开中断执行这个函数 diff --git a/kernel/irq.c b/kernel/irq.c index b7a093c..1557343 100644 --- a/kernel/irq.c +++ b/kernel/irq.c @@ -22,13 +22,8 @@ #include irq_desc_t irq_desc[NR_IRQS]; - -int enable_no_irq_chip(unsigned int irq) { return 0; } -int disable_no_irq_chip(unsigned int irq) { return 0; } - -irq_chip_t no_irq_chip = {.name = "none", .enable = enable_no_irq_chip, .disable = disable_no_irq_chip}; - -irq_desc_t no_irq_desc = {.chip = &no_irq_chip, .action = NULL, .status = 0, .depth = 0}; +irq_bh_action_t *irq_bh_actions = NULL; +irq_bh_action_t *irq_bh_actions_end = NULL; #if 0 unsigned int irq_nr_stack[64] = {1, 2, 3, 4}; @@ -79,6 +74,8 @@ void dump_irq_nr_stack() { } #endif +void irq_bh_handler(); + __attribute__((regparm(1))) void irq_handler(pt_regs_t *regs) { unsigned int irq = regs->irq; if (irq >= NR_IRQS) { @@ -127,13 +124,7 @@ __attribute__((regparm(1))) void irq_handler(pt_regs_t *regs) { { enable_irq(); - action = p->action; - while (action) { - if (action->bh_handler != NULL) { - action->bh_handler(); - } - action = action->next; - } + irq_bh_handler(); disable_irq(); } @@ -152,8 +143,45 @@ __attribute__((regparm(1))) void irq_handler(pt_regs_t *regs) { schedule(); } -int request_irq(unsigned int irq, void (*handler)(unsigned int, pt_regs_t *, void *), void (*bh_handler)(), - const char *devname, void *dev_id) { +extern uint32_t jiffies; +void irq_bh_handler() { + uint32_t end = jiffies + 2; + while (true) { + irq_bh_action_t *action = NULL; + + disable_irq(); + + action = irq_bh_actions; + irq_bh_actions = NULL; + irq_bh_actions_end = NULL; + + enable_irq(); + + if (action == NULL) { + break; + } + + while (action != NULL) { + action->handler(); + irq_bh_action_t *p = action; + action = action->next; + kfree(p); + } + + if (jiffies >= end) { + break; + } + + // 这里可能存在有部分没处理完 + } + + // 这之后也可能存在再次被中断加入下半部处理请求 + // 但这些都不会丢失 + // 而是会延迟到这次中断返回后下一次的中断的下半部分处理逻辑 +} + +int request_irq(unsigned int irq, void (*handler)(unsigned int, pt_regs_t *, void *), const char *devname, + void *dev_id) { irq_action_t *p; if (irq >= NR_IRQS) { @@ -180,7 +208,6 @@ 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; @@ -191,6 +218,31 @@ int request_irq(unsigned int irq, void (*handler)(unsigned int, pt_regs_t *, voi return 0; } +void add_irq_bh_handler(void (*handler)()) { + // 只能在中断处理函数中调用 + assert(irq_disabled()); + + irq_bh_action_t *p; + p = (irq_bh_action_t *)kmalloc(sizeof(irq_bh_action_t), 0); + assert(p != NULL); + + p->handler = handler; + + if (irq_bh_actions_end == NULL) { + assert(irq_bh_actions == NULL); + irq_bh_actions = p; + irq_bh_actions_end = p; + + } else { + assert(irq_bh_actions != NULL); + irq_bh_actions_end->next = p; + irq_bh_actions_end = p; + } + p->next = NULL; + + irq_bh_actions = p; +} + int open_irq(unsigned int irq) { return irq_desc[irq].chip->enable(irq); } int close_irq(unsigned int irq) { return irq_desc[irq].chip->disable(irq); } @@ -206,4 +258,10 @@ bool irq_enabled() { return false; } -bool irq_disabled() { return !irq_enabled(); } \ No newline at end of file +bool irq_disabled() { return !irq_enabled(); } + +int enable_no_irq_chip(unsigned int irq) { return 0; } +int disable_no_irq_chip(unsigned int irq) { return 0; } + +irq_chip_t no_irq_chip = {.name = "none", .enable = enable_no_irq_chip, .disable = disable_no_irq_chip}; +irq_desc_t no_irq_desc = {.chip = &no_irq_chip, .action = NULL, .status = 0, .depth = 0}; diff --git a/kernel/setup.c b/kernel/setup.c index 5af3618..cd8802b 100644 --- a/kernel/setup.c +++ b/kernel/setup.c @@ -65,7 +65,7 @@ void setup_kernel() { setup_gate(); set_tss(); - setup_i8253(20); + setup_i8253(100); setup_sysc(); diff --git a/kernel/system.c b/kernel/system.c index a0ff96a..53b72dd 100644 --- a/kernel/system.c +++ b/kernel/system.c @@ -109,12 +109,12 @@ void setup_irqs() { void clk_handler(unsigned int irq, pt_regs_t *regs, void *dev_id); void clk_bh_handler(); - 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(0x00, clk_handler, "Intel 8254", "Clock Chip"); + request_irq(0x01, kbd_handler, "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, NULL, "default", "default"); + request_irq(i, default_irq_handler, "default", "default"); } } diff --git a/scripts/link.ld b/scripts/link.ld index 3a38a78..7d6272c 100644 --- a/scripts/link.ld +++ b/scripts/link.ld @@ -29,7 +29,7 @@ SECTIONS boot/multiboot.S.o(.text) *(.multiboot2_header) *(.text) - *(.ring3.text); + *(.ring3.text); *(.sysexit) /* last */ } etext = .;