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