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:
@@ -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
@@ -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()
|
||||||
|
|||||||
@@ -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();
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user