Kernel: Send EOI after handling the interrupt

There is no need to send it prior to handling. This required us to not
yield from HPET/PIT irq so that the EOI actually gets sent
This commit is contained in:
2026-07-20 10:43:50 +03:00
parent a3b7a758eb
commit 0d390e2246
3 changed files with 24 additions and 12 deletions
+3 -1
View File
@@ -58,7 +58,7 @@ namespace Kernel
BAN::ErrorOr<void> initialize(); BAN::ErrorOr<void> initialize();
void reschedule(YieldRegisters*); void reschedule(YieldRegisters*);
void reschedule_if_idle(); void reschedule_if_needed();
void on_timer_interrupt(); void on_timer_interrupt();
void on_yield(YieldRegisters*); void on_yield(YieldRegisters*);
@@ -118,6 +118,8 @@ namespace Kernel
bool m_should_calculate_max_load_threads { true }; bool m_should_calculate_max_load_threads { true };
bool m_has_pending_reschedule { false };
Thread* m_idle_thread { nullptr }; Thread* m_idle_thread { nullptr };
friend class ThreadBlocker; friend class ThreadBlocker;
+15 -8
View File
@@ -413,10 +413,14 @@ namespace Kernel
extern "C" void cpp_ipi_handler() extern "C" void cpp_ipi_handler()
{ {
ASSERT(InterruptController::get().is_in_service(IRQ_IPI - IRQ_VECTOR_BASE)); if (!InterruptController::get().is_in_service(IRQ_IPI - IRQ_VECTOR_BASE))
InterruptController::get().eoi(IRQ_IPI - IRQ_VECTOR_BASE); return;
Processor::handle_ipi(); Processor::handle_ipi();
Processor::scheduler().reschedule_if_idle();
InterruptController::get().eoi(IRQ_IPI - IRQ_VECTOR_BASE);
Processor::scheduler().reschedule_if_needed();
} }
extern "C" void cpp_timer_handler() extern "C" void cpp_timer_handler()
@@ -429,13 +433,17 @@ namespace Kernel
asm volatile("cli; 1: hlt; jmp 1b"); asm volatile("cli; 1: hlt; jmp 1b");
} }
ASSERT(InterruptController::get().is_in_service(IRQ_TIMER - IRQ_VECTOR_BASE)); if (!InterruptController::get().is_in_service(IRQ_TIMER - IRQ_VECTOR_BASE))
InterruptController::get().eoi(IRQ_TIMER - IRQ_VECTOR_BASE); return;
if (Processor::current_is_bsp()) if (Processor::current_is_bsp())
Process::update_alarm_queue(); Process::update_alarm_queue();
Processor::scheduler().on_timer_interrupt(); Processor::scheduler().on_timer_interrupt();
InterruptController::get().eoi(IRQ_TIMER - IRQ_VECTOR_BASE);
Processor::scheduler().reschedule_if_needed();
} }
extern "C" void cpp_irq_handler(uint32_t irq) extern "C" void cpp_irq_handler(uint32_t irq)
@@ -453,15 +461,14 @@ namespace Kernel
if (!InterruptController::get().is_in_service(irq)) if (!InterruptController::get().is_in_service(irq))
return; return;
InterruptController::get().eoi(irq);
if (auto* handler = s_interruptables[irq]) if (auto* handler = s_interruptables[irq])
handler->handle_irq(); handler->handle_irq();
else else
dprintln("no handler for irq 0x{2H}", irq); dprintln("no handler for irq 0x{2H}", irq);
Processor::scheduler().reschedule_if_idle(); InterruptController::get().eoi(irq);
ASSERT(Thread::current().state() != Thread::State::Terminated); Processor::scheduler().reschedule_if_needed();
} }
extern "C" void cpp_check_signal() extern "C" void cpp_check_signal()
+6 -3
View File
@@ -332,12 +332,15 @@ namespace Kernel
static_cast<APIC&>(interrupt_controller).set_timer_dealine(deadline_ns); static_cast<APIC&>(interrupt_controller).set_timer_dealine(deadline_ns);
} }
void Scheduler::reschedule_if_idle() void Scheduler::reschedule_if_needed()
{ {
ASSERT(Processor::get_interrupt_state() == InterruptState::Disabled); ASSERT(Processor::get_interrupt_state() == InterruptState::Disabled);
if (m_current == nullptr && !m_run_queue.empty()) if ((is_idle() && !m_run_queue.empty()) || m_has_pending_reschedule)
{
m_has_pending_reschedule = false;
Processor::yield(); Processor::yield();
}
} }
extern "C" void scheduler_on_yield_trampoline(YieldRegisters* yield_registers) extern "C" void scheduler_on_yield_trampoline(YieldRegisters* yield_registers)
@@ -366,7 +369,7 @@ namespace Kernel
// NOTE: yield will update the timer deadline, but if we do not yield make sure // NOTE: yield will update the timer deadline, but if we do not yield make sure
// we set the next deadline or we won't get another timer interrupt // we set the next deadline or we won't get another timer interrupt
if (is_idle() || SystemTimer::get().ns_since_boot() >= m_next_reschedule_ns) if (is_idle() || SystemTimer::get().ns_since_boot() >= m_next_reschedule_ns)
Processor::yield(); m_has_pending_reschedule = true;
else else
update_wake_up_deadline(); update_wake_up_deadline();
} }