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

[tyndur-devel] [PATCH 3/3] cdi/core: Funktionen um auf IRQs zu warten



+ cdi/core: Zwei neue Funktionen um effizient auf IRQs zu warten
---
 src/modules/cdi/include/cdi/misc.h |   24 +++++++++++-
 src/modules/cdi/lib/misc.c         |   73 +++++++++++++++++++++++++++++++++++-
 2 files changed, 95 insertions(+), 2 deletions(-)

diff --git a/src/modules/cdi/include/cdi/misc.h b/src/modules/cdi/include/cdi/misc.h
index dc9e277..2a130f6 100644
--- a/src/modules/cdi/include/cdi/misc.h
+++ b/src/modules/cdi/include/cdi/misc.h
@@ -24,7 +24,29 @@
  */
 void cdi_register_irq(uint8_t irq, void (*handler)(struct cdi_device*), 
     struct cdi_device* device);
-    
+
+/**
+ * Setzt den IRQ-Zaehler fuer cdi_wait_irq zurueck.
+ *
+ * @param irq Nummer des IRQ
+ *
+ * @return 0 bei Erfolg, -1 im Fehlerfall
+ */
+int cdi_reset_wait_irq(uint8_t irq);
+
+/**
+ * Wartet bis der IRQ aufgerufen wurde. Der interne Zaehler muss zuerst mit
+ * cdi_reset_wait_irq zurueckgesetzt werden, damit auch die IRQs abgefangen
+ * werden koennen, die kurz vor dem Aufruf von dieser Funktion aufgerufen
+ * werden.
+ *
+ * @param irq       Nummer des IRQ auf den gewartet werden soll
+ * @param timeout   Anzahl der Millisekunden, die maximal gewartet werden sollen
+ *
+ * @return 0 wenn der irq aufgerufen wurde, -1 sonst.
+ */
+int cdi_wait_irq(uint8_t irq, uint32_t timeout);
+
 /**
  * Reserviert physisch zusammenhaengenden Speicher.
  *
diff --git a/src/modules/cdi/lib/misc.c b/src/modules/cdi/lib/misc.c
index ae66a9e..4f2c19d 100644
--- a/src/modules/cdi/lib/misc.c
+++ b/src/modules/cdi/lib/misc.c
@@ -21,6 +21,7 @@
 
 static void (*driver_irq_handler[IRQ_COUNT])(struct cdi_device*) = { NULL };
 static struct cdi_device* driver_irq_device[IRQ_COUNT] = { NULL };
+static uint8_t driver_irq_count[IRQ_COUNT] = { 0 };
 
 /**
  * Interner IRQ-Handler, der den IRQ-Handler des Treibers aufruft
@@ -33,6 +34,7 @@ static void irq_handler(uint8_t irq)
     }
 
     irq -= LOST_IRQ_OFFSET;
+    driver_irq_count[irq]++;
     if (driver_irq_handler[irq]) {
         driver_irq_handler[irq](driver_irq_device[irq]);
     }
@@ -59,7 +61,76 @@ void cdi_register_irq(uint8_t irq, void (*handler)(struct cdi_device*),
 
     register_intr_handler(LOST_IRQ_OFFSET + irq, irq_handler);
 }
-    
+
+/**
+ * Setzt den IRQ-Zaehler fuer cdi_wait_irq zurueck.
+ *
+ * @param irq Nummer des IRQ
+ *
+ * @return 0 bei Erfolg, -1 im Fehlerfall
+ */
+int cdi_reset_wait_irq(uint8_t irq)
+{
+    if (irq > IRQ_COUNT) {
+        return -1;
+    }
+
+    driver_irq_count[irq] = 0;
+    return 0;
+}
+
+// Dummy-Callback fuer den timer_register-Aufruf in cdi_wait_irq
+static void wait_irq_dummy_callback(void) { }
+
+/**
+ * Wartet bis der IRQ aufgerufen wurde. Der interne Zaehler muss zuerst mit
+ * cdi_reset_wait_irq zurueckgesetzt werden, damit auch die IRQs abgefangen
+ * werden koennen, die kurz vor dem Aufruf von dieser Funktion aufgerufen
+ * werden.
+ *
+ * @param irq       Nummer des IRQ auf den gewartet werden soll
+ * @param timeout   Anzahl der Millisekunden, die maximal gewartet werden sollen
+ *
+ * @return 0 wenn der irq aufgerufen wurde, -1 wenn eine ungueltige IRQ-Nummer
+ * angegeben wurde, -2 wenn eine nicht registrierte IRQ-Nummer angegeben wurde,
+ * und -3 im Falle eines Timeouts.
+ */
+int cdi_wait_irq(uint8_t irq, uint32_t timeout)
+{
+    uint64_t timeout_ticks;
+
+    if (irq > IRQ_COUNT) {
+        return -1;
+    }
+
+    if (!driver_irq_handler[irq]) {
+        return -2;
+    }
+
+    // Wenn der IRQ bereits gefeuert wurde, koennen wir uns ein paar Syscalls
+    // sparen
+    if (driver_irq_count [irq]) {
+        return 0;
+    }
+
+    timeout_ticks = get_tick_count() + (uint64_t) timeout * 1000;
+    timer_register(wait_irq_dummy_callback, timeout * 1000);
+
+    p();
+    while (!driver_irq_count [irq]) {
+        v_and_wait_for_rpc();
+
+        if (timeout_ticks < get_tick_count()) {
+            return -3;
+        }
+        p();
+    }
+    v();
+
+    return 0;
+}
+
+
 /**
  * Reserviert physisch zusammenhaengenden Speicher.
  *
-- 
1.6.0.6