mirror of https://gitlab.com/nakst/essence
introduce irqHandlersLock
This commit is contained in:
parent
4f8618bd23
commit
be09af9014
|
@ -95,6 +95,7 @@ struct IRQHandler {
|
||||||
|
|
||||||
MSIHandler msiHandlers[INTERRUPT_VECTOR_MSI_COUNT];
|
MSIHandler msiHandlers[INTERRUPT_VECTOR_MSI_COUNT];
|
||||||
IRQHandler irqHandlers[0x40];
|
IRQHandler irqHandlers[0x40];
|
||||||
|
KSpinlock irqHandlersLock; // Also for msiHandlers.
|
||||||
|
|
||||||
extern uintptr_t bootloaderInformationOffset;
|
extern uintptr_t bootloaderInformationOffset;
|
||||||
extern "C" bool simdSSE3Support;
|
extern "C" bool simdSSE3Support;
|
||||||
|
@ -693,14 +694,14 @@ bool SetupInterruptRedirectionEntry(uintptr_t _line) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void KUnregisterMSI(uintptr_t tag) {
|
void KUnregisterMSI(uintptr_t tag) {
|
||||||
KSpinlockAcquire(&scheduler.lock);
|
KSpinlockAcquire(&irqHandlersLock);
|
||||||
EsDefer(KSpinlockRelease(&scheduler.lock));
|
EsDefer(KSpinlockRelease(&irqHandlersLock));
|
||||||
msiHandlers[tag].callback = nullptr;
|
msiHandlers[tag].callback = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
KMSIInformation KRegisterMSI(KIRQHandler handler, void *context, const char *cOwnerName) {
|
KMSIInformation KRegisterMSI(KIRQHandler handler, void *context, const char *cOwnerName) {
|
||||||
KSpinlockAcquire(&scheduler.lock);
|
KSpinlockAcquire(&irqHandlersLock);
|
||||||
EsDefer(KSpinlockRelease(&scheduler.lock));
|
EsDefer(KSpinlockRelease(&irqHandlersLock));
|
||||||
|
|
||||||
for (uintptr_t i = 0; i < INTERRUPT_VECTOR_MSI_COUNT; i++) {
|
for (uintptr_t i = 0; i < INTERRUPT_VECTOR_MSI_COUNT; i++) {
|
||||||
if (msiHandlers[i].callback) continue;
|
if (msiHandlers[i].callback) continue;
|
||||||
|
@ -735,6 +736,8 @@ bool KRegisterIRQ(intptr_t line, KIRQHandler handler, void *context, const char
|
||||||
if (line > 0x20 || line < -1) KernelPanic("KRegisterIRQ - Unexpected IRQ %d\n", line);
|
if (line > 0x20 || line < -1) KernelPanic("KRegisterIRQ - Unexpected IRQ %d\n", line);
|
||||||
bool found = false;
|
bool found = false;
|
||||||
|
|
||||||
|
KSpinlockAcquire(&irqHandlersLock);
|
||||||
|
|
||||||
for (uintptr_t i = 0; i < sizeof(irqHandlers) / sizeof(irqHandlers[0]); i++) {
|
for (uintptr_t i = 0; i < sizeof(irqHandlers) / sizeof(irqHandlers[0]); i++) {
|
||||||
if (!irqHandlers[i].callback) {
|
if (!irqHandlers[i].callback) {
|
||||||
found = true;
|
found = true;
|
||||||
|
@ -747,6 +750,8 @@ bool KRegisterIRQ(intptr_t line, KIRQHandler handler, void *context, const char
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
KSpinlockRelease(&irqHandlersLock);
|
||||||
|
|
||||||
if (!found) {
|
if (!found) {
|
||||||
KernelLog(LOG_ERROR, "Arch", "too many IRQ handlers", "The limit of IRQ handlers was reached (%d), and the handler for '%z' was not registered.\n",
|
KernelLog(LOG_ERROR, "Arch", "too many IRQ handlers", "The limit of IRQ handlers was reached (%d), and the handler for '%z' was not registered.\n",
|
||||||
sizeof(irqHandlers) / sizeof(irqHandlers[0]), cOwnerName);
|
sizeof(irqHandlers) / sizeof(irqHandlers[0]), cOwnerName);
|
||||||
|
@ -1080,13 +1085,15 @@ extern "C" void InterruptHandler(InterruptContext *context) {
|
||||||
|
|
||||||
acpi.lapic.EndOfInterrupt();
|
acpi.lapic.EndOfInterrupt();
|
||||||
} else if (interrupt >= INTERRUPT_VECTOR_MSI_START && interrupt < INTERRUPT_VECTOR_MSI_START + INTERRUPT_VECTOR_MSI_COUNT && local) {
|
} else if (interrupt >= INTERRUPT_VECTOR_MSI_START && interrupt < INTERRUPT_VECTOR_MSI_START + INTERRUPT_VECTOR_MSI_COUNT && local) {
|
||||||
MSIHandler *handler = &msiHandlers[interrupt - INTERRUPT_VECTOR_MSI_START];
|
KSpinlockAcquire(&irqHandlersLock);
|
||||||
|
MSIHandler handler = msiHandlers[interrupt - INTERRUPT_VECTOR_MSI_START];
|
||||||
|
KSpinlockRelease(&irqHandlersLock);
|
||||||
local->irqSwitchThread = false;
|
local->irqSwitchThread = false;
|
||||||
|
|
||||||
if (!handler->callback) {
|
if (!handler.callback) {
|
||||||
KernelLog(LOG_ERROR, "Arch", "unexpected MSI", "Unexpected MSI vector %X (no handler).\n", interrupt);
|
KernelLog(LOG_ERROR, "Arch", "unexpected MSI", "Unexpected MSI vector %X (no handler).\n", interrupt);
|
||||||
} else {
|
} else {
|
||||||
handler->callback(interrupt - INTERRUPT_VECTOR_MSI_START, handler->context);
|
handler.callback(interrupt - INTERRUPT_VECTOR_MSI_START, handler.context);
|
||||||
}
|
}
|
||||||
|
|
||||||
acpi.lapic.EndOfInterrupt();
|
acpi.lapic.EndOfInterrupt();
|
||||||
|
@ -1110,12 +1117,13 @@ extern "C" void InterruptHandler(InterruptContext *context) {
|
||||||
|
|
||||||
uintptr_t line = interrupt - IRQ_BASE;
|
uintptr_t line = interrupt - IRQ_BASE;
|
||||||
KernelLog(LOG_VERBOSE, "Arch", "IRQ start", "IRQ start %d.\n", line);
|
KernelLog(LOG_VERBOSE, "Arch", "IRQ start", "IRQ start %d.\n", line);
|
||||||
|
KSpinlockAcquire(&irqHandlersLock);
|
||||||
|
|
||||||
for (uintptr_t i = 0; i < sizeof(irqHandlers) / sizeof(irqHandlers[0]); i++) {
|
for (uintptr_t i = 0; i < sizeof(irqHandlers) / sizeof(irqHandlers[0]); i++) {
|
||||||
IRQHandler *handler = &irqHandlers[i];
|
IRQHandler handler = irqHandlers[i];
|
||||||
if (!handler->callback) continue;
|
if (!handler.callback) continue;
|
||||||
|
|
||||||
if (handler->line == -1) {
|
if (handler.line == -1) {
|
||||||
// Before we get the actual IRQ line information from ACPI (which might take it a while),
|
// Before we get the actual IRQ line information from ACPI (which might take it a while),
|
||||||
// only test that the IRQ is in the correct range for PCI interrupts.
|
// only test that the IRQ is in the correct range for PCI interrupts.
|
||||||
// This is a bit slower because we have to dispatch the interrupt to more drivers,
|
// This is a bit slower because we have to dispatch the interrupt to more drivers,
|
||||||
|
@ -1125,21 +1133,24 @@ extern "C" void InterruptHandler(InterruptContext *context) {
|
||||||
if (line != 9 && line != 10 && line != 11) {
|
if (line != 9 && line != 10 && line != 11) {
|
||||||
continue;
|
continue;
|
||||||
} else {
|
} else {
|
||||||
uint8_t mappedLine = pciIRQLines[handler->pciDevice->slot][handler->pciDevice->interruptPin - 1];
|
uint8_t mappedLine = pciIRQLines[handler.pciDevice->slot][handler.pciDevice->interruptPin - 1];
|
||||||
|
|
||||||
if (mappedLine && line != mappedLine) {
|
if (mappedLine && line != mappedLine) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if ((uintptr_t) handler->line != line) {
|
if ((uintptr_t) handler.line != line) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
handler->callback(interrupt - IRQ_BASE, handler->context);
|
KSpinlockRelease(&irqHandlersLock);
|
||||||
|
handler.callback(interrupt - IRQ_BASE, handler.context);
|
||||||
|
KSpinlockAcquire(&irqHandlersLock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
KSpinlockRelease(&irqHandlersLock);
|
||||||
KernelLog(LOG_VERBOSE, "Arch", "IRQ end", "IRQ end %d.\n", line);
|
KernelLog(LOG_VERBOSE, "Arch", "IRQ end", "IRQ end %d.\n", line);
|
||||||
|
|
||||||
GetLocalStorage()->inIRQ = false;
|
GetLocalStorage()->inIRQ = false;
|
||||||
|
|
Loading…
Reference in New Issue