From 19bcb3be0ad6253e379012a0df1acc9ee22cf29d Mon Sep 17 00:00:00 2001 From: Augustin Cavalier Date: Tue, 17 Mar 2026 11:25:36 -0400 Subject: [PATCH] kernel/scheduler: Make invoke_scheduler atomic to skip unnecessary ICIs. Following upon a KDL reported by atomozero, on wait-for-free-SMP-messages on an unblock occurring with interrupts disabled. In changing cpu_ent, move disabled to the beginning to avoid enlarging the structure unncessarily. On a 4-core VM, this skips around 200 sends during boot, and over 3000 during a rebuild of HaikuDepot + mime_db (cold). On bare metal (i3, 2x2), it skips around 150 during boot, and a bit below 3000 during a rebuild of HaikuDepot + mime_db (over a much longer time than in the VM, as the hardware is slower.) Performance in the VM doesn't look much different. But this might help in VirtualBox, or other situations where ICI latency is far above what it should be. --- headers/private/kernel/cpu.h | 6 +++--- src/system/kernel/scheduler/scheduler.cpp | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/headers/private/kernel/cpu.h b/headers/private/kernel/cpu.h index a864d5fb16..df00acca2b 100644 --- a/headers/private/kernel/cpu.h +++ b/headers/private/kernel/cpu.h @@ -50,8 +50,9 @@ typedef struct cpu_topology_node { typedef struct CACHE_LINE_ALIGN cpu_ent { int cpu_num; + bool disabled; - // thread.c: used to force a reschedule at quantum expiration time + // used to force a reschedule at quantum expiration time bool preempted; timer quantum_timer; @@ -72,8 +73,7 @@ typedef struct CACHE_LINE_ALIGN cpu_ent { Thread* running_thread; Thread* previous_thread; - bool invoke_scheduler; - bool disabled; + int32 invoke_scheduler; // CPU topology information int topology_id[CPU_TOPOLOGY_LEVELS]; diff --git a/src/system/kernel/scheduler/scheduler.cpp b/src/system/kernel/scheduler/scheduler.cpp index 0a4574c1aa..036e06075a 100644 --- a/src/system/kernel/scheduler/scheduler.cpp +++ b/src/system/kernel/scheduler/scheduler.cpp @@ -134,7 +134,7 @@ enqueue(Thread* thread, bool newOne) if (targetCPU->ID() == smp_get_current_cpu()) { gCPU[targetCPU->ID()].invoke_scheduler = true; - } else { + } else if (atomic_get_and_set(&gCPU[targetCPU->ID()].invoke_scheduler, true) != true) { smp_send_ici(targetCPU->ID(), SMP_MSG_RESCHEDULE, 0, 0, 0, NULL, SMP_MSG_FLAG_ASYNC); } @@ -321,7 +321,7 @@ reschedule(int32 nextState) SCHEDULER_ENTER_FUNCTION(); int32 thisCPU = smp_get_current_cpu(); - gCPU[thisCPU].invoke_scheduler = false; + atomic_set(&gCPU[thisCPU].invoke_scheduler, false); CPUEntry* cpu = CPUEntry::GetCPU(thisCPU); CoreEntry* core = CoreEntry::GetCore(thisCPU);