[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [tyndur-devel] [PATCH] Mehrere ISRs pro IRQ
On Sun, Aug 30, 2009 at 01:53:22PM +0200, max@xxxxxxxxxx wrote:
> From: Max Reitz <max@xxxxxxxxxx>
>
> Signed-off-by: Max Reitz <max@xxxxxxxxxx>
> ---
> src/kernel/src/intr.c | 76 +++++++++++++++++++++++++++++++------------------
> 1 files changed, 48 insertions(+), 28 deletions(-)
>
> diff --git a/src/kernel/src/intr.c b/src/kernel/src/intr.c
> index 9fa3ff3..be90e8c 100644
> --- a/src/kernel/src/intr.c
> +++ b/src/kernel/src/intr.c
> @@ -38,6 +38,7 @@
> */
>
> #include "cpu.h"
> +#include <collections.h>
> #include "ports.h"
> #include "types.h"
> #include "kernel.h"
> @@ -65,8 +66,8 @@ typedef struct {
>
> gate_descriptor idt[IDT_SIZE];
>
> -pfIrqHandler irq_handlers[16] = { 0 }; // f?r jeden IRQ genau ein Handler. Wenn es keinen Handler gibt, ist der entsprechende Wert 0.
> -struct task * intr_handling_task[256] = { NULL };
> +static list_t* irq_handlers[16] = { NULL };
> +list_t* intr_handling_task[256] = { NULL };
Der kann auch static sein, wenn wir schon dabei sind, oder?
>
> void handle_irq(int irq, dword* esp);
>
> @@ -120,7 +121,7 @@ dword irqs_to_send[16];
> extern dword kernel_pd_id;
>
> /*
> - * gibt einen neuen Wert f?r esp zurck
> + * gibt einen neuen Wert fuer esp zurck
> */
> dword handle_int(dword esp)
> {
> @@ -146,7 +147,7 @@ dword handle_int(dword esp)
> }
> else
> {
> - // TODO: Abst?rzen, denn diese Interrupts d?rften nicht aufgerufen werden
> + // TODO: Abstuerzen, denn diese Interrupts duerften nicht aufgerufen werden
> }
>
> send_irqs(&esp);
> @@ -186,11 +187,11 @@ dword handle_int(dword esp)
>
> /**
> * Legt eine IDT an und installiert die Exception Handler. Nicht genutzte
> - * Eintr?ge werden mit Verweisen auf den Null-Handler initalisiert.
> - * Anschlie?end wird die IDT geladen.
> + * Eintraege werden mit Verweisen auf den Null-Handler initalisiert.
> + * Anschliessend wird die IDT geladen.
> */
> void init_idt() {
> - int i;
> + int i;
Die Einrückung ist vorher und nachher nicht korrekt. ;-)
>
> // Tabelle initialisieren
> for (i = 0; i < IDT_SIZE; i++)
> @@ -198,7 +199,7 @@ void init_idt() {
> set_intr(i, 0x08, &null_handler, 0, IDT_INTERRUPT_GATE);
> }
>
> - // Register befllen
> + // Register befuellen
> struct {
> word size;
> dword base;
> @@ -265,9 +266,9 @@ void init_idt() {
> outb_wait(PIC1_DATA, 0x00);
> outb_wait(PIC2_DATA, 0x00);
>
> - // Handler f?r den System Call installieren
> + // Handler fuer den System Call installieren
> // TODO: SOllte eigentlich ein IDT_TRAP_GATE sein, aber irgendwo ist da
> - // noch ein Problem, das dann f?r einen Page Fault sorgt, wenn ich zu
> + // noch ein Problem, das dann fuer einen Page Fault sorgt, wenn ich zu
> // schnell tippe...
> set_intr(SYSCALL_INTERRUPT, 0x08, syscall_stub, 3, IDT_INTERRUPT_GATE);
> //set_intr(SYSCALL_INTERRUPT, 0x08, syscall_stub, 3, IDT_TRAP_GATE);
> @@ -323,26 +324,29 @@ int request_irq(int irq, void * handler)
> return 1;
> }
>
> - if(irq_handlers[irq] != 0)
> - {
> - return 1;
> + if (irq_handlers[irq] == NULL) {
> + irq_handlers[irq] = list_create();
> }
>
> - irq_handlers[irq] = handler;
> + list_push(irq_handlers[irq], handler);
>
> return 0;
> }
>
> int release_irq(int irq)
> {
> - if(irq < 0 || irq > 15)
> + /*if(irq < 0 || irq > 15)
> {
> return 1;
> }
>
> irq_handlers[irq] = 0;
>
> - return 0;
> + return 0;*/
> +
> + //FIXME Ich weiss ja nicht, wer das braucht. Aber wenn es noetig ist, dann
> + //muesste man das in release_irq(int irq, void* handler) oder sowas aendern
> + return 1;
> }
Dann änder den Prototypen eben ab. FIXMEs für triviale Sachen mag ich
nicht so.
>
>
> @@ -361,7 +365,7 @@ void handle_irq(int irq, dword* esp)
> }
> }*/
>
> - // IRQs 7 und 15 k?nnen unabsichtlich aufgerufen werden
> + // IRQs 7 und 15 koennen unabsichtlich aufgerufen werden
> // In diesem Fall beim PIC nachschauen, ob wirklich was zu verarbeiten
> // ist, ansonsten gleich wieder abbrechen.
> if ((irq == 7) || (irq == 15))
> @@ -386,9 +390,16 @@ void handle_irq(int irq, dword* esp)
> //printf("disable IRQ %d\n", irq);
> disable_irq(irq);
> }
> - else if (irq_handlers[irq] != 0)
> + else if (irq_handlers[irq] != NULL)
else if ist jetzt nicht mehr richtig. Es könnte sowohl für den Kernel
als auch für ein Modul ein Handler installiert sein.
> {
> - irq_handlers[irq](irq, esp);
> + int i;
> + pfIrqHandler handler;
> +
> + for (i = 0; (handler = list_get_element_at(irq_handlers[irq], i))
> + != NULL; i++)
> + {
> + handler(irq, esp);
> + }
> }
>
> send_eoi:
> @@ -402,7 +413,10 @@ send_eoi:
> void set_intr_handling_task(byte intr, struct task * task)
> {
> //kprintf("Interrupt %d wird jetzt von Task %d behandelt\n", intr, task->pid);
> - intr_handling_task[intr] = task;
> + if (intr_handling_task[intr] == NULL) {
> + intr_handling_task[intr] = list_create();
> + }
> + list_push(intr_handling_task[intr], task);
> }
>
> void handle_exception(dword* esp)
> @@ -426,7 +440,7 @@ void handle_exception(dword* esp)
> case 14:
> cr2 = read_cr2();
> diff = (cr2 >> PAGE_SHIFT) - (isf->esp >> PAGE_SHIFT);
> - // Ueberpr?fen ob der Pagefault durch einen Stackoverflow
> + // Ueberpruefen, ob der Pagefault durch einen Stackoverflow
> // hervorgerufen wurde
> if ((diff >= -2) && (diff <= 2)
> && (current_task != NULL)
> @@ -440,7 +454,7 @@ void handle_exception(dword* esp)
> break;
> }
>
> - // Pr?fen, ob ein VM86-Task die Exception ausgel?st hat, und evtl reagieren
> + // Pruefen, ob ein VM86-Task die Exception ausgeloest hat, und evtl reagieren
> if (isf->eflags & 0x20000) {
> if (vm86_exception(esp)) {
> return;
> @@ -512,19 +526,25 @@ void handle_exception(dword* esp)
>
> void send_irqs(dword* esp)
> {
> + int i;
> + struct task* tsk;
> dword irq;
> for (irq = 0; irq < 16; irq++)
> {
> dword rpc_data = irq + IRQ_BASE;
> while (irqs_to_send[irq] > 0) {
> - schedule_to_task(intr_handling_task[irq + IRQ_BASE], esp);
> - if (!fastrpc_irq(intr_handling_task[irq + IRQ_BASE], 0, 0, 4,
> - (char*) &rpc_data, irq))
> + for (i = 0; (tsk = list_get_element_at(
> + intr_handling_task[irq + IRQ_BASE], i)) != NULL; i++)
> {
> - //kprintf("SYSCALL_RPC = FALSE");
> - break;
> + schedule_to_task(tsk, esp);
> + if (!fastrpc_irq(tsk, 0, 0, 4,
> + (char*) &rpc_data, irq))
Der Zeilenumbruch kommt mir überflüssig vor
> + {
> + //kprintf("SYSCALL_RPC = FALSE");
> + break;
Wenn der zweite IRQ-Handler beim ersten Versuch scheitert, wird der
erste Handler zweimal aufgerufen. Bin mir aber nicht sicher, ob es sich
lohnt, das zu fixen - die Treiber müssen eh damit umgehen können, wenn
zu viele Interrupts kommen.