mirror of
https://gitlab.com/sortix/sortix.git
synced 2023-02-13 20:55:38 -05:00
Refactor interrupt handler registration.
This commit is contained in:
parent
ede6d8f800
commit
59262f6bf2
6 changed files with 76 additions and 24 deletions
|
@ -415,6 +415,9 @@ static void UARTIRQHandler(struct interrupt_context* /*intctx*/, void* /*user*/)
|
|||
}
|
||||
}
|
||||
|
||||
static struct interrupt_handler irq3_handler;
|
||||
static struct interrupt_handler irq4_handler;
|
||||
|
||||
void Init(const char* devpath, Ref<Descriptor> slashdev)
|
||||
{
|
||||
ioctx_t ctx; SetupKernelIOCtx(&ctx);
|
||||
|
@ -434,8 +437,11 @@ void Init(const char* devpath, Ref<Descriptor> slashdev)
|
|||
PanicF("Unable to link %s/%s to COM port driver.", devpath, name);
|
||||
}
|
||||
|
||||
Interrupt::RegisterHandler(Interrupt::IRQ3, UARTIRQHandler, NULL);
|
||||
Interrupt::RegisterHandler(Interrupt::IRQ4, UARTIRQHandler, NULL);
|
||||
irq3_handler.handler = UARTIRQHandler;
|
||||
irq4_handler.handler = UARTIRQHandler;
|
||||
|
||||
Interrupt::RegisterHandler(Interrupt::IRQ3, &irq3_handler);
|
||||
Interrupt::RegisterHandler(Interrupt::IRQ4, &irq4_handler);
|
||||
|
||||
// Initialize the ports so we can transfer data.
|
||||
for ( size_t i = 1; i <= NUMCOMPORTS; i++ )
|
||||
|
|
|
@ -31,6 +31,21 @@
|
|||
#include <sortix/kernel/registers.h>
|
||||
|
||||
namespace Sortix {
|
||||
|
||||
struct interrupt_context;
|
||||
|
||||
struct interrupt_handler
|
||||
{
|
||||
void (*handler)(struct interrupt_context*, void*);
|
||||
void* context;
|
||||
struct interrupt_handler* next;
|
||||
struct interrupt_handler* prev;
|
||||
};
|
||||
|
||||
} // namespace Sortix
|
||||
|
||||
namespace Sortix {
|
||||
|
||||
namespace Interrupt {
|
||||
|
||||
#if defined(__i386__) || defined(__x86_64__)
|
||||
|
@ -100,9 +115,8 @@ inline bool SetEnabled(bool is_enabled)
|
|||
return wasenabled;
|
||||
}
|
||||
|
||||
|
||||
typedef void (*Handler)(struct interrupt_context* intctx, void* user);
|
||||
void RegisterHandler(unsigned int index, Handler handler, void* user);
|
||||
void RegisterHandler(unsigned int index, struct interrupt_handler* handler);
|
||||
void UnregisterHandler(unsigned int index, struct interrupt_handler* handler);
|
||||
|
||||
void Init();
|
||||
void InitWorker();
|
||||
|
|
|
@ -76,7 +76,9 @@ PS2Keyboard::PS2Keyboard(uint16_t iobase, uint8_t interrupt)
|
|||
this->leds = 0;
|
||||
this->scancodeescaped = false;
|
||||
this->kblock = KTHREAD_MUTEX_INITIALIZER;
|
||||
Interrupt::RegisterHandler(interrupt, PS2Keyboard__OnInterrupt, this);
|
||||
interrupt_registration.handler = PS2Keyboard__OnInterrupt;
|
||||
interrupt_registration.context = this;
|
||||
Interrupt::RegisterHandler(interrupt, &interrupt_registration);
|
||||
|
||||
// If any scancodes were already pending, our interrupt handler will
|
||||
// never be called. Let's just discard anything pending.
|
||||
|
@ -85,7 +87,7 @@ PS2Keyboard::PS2Keyboard(uint16_t iobase, uint8_t interrupt)
|
|||
|
||||
PS2Keyboard::~PS2Keyboard()
|
||||
{
|
||||
Interrupt::RegisterHandler(interrupt, NULL, NULL);
|
||||
Interrupt::RegisterHandler(interrupt, &interrupt_registration);
|
||||
delete[] queue;
|
||||
}
|
||||
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <sortix/kernel/interrupt.h>
|
||||
#include <sortix/kernel/kthread.h>
|
||||
#include <sortix/kernel/keyboard.h>
|
||||
|
||||
|
@ -56,6 +57,7 @@ private:
|
|||
void NotifyOwner();
|
||||
|
||||
private:
|
||||
struct interrupt_handler interrupt_registration;
|
||||
int* queue;
|
||||
size_t queuelength;
|
||||
size_t queueoffset;
|
||||
|
|
|
@ -134,16 +134,35 @@ const char* exception_names[] =
|
|||
const unsigned int NUM_INTERRUPTS = 256U;
|
||||
|
||||
static struct IDT::idt_entry interrupt_table[NUM_INTERRUPTS];
|
||||
static Handler interrupt_handlers[NUM_INTERRUPTS];
|
||||
static void* interrupt_handler_context[NUM_INTERRUPTS];
|
||||
static struct interrupt_handler* interrupt_handlers[NUM_INTERRUPTS];
|
||||
|
||||
void RegisterHandler(unsigned int index,
|
||||
Interrupt::Handler handler,
|
||||
void* context)
|
||||
static struct interrupt_handler Scheduler__InterruptYieldCPU_handler;
|
||||
static struct interrupt_handler Signal__DispatchHandler_handler;
|
||||
static struct interrupt_handler Signal__ReturnHandler_handler;
|
||||
static struct interrupt_handler Scheduler__ThreadExitCPU_handler;
|
||||
|
||||
void RegisterHandler(unsigned int index, struct interrupt_handler* handler)
|
||||
{
|
||||
assert(index < NUM_INTERRUPTS);
|
||||
bool was_enabled = SetEnabled(false);
|
||||
handler->prev = NULL;
|
||||
if ( (handler->next = interrupt_handlers[index]) )
|
||||
handler->next->prev = handler;
|
||||
interrupt_handlers[index] = handler;
|
||||
interrupt_handler_context[index] = context;
|
||||
SetEnabled(was_enabled);
|
||||
}
|
||||
|
||||
void UnregisterHandler(unsigned int index, struct interrupt_handler* handler)
|
||||
{
|
||||
assert(index < NUM_INTERRUPTS);
|
||||
bool was_enabled = SetEnabled(false);
|
||||
if ( handler->prev )
|
||||
handler->prev->next = handler->next;
|
||||
else
|
||||
interrupt_handlers[index] = handler->next;
|
||||
if ( handler->next )
|
||||
handler->next->prev = handler->prev;
|
||||
SetEnabled(was_enabled);
|
||||
}
|
||||
|
||||
static void RegisterRawHandler(unsigned int index,
|
||||
|
@ -168,11 +187,7 @@ void Init()
|
|||
// Initialize the interrupt table entries to the null interrupt handler.
|
||||
memset(&interrupt_table, 0, sizeof(interrupt_table));
|
||||
for ( unsigned int i = 0; i < NUM_INTERRUPTS; i++ )
|
||||
{
|
||||
interrupt_handlers[i] = NULL;
|
||||
interrupt_handler_context[i] = NULL;
|
||||
RegisterRawHandler(i, interrupt_handler_null, false, false);
|
||||
}
|
||||
|
||||
// Remap the IRQ table on the PICs.
|
||||
PIC::ReprogramPIC();
|
||||
|
@ -231,10 +246,14 @@ void Init()
|
|||
RegisterRawHandler(131, isr131, true, true);
|
||||
RegisterRawHandler(132, thread_exit_handler, true, false);
|
||||
|
||||
RegisterHandler(129, Scheduler::InterruptYieldCPU, NULL);
|
||||
RegisterHandler(130, Signal::DispatchHandler, NULL);
|
||||
RegisterHandler(131, Signal::ReturnHandler, NULL);
|
||||
RegisterHandler(132, Scheduler::ThreadExitCPU, NULL);
|
||||
Scheduler__InterruptYieldCPU_handler.handler = Scheduler::InterruptYieldCPU;
|
||||
RegisterHandler(129, &Scheduler__InterruptYieldCPU_handler);
|
||||
Signal__DispatchHandler_handler.handler = Signal::DispatchHandler;
|
||||
RegisterHandler(130, &Signal__DispatchHandler_handler);
|
||||
Signal__ReturnHandler_handler.handler = Signal::ReturnHandler;
|
||||
RegisterHandler(131, &Signal__ReturnHandler_handler);
|
||||
Scheduler__ThreadExitCPU_handler.handler = Scheduler::ThreadExitCPU;
|
||||
RegisterHandler(132, &Scheduler__ThreadExitCPU_handler);
|
||||
|
||||
IDT::Set(interrupt_table, NUM_INTERRUPTS);
|
||||
|
||||
|
@ -333,8 +352,13 @@ extern "C" void interrupt_handler(struct interrupt_context* intctx)
|
|||
KernelCrashHandler(intctx);
|
||||
else if ( is_crash && is_in_user )
|
||||
UserCrashHandler(intctx);
|
||||
else if ( interrupt_handlers[int_no] )
|
||||
interrupt_handlers[int_no](intctx, interrupt_handler_context[int_no]);
|
||||
else
|
||||
{
|
||||
for ( struct interrupt_handler* iter = interrupt_handlers[int_no];
|
||||
iter;
|
||||
iter = iter->next )
|
||||
iter->handler(intctx, iter->context);
|
||||
}
|
||||
|
||||
// Send an end of interrupt signal to the PICs if we got an IRQ.
|
||||
if ( IRQ0 <= int_no && int_no <= IRQ15 )
|
||||
|
|
|
@ -74,6 +74,8 @@ static void RequestIRQ0(uint16_t divisor)
|
|||
extern Clock* realtime_clock;
|
||||
extern Clock* uptime_clock;
|
||||
|
||||
struct interrupt_handler timer_interrupt_registration;
|
||||
|
||||
static struct timespec tick_period;
|
||||
static long tick_frequency;
|
||||
static uint16_t tick_divisor;
|
||||
|
@ -126,7 +128,9 @@ void InitializeProcessClocks(Process* process)
|
|||
void Start()
|
||||
{
|
||||
// Handle timer interrupts if they arrive.
|
||||
Interrupt::RegisterHandler(Interrupt::IRQ0, &OnIRQ0, NULL);
|
||||
timer_interrupt_registration.handler = OnIRQ0;
|
||||
timer_interrupt_registration.context = 0;
|
||||
Interrupt::RegisterHandler(Interrupt::IRQ0, &timer_interrupt_registration);
|
||||
|
||||
// Request a timer interrupt now that we can handle them safely.
|
||||
RequestIRQ0(tick_divisor);
|
||||
|
|
Loading…
Reference in a new issue