Kernel: Reduce the number of sent IPIs

Only send an IPI when the target processors don't have pending messages.
This basically gets rid of TLB shootdowns from showing up in profiles.
Before they were taking maybe >10% kernel time :^D
This commit is contained in:
2026-05-19 23:52:38 +03:00
parent 24c37e7381
commit 376e4b4c45
2 changed files with 15 additions and 6 deletions

View File

@@ -132,7 +132,7 @@ namespace Kernel
static void handle_ipi();
static void handle_smp_messages();
static void send_smp_message(ProcessorID, const SMPMessage&, bool send_ipi = true);
static bool send_smp_message(ProcessorID, const SMPMessage&, bool send_ipi = true);
static void broadcast_smp_message(const SMPMessage&);
static void load_segments();

View File

@@ -488,7 +488,7 @@ namespace Kernel
set_interrupt_state(state);
}
void Processor::send_smp_message(ProcessorID processor_id, const SMPMessage& message, bool send_ipi)
bool Processor::send_smp_message(ProcessorID processor_id, const SMPMessage& message, bool send_ipi)
{
auto state = get_interrupt_state();
set_interrupt_state(InterruptState::Disabled);
@@ -499,6 +499,8 @@ namespace Kernel
{
processor.lock_tlb_lock();
const bool is_first_entry = (processor.m_tlb_entry_count == 0);
const auto& tlb_msg = message.flush_tlb;
processor.m_tlb_global |= (tlb_msg.page_table == nullptr);
@@ -515,7 +517,7 @@ namespace Kernel
processor.unlock_tlb_lock();
set_interrupt_state(state);
return;
return is_first_entry;
}
// find a slot for message
@@ -557,15 +559,19 @@ namespace Kernel
storage->next = processor.m_smp_pending;
}
const bool needs_ipi = (storage->next == nullptr);
if (send_ipi)
{
if (processor_id == current_id())
handle_smp_messages();
else
else if (needs_ipi)
InterruptController::get().send_ipi(processor_id);
}
set_interrupt_state(state);
return needs_ipi;
}
void Processor::broadcast_smp_message(const SMPMessage& message)
@@ -576,15 +582,18 @@ namespace Kernel
const auto state = get_interrupt_state();
set_interrupt_state(InterruptState::Disabled);
bool needs_ipi = false;
const auto current_id = Processor::current_id();
for (size_t i = 0; i < Processor::count(); i++)
{
const auto processor_id = s_processor_ids[i];
if (processor_id != current_id)
send_smp_message(processor_id, message, false);
needs_ipi |= send_smp_message(processor_id, message, false);
}
InterruptController::get().broadcast_ipi();
if (needs_ipi)
InterruptController::get().broadcast_ipi();
set_interrupt_state(state);
}