[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[tyndur-devel] [PATCH v2] IRQ-Sharing



From: Max Reitz <max@xxxxxxxxxx>

* Mit dem Makro MAX_INTERRUPTS in intr.c kann man jetzt die
  maximale Anzahl von Handlern pro IRQ definieren

Signed-off-by: Max Reitz <max@xxxxxxxxxx>
---
 src/kernel/src/intr.c |   99 ++++++++++++++++++++++++++++++++-----------------
 1 files changed, 65 insertions(+), 34 deletions(-)

diff --git a/src/kernel/src/intr.c b/src/kernel/src/intr.c
index 9fa3ff3..2a56e64 100644
--- a/src/kernel/src/intr.c
+++ b/src/kernel/src/intr.c
@@ -55,6 +55,8 @@
 #include "vm86.h"
 #include "tss.h"
 
+#define MAX_INTERRUPTS 4
+
 typedef struct {
   word lsb_handler;
   word selector;
@@ -65,8 +67,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 };
+pfIrqHandler irq_handlers[16] = { 0 }; // f�r jeden IRQ genau ein Handler. Wenn es keinen Handler gibt, ist der entsprechende Wert 0.
+static struct task * intr_handling_task[256][MAX_INTERRUPTS] = { { NULL } };
 
 void handle_irq(int irq, dword* esp);
 
@@ -116,17 +118,17 @@ extern void stack_backtrace_ebp(dword start_ebp, dword start_eip);
 void handle_exception(dword* esp);
 
 void send_irqs(dword* esp);
-dword irqs_to_send[16];
+static dword irqs_to_send[16][MAX_INTERRUPTS];
 extern dword kernel_pd_id;
 
 /*
- * gibt einen neuen Wert für esp zurck
+ * gibt einen neuen Wert f�r esp zurck
  */
 dword handle_int(dword esp)
 {
     struct int_stack_frame * isf = (struct int_stack_frame *)esp;
     struct task* old_task = current_task;
-    
+
 //	kprintf("\nTask switch!  esp alter Task:0x%08x", isf->esp);
 	
 	if(isf->interrupt_number <= 31)
@@ -146,7 +148,7 @@ dword handle_int(dword esp)
     }
     else
     {
-        // TODO: Abstürzen, denn diese Interrupts dürften nicht aufgerufen werden
+        // TODO: Abst�rzen, denn diese Interrupts d�rften nicht aufgerufen werden
     }
 
     send_irqs(&esp);
@@ -158,7 +160,7 @@ dword handle_int(dword esp)
         //tss.esp = current_task->kernel_stack;
         isf = (struct int_stack_frame *)esp;
         //kprintf("  esp neuer Task:0x%08x", isf->esp);
-        
+
         tss.esp0 = current_task->kernel_stack;
         // sicherstellen, dass der Kernel Adressraum im Page Directory des Tasks korrekt gemappt ist
         //kprintf("PID=%d  cr3=0x%08x  kernel_pd=0x%08x eip=0x%08x\n", 
@@ -186,8 +188,8 @@ 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.
+ * Eintr�ge werden mit Verweisen auf den Null-Handler initalisiert.
+ * Anschlie�end wird die IDT geladen.
  */
 void init_idt() {
   int i;
@@ -265,9 +267,9 @@ void init_idt() {
   outb_wait(PIC1_DATA, 0x00);
   outb_wait(PIC2_DATA, 0x00);
 
-  // Handler für den System Call installieren
+  // Handler f�r 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 f�r 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);
@@ -348,10 +350,12 @@ int release_irq(int irq)
 
 void handle_irq(int irq, dword* esp)
 {
+    int i;
+
     //if (irq > 0) {
     //    kprintf("Interrupt 0x%x\n", irq + IRQ_BASE);
     //}
-        
+
     /*if (irq > 0)
     {
         byte pic = (irq < 8 ? PIC1 : PIC2);
@@ -360,8 +364,8 @@ void handle_irq(int irq, dword* esp)
             kprintf("Spurious IRQ %d\n", irq);
         }
     }*/
-        
-    // IRQs 7 und 15 können unabsichtlich aufgerufen werden
+
+    // IRQs 7 und 15 k�nnen unabsichtlich aufgerufen werden
     // In diesem Fall beim PIC nachschauen, ob wirklich was zu verarbeiten 
     // ist, ansonsten gleich wieder abbrechen.
     if ((irq == 7) || (irq == 15))
@@ -377,12 +381,22 @@ void handle_irq(int irq, dword* esp)
             goto send_eoi;
         }
     }
-            
-    if (intr_handling_task[irq + IRQ_BASE] != NULL)  
+
+    for (i = 0; i < MAX_INTERRUPTS; i++) {
+        if (intr_handling_task[irq + IRQ_BASE][i] != NULL) {
+            i = -1;
+            break;
+        }
+    }
+    if (i == -1)
     {
         //kprintf("IRQ-Verarbeitung durch ein Modul\n");
-        irqs_to_send[irq]++;
-    
+        for (i = 0; i < MAX_INTERRUPTS; i++) {
+            if (intr_handling_task[irq + IRQ_BASE][i] != NULL) {
+                irqs_to_send[irq][i]++;
+            }
+        }
+
         //printf("disable IRQ %d\n", irq);
         disable_irq(irq);
     } 
@@ -401,10 +415,20 @@ send_eoi:
 
 void set_intr_handling_task(byte intr, struct task * task)
 {
+    int i;
+
     //kprintf("Interrupt %d wird jetzt von Task %d behandelt\n", intr, task->pid);
-    intr_handling_task[intr] = task;
+    for (i = 0; i < MAX_INTERRUPTS; i++) {
+        if ((intr_handling_task[intr][i] == NULL) ||
+            (i == MAX_INTERRUPTS - 1))
+        {
+            intr_handling_task[intr][i] = task;
+            irqs_to_send[intr - IRQ_BASE][i] = 0;
+            break;
+        }
+    }
 }
-		
+
 void handle_exception(dword* esp)
 {
     struct int_stack_frame * isf = *((struct int_stack_frame **)esp);
@@ -426,7 +450,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
+            // Ueberpr�fen ob der Pagefault durch einen Stackoverflow
             // hervorgerufen wurde
             if ((diff >= -2) && (diff <= 2)
                 && (current_task != NULL)
@@ -439,8 +463,8 @@ void handle_exception(dword* esp)
             kprintf("\033[1;37m\033[41mPage Fault: 0x%x\033[0;37m\033[40m", cr2);
             break;
     }
-    
-    // Prüfen, ob ein VM86-Task die Exception ausgelöst hat, und evtl reagieren
+
+    // Pr�fen, ob ein VM86-Task die Exception ausgel�st hat, und evtl reagieren
     if (isf->eflags & 0x20000) {
         if (vm86_exception(esp)) {
             return;
@@ -472,7 +496,7 @@ void handle_exception(dword* esp)
             kprintf("\n");
         }
         #endif 
-        
+
         if(debug_test_flag(DEBUG_FLAG_STACK_BACKTRACE))
         {
             stack_backtrace_ebp(isf->ebp, isf->eip);
@@ -508,24 +532,31 @@ void handle_exception(dword* esp)
 
         abort_task("Unbehandelte Ausnahme.");
     }
-}        
+}
 
 void send_irqs(dword* esp) 
 {
     dword irq;
+    int task;
+
     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)) 
-            {
-                //kprintf("SYSCALL_RPC = FALSE");
-                break;
+        for (task = 0; task < MAX_INTERRUPTS; task++) {
+            if (intr_handling_task[irq + IRQ_BASE][task] == NULL) {
+                continue;
+            }
+            while (irqs_to_send[irq][task] > 0) {
+                schedule_to_task(intr_handling_task[irq + IRQ_BASE][task], esp);
+                if (!fastrpc_irq(intr_handling_task[irq + IRQ_BASE][task], 0, 0, 4, 
+                    (char*) &rpc_data, irq)) 
+                {
+                    //kprintf("SYSCALL_RPC = FALSE");
+                    break;
+                }
+                //kprintf("IRQ-Handler aufgerufen");
+                irqs_to_send[irq][task]--;
             }
-            //kprintf("IRQ-Handler aufgerufen");
-            irqs_to_send[irq]--;
         }
     }
 }
-- 
1.6.5