From 135b9d80095d4000442e0af401b29f71698c7122 Mon Sep 17 00:00:00 2001 From: Matheus Date: Sun, 25 Jun 2023 19:56:33 -0300 Subject: [PATCH] interrupts: interrupt_raise --- kernel-src/include/kernel/interrupt.h | 1 + kernel-src/sys/interrupt.c | 37 +++++++++++++++++---------- 2 files changed, 25 insertions(+), 13 deletions(-) diff --git a/kernel-src/include/kernel/interrupt.h b/kernel-src/include/kernel/interrupt.h index 8baf9b26..12f90221 100644 --- a/kernel-src/include/kernel/interrupt.h +++ b/kernel-src/include/kernel/interrupt.h @@ -33,5 +33,6 @@ isr_t *interrupt_allocate(void (*func)(isr_t *self, context_t *ctx), void (*eoi) long interrupt_loweripl(long newipl); long interrupt_raiseipl(long ipl); bool interrupt_set(bool status); +void interrupt_raise(isr_t *isr); #endif diff --git a/kernel-src/sys/interrupt.c b/kernel-src/sys/interrupt.c index 00f8ec7c..980d54b7 100644 --- a/kernel-src/sys/interrupt.c +++ b/kernel-src/sys/interrupt.c @@ -29,6 +29,15 @@ static void insertinqueue(isr_t *isr) { _cpu()->isrqueue = isr; } +static void runisr(isr_t *isr, context_t *ctx) { + long oldipl = interrupt_raiseipl(isr->priority); + + isr->func(isr, ctx); + interrupt_set(false); + + interrupt_loweripl(oldipl); +} + static void dopending(context_t *ctx) { bool entrystatus = _cpu()->intstatus; if (entrystatus) { @@ -40,7 +49,6 @@ static void dopending(context_t *ctx) { isr_t *iterator = _cpu()->isrqueue; // build a list of pending ISRs and remove them from the main queue - while (iterator) { isr_t *next = iterator->next; if (_cpu()->ipl > iterator->priority) { @@ -70,12 +78,7 @@ static void dopending(context_t *ctx) { list->prev = NULL; isr->pending = false; - long oldipl = interrupt_raiseipl(isr->priority); - - isr->func(isr, ctx); - interrupt_set(false); - - interrupt_loweripl(oldipl); + runisr(isr, ctx); // if any new interrupts are pending, they will be taken care of here // XXX this is kinda hacky could be very very bad if there are a lot of interrupts @@ -98,12 +101,7 @@ void interrupt_isr(int vec, context_t *ctx) { _panic("Unregistered interrupt", ctx); if (_cpu()->ipl > isr->priority) { - long oldipl = interrupt_raiseipl(isr->priority); - - isr->func(isr, ctx); - interrupt_set(false); - - interrupt_loweripl(oldipl); + runisr(isr, ctx); dopending(ctx); } else { insertinqueue(isr); @@ -116,6 +114,19 @@ void interrupt_isr(int vec, context_t *ctx) { _cpu()->intstatus = ARCH_CONTEXT_INTSTATUS(ctx); } +void interrupt_raise(isr_t *isr) { + bool entrystate = interrupt_set(false); + + if (isr->pending) + goto cleanup; + + insertinqueue(isr); + isr->pending = true; + + cleanup: + interrupt_set(entrystate); +} + void interrupt_register(int vector, void (*func)(isr_t *self, context_t *ctx), void (*eoi)(isr_t *self), long priority) { isr_t *isr = &_cpu()->isr[vector]; isr->func = func;