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

[Lost] [Patch] kernel2: Userspace-IRQ-Handler



+ kernel2: Syscall add_interrupt_handler
+ kernel2: Userspace-Interrupthandling
+ kernel2: on_destroy-Eventhandler fuer Prozesse
! kernel2: Funktionsnamen in pic.h korrigiert
Index: trunk/src/kernel2/include/syscall.h
===================================================================
--- trunk.orig/src/kernel2/include/syscall.h
+++ trunk/src/kernel2/include/syscall.h
@@ -128,6 +128,9 @@ int syscall_fastrpc(pid_t callee_pid, si
 /// Von einem RPC zurueckkehren
 void syscall_fastrpc_ret(void);
 
+/// Interrupt registrieren
+void syscall_add_interrupt_handler(uint32_t intr);
+
 // Diverse
 /// Textausgabe ueber den Kernel
 void syscall_putsn(int char_count, char* source);
Index: trunk/src/kernel2/src/syscall.c
===================================================================
--- trunk.orig/src/kernel2/src/syscall.c
+++ trunk/src/kernel2/src/syscall.c
@@ -75,6 +75,8 @@ void syscall_init()
 #endif
 
     syscall_register(SYSCALL_PM_REQUEST_PORT, syscall_io_request_port, 2);
+    syscall_register(SYSCALL_ADD_INTERRUPT_HANDLER,
+        syscall_add_interrupt_handler, 1);
 
     syscall_register(SYSCALL_PUTSN, (void*) &syscall_putsn, 2);
 }
Index: trunk/src/kernel2/src/syscalls/rpc.c
===================================================================
--- trunk.orig/src/kernel2/src/syscalls/rpc.c
+++ trunk/src/kernel2/src/syscalls/rpc.c
@@ -41,6 +41,7 @@
 #include "syscall.h"
 #include "tasks.h"
 #include "cpu.h"
+#include "im.h"
 
 typedef struct {
     uintptr_t   old_eip;
@@ -50,7 +51,7 @@ typedef struct {
     dword       eflags;
     dword       eax;
 
-    dword       reenable_irq;
+    uint8_t     reenable_irq;
 
     pm_thread_t* caller;
 } rpc_t;
@@ -288,8 +289,6 @@ int syscall_fastrpc(pid_t callee_pid, si
     return 0;
 }
 
-
-#if 0
 /**
  * Führt einen RPC zur Behandlung eines IRQ durch. Der IRQ wird dabei
  * deaktiviert, solange der Handler arbeitet und erst anschlieÃ?end
@@ -298,22 +297,23 @@ int syscall_fastrpc(pid_t callee_pid, si
  *
  * @see fastrpc
  */
-bool fastrpc_irq(struct task * callee, dword metadata_size, void* metadata,
-    dword data_size, void* data, byte irq)
+bool fastrpc_irq(pm_process_t* callee, size_t metadata_size, void* metadata,
+    size_t data_size, void* data, uint8_t irq)
 {
-    if (callee->blocked_by_pid && (callee->status != TS_WAIT_FOR_RPC)) {
+    if (callee->blocked_by_pid && (callee->status != PM_STATUS_WAIT_FOR_RPC)) {
         return FALSE;
     }
 
-    if (fastrpc(callee, metadata_size, metadata, data_size, data)) {
-        rpc_t* rpc = list_get_element_at(current_task->rpcs, 0);
+    if (syscall_fastrpc(callee->pid, metadata_size, metadata, data_size, data))
+    {
+        rpc_t* rpc = list_get_element_at(
+            cpu_get_current()->thread->process->rpcs, 0);
         rpc->reenable_irq = irq;
         return TRUE;
     } else {
         return FALSE;
     }
 }
-#endif
 
 /**
  * Wird nach der Ausführung eines RPC-Handlers aufgerufen.
@@ -363,14 +363,13 @@ void syscall_fastrpc_ret(void)
     if (rpc->caller) {
         schedule_to_task(rpc->caller, (dword*) esp);
     }
+#endif
 
     // Wenn es ein IRQ-verarbeitender RPC war, den Interrupt jetzt
     // wieder aktivieren
     if (rpc->reenable_irq) {
-        //printf("reenable IRQ %d\n", rpc->reenable_irq);
-        enable_irq(rpc->reenable_irq);
+        im_enable_irq(rpc->reenable_irq);
     }
-#endif
 
     free(rpc);
 }
@@ -399,4 +398,9 @@ void rpc_destroy_task_backlinks(struct t
 
 #endif
 
+void syscall_add_interrupt_handler(uint32_t intr)
+{
+    im_add_handler(intr, cpu_get_current()->thread->process);
+}
+
 #endif
Index: trunk/src/kernel2/include/im.h
===================================================================
--- trunk.orig/src/kernel2/include/im.h
+++ trunk/src/kernel2/include/im.h
@@ -39,8 +39,10 @@
 #include <types.h>
 
 #include "cpu.h"
+#include "tasks.h"
 
 #define IM_IRQ_BASE 0x20
+#define IM_NUM_INTERRUPTS 256
 
 void im_init();
 void im_init_local();
@@ -48,8 +50,13 @@ void im_init_local();
 void im_enable();
 void im_disable();
 
+void im_enable_irq(uint8_t irq);
+void im_disable_irq(uint8_t irq);
+
 void im_end_of_interrupt(byte interrupt);
 interrupt_stack_frame_t* im_handler(interrupt_stack_frame_t* isf);
 
+bool im_add_handler(uint32_t intr, pm_process_t* handler);
+
 #endif //ifndef _IM_H_
 
Index: trunk/src/kernel2/include/tasks.h
===================================================================
--- trunk.orig/src/kernel2/include/tasks.h
+++ trunk/src/kernel2/include/tasks.h
@@ -83,8 +83,13 @@ typedef struct pm_process {
 
     /// Eine Liste von RPC-Backlinks
     list_t* rpcs;
-} pm_process_t;
 
+    /**
+     * Eine Liste von Eventhandlern, die beim Loeschen des Prozesses
+     * aufgerufen werden
+     */
+    list_t* on_destroy;
+} pm_process_t;
 
 typedef struct {
     /// Adresse des Kernelstack-Pointers
@@ -106,6 +111,7 @@ typedef struct {
     lock_t lock;
 } pm_thread_t;
 
+typedef void (*pm_process_destroy_handler)(pm_process_t* process, void* prv);
 
 /**
  * Prozessverwaltung
@@ -135,6 +141,11 @@ bool pm_block_rpc(pm_process_t* task, pi
 bool pm_unblock_rpc(pm_process_t* task, pid_t blocked_by);
 
 
+/// Handler fuer das Loeschen des Prozesses registrieren
+void pm_register_on_destroy(pm_process_t* process,
+    pm_process_destroy_handler handler, void* prv);
+
+
 /**
  * Threadverwaltung
  */
Index: trunk/src/kernel2/src/interrupts/im.c
===================================================================
--- trunk.orig/src/kernel2/src/interrupts/im.c
+++ trunk/src/kernel2/src/interrupts/im.c
@@ -42,10 +42,17 @@
 #include "tasks.h"
 #include "debug.h"
 #include "apic.h"
+#include "kernel.h"
 #include "syscall.h"
 
 extern size_t cpu_count;
 
+static pm_process_t* intr_handling_task[IM_NUM_INTERRUPTS];
+static uint32_t intr_to_send[IM_NUM_INTERRUPTS];
+
+bool fastrpc_irq(pm_process_t* callee, size_t metadata_size, void* metadata,
+    size_t data_size, void* data, uint8_t irq);
+
 /**
  * Behandelt alle Interrupts. Wird aus den Interrupt-Stubs aufgerufen.
  * 
@@ -101,6 +108,9 @@ interrupt_stack_frame_t* im_handler(inte
 
             // Einen neuen Thread holen.
             cpu_get_current()->thread = pm_scheduler_pop();
+        } else {
+            intr_to_send[int_num]++;
+            im_disable_irq(int_num - IM_IRQ_BASE);
         }
     } else if (int_num == 0x30) {
         // Syscall
@@ -131,3 +141,70 @@ interrupt_stack_frame_t* im_handler(inte
     return (interrupt_stack_frame_t*) thread->kernel_stack;
 }
 
+/**
+ * Wird beim Loeschen einen Prozesses aufgerufen. Entfernt den Prozess aus der
+ * Interrupthandlertabelle.
+ */
+static void on_process_destroy(pm_process_t* process, void* prv)
+{
+    uint32_t intr = (uint32_t) prv;
+
+    if (intr >= IM_NUM_INTERRUPTS) {
+        panic("im.c: on_process_destroy(): Korrupte Interruptnummer %d", intr);
+    }
+
+    if (intr_handling_task[intr] != process) {
+        panic("im.c: on_process_destroy(): Prozess nicht fuer Interrupt %d "
+            "zustaendig", intr);
+    }
+
+    intr_handling_task[intr] = NULL;
+}
+
+/**
+ * Registriert einen Prozess als fuer einen Interrupt zustandig
+ *
+ * @return TRUE falls der Interrupt registriert werden konnte, FALSE falls fuer
+ * ihn bereits einen Handler registriert war oder die Interruptnummer
+ * ausserhalb des zulaessigen Bereichs liegt.
+ *
+ * TODO Mehrere Handler fuer einen Interrupt unterstuetzen
+ */
+bool im_add_handler(uint32_t intr, pm_process_t* handler)
+{
+    if ((intr >= IM_NUM_INTERRUPTS) || intr_handling_task[intr]) {
+        return FALSE;
+    }
+
+    intr_handling_task[intr] = handler;
+    pm_register_on_destroy(handler, on_process_destroy, (void*) intr);
+
+    return TRUE;
+}
+
+/**
+ * Ruft die Handler ausstehender Interrupts auf
+ */
+void im_send_interrupts(void)
+{
+    uint32_t intr;
+
+    for (intr = 0; intr < IM_NUM_INTERRUPTS; intr++)
+    {
+        while (intr_to_send[intr] > 0) {
+            if (intr_handling_task[intr] == NULL) {
+                intr_to_send[intr] = 0;
+                break;
+            }
+
+            // TODO schedule_to_task(intr_handling_task[intr], esp);
+
+            if (!fastrpc_irq(intr_handling_task[intr], 0, 0,
+                sizeof(intr), (char*) &intr, intr - IM_IRQ_BASE))
+            {
+                break;
+            }
+            intr_to_send[intr]--;
+        }
+    }
+}
Index: trunk/src/kernel2/src/tasks/pm.c
===================================================================
--- trunk.orig/src/kernel2/src/tasks/pm.c
+++ trunk/src/kernel2/src/tasks/pm.c
@@ -41,6 +41,12 @@
 #include "tasks.h"
 #include "lock.h"
 
+
+struct on_destroy_info {
+    pm_process_destroy_handler handler;
+    void* prv;
+};
+
 /// Liste mit allen Prozessen
 static list_t* process_list;
 
@@ -91,6 +97,9 @@ pm_process_t* pm_create(pm_process_t* pa
         return NULL;
     }
 
+    // Eventhandlerlisten anlegen
+    process->on_destroy = list_create();
+
     // Dem Prozess eine ID zuordnen
     process->pid = generate_pid();
 
@@ -141,9 +150,18 @@ pm_process_t* pm_create(pm_process_t* pa
  */
 void pm_destroy(pm_process_t* process)
 {
+    struct on_destroy_info* info;
+
     // Den Prozess blockieren
     while (pm_block(process) == FALSE);
 
+    // Eventhandler ausfuehren
+    while ((info = list_pop(process->on_destroy))) {
+        info->handler(process, info->prv);
+        free(info);
+    }
+    list_destroy(process->on_destroy);
+
     // RPC-Strukturen freigeben
     // TODO Die einzelnen Listenglieder freigeben
     list_destroy(process->rpcs);
@@ -296,3 +314,17 @@ bool pm_unblock_rpc(pm_process_t* task,
         return FALSE;
     }
 }
+
+/**
+ * Handler fuer das Loeschen des Prozesses registrieren
+ */
+void pm_register_on_destroy(pm_process_t* process,
+    pm_process_destroy_handler handler, void* prv)
+{
+    struct on_destroy_info* info = malloc(sizeof(*info));
+
+    info->handler = handler;
+    info->prv = prv;
+
+    list_push(process->on_destroy, info);
+}
Index: trunk/src/kernel2/include/pic.h
===================================================================
--- trunk.orig/src/kernel2/include/pic.h
+++ trunk/src/kernel2/include/pic.h
@@ -39,8 +39,8 @@
 #include <types.h>
 
 void pic_init(byte irq_base);
-void pic_mask(byte irq);
-void pic_unmask(byte irq);
+void pic_enable_irq(byte irq);
+void pic_disable_irq(byte irq);
 void pic_eoi(byte irq);
 
 #endif //ifndef _PIC_H_