[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[tyndur-devel] [PATCH v2] kernel2: IRQ-Sharing (Bug 79)
! Ein IRQ sollte erst dann demaskiert werden, wenn alle RPCs, die ihn
behandeln, zurückgekehrt sind.
Signed-off-by: Max Reitz <max@xxxxxxxxxx>
---
src/kernel2/include/im.h | 12 ++++++++++++
src/kernel2/src/interrupts/im.c | 25 +++++++++++++++++++++++++
src/kernel2/src/syscalls/rpc.c | 4 +++-
3 files changed, 40 insertions(+), 1 deletions(-)
diff --git a/src/kernel2/include/im.h b/src/kernel2/include/im.h
index 05f7200..23ccf22 100644
--- a/src/kernel2/include/im.h
+++ b/src/kernel2/include/im.h
@@ -54,6 +54,18 @@ void im_disable(void);
void im_enable_irq(uint8_t irq);
void im_disable_irq(uint8_t irq);
+/**
+ * Zeigt an, dass ein RPC zu einem Task ausgelöst wurde, der den entsprechenden
+ * IRQ verarbeiten soll.
+ */
+void im_irq_handlers_increment(uint8_t irq);
+/**
+ * Zeigt an, dass solch ein RPC beendet wurde. Ist die Zahl der Tasks, die sich
+ * um diesen IRQ kümmern, auf 0 gesunken, kann der IRQ wieder per im_enable_irq
+ * zugelassen werden.
+ */
+void im_irq_handlers_decrement(uint8_t irq);
+
void im_end_of_interrupt(uint8_t interrupt);
interrupt_stack_frame_t* im_handler(interrupt_stack_frame_t* isf);
interrupt_stack_frame_t* im_prepare_current_thread(void);
diff --git a/src/kernel2/src/interrupts/im.c b/src/kernel2/src/interrupts/im.c
index 97862ac..f22498a 100644
--- a/src/kernel2/src/interrupts/im.c
+++ b/src/kernel2/src/interrupts/im.c
@@ -34,6 +34,7 @@
*/
#include <stdbool.h>
+#include <lock.h>
#include <types.h>
#include <lost/config.h>
@@ -67,6 +68,12 @@ static int intr_num_tasks[IM_NUM_INTERRUPTS];
// Interrupt 0 sind, sonst true).
static bool any_intr[IM_NUM_INTERRUPTS];
+// Anzahl von Tasks, die sich gerade um einen bestimmten IRQ kümmern (zu denen
+// also ein fastrpc_irq ausgeführt wurde und noch nicht beendet ist)
+static uint32_t intr_active_tasks[IM_NUM_INTERRUPTS];
+// Ein Lock für dieses Array
+static lock_t intr_active_tasks_lock = LOCK_UNLOCKED;
+
void im_send_interrupts(void);
bool fastrpc_irq(pm_process_t* callee, size_t metadata_size, void* metadata,
size_t data_size, void* data, uint8_t irq);
@@ -373,3 +380,20 @@ void im_send_interrupts(void)
pm_scheduler_try_switch(new_thread);
}
}
+
+void im_irq_handlers_increment(uint8_t irq)
+{
+ locked_increment(&intr_active_tasks[irq]);
+}
+
+void im_irq_handlers_decrement(uint8_t irq)
+{
+ lock(&intr_active_tasks_lock);
+
+ if (--intr_active_tasks[irq] <= 0) {
+ intr_active_tasks[irq] = 0;
+ im_enable_irq(irq);
+ }
+
+ unlock(&intr_active_tasks_lock);
+}
diff --git a/src/kernel2/src/syscalls/rpc.c b/src/kernel2/src/syscalls/rpc.c
index 382c882..1b57ae0 100644
--- a/src/kernel2/src/syscalls/rpc.c
+++ b/src/kernel2/src/syscalls/rpc.c
@@ -325,6 +325,8 @@ bool fastrpc_irq(pm_process_t* callee, size_t metadata_size, void* metadata,
return false;
}
+ im_irq_handlers_increment(irq);
+
rpc_t* rpc = list_get_element_at(callee->rpcs, 0);
rpc->reenable_irq = irq;
@@ -381,7 +383,7 @@ void syscall_fastrpc_ret(void)
// Wenn es ein IRQ-verarbeitender RPC war, den Interrupt jetzt
// wieder aktivieren
if (rpc->reenable_irq) {
- im_enable_irq(rpc->reenable_irq);
+ im_irq_handlers_decrement(rpc->reenable_irq);
}
free(rpc);
--
1.7.4.4