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.
This commit is contained in:
@@ -50,8 +50,9 @@ typedef struct cpu_topology_node {
|
|||||||
|
|
||||||
typedef struct CACHE_LINE_ALIGN cpu_ent {
|
typedef struct CACHE_LINE_ALIGN cpu_ent {
|
||||||
int cpu_num;
|
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;
|
bool preempted;
|
||||||
timer quantum_timer;
|
timer quantum_timer;
|
||||||
|
|
||||||
@@ -72,8 +73,7 @@ typedef struct CACHE_LINE_ALIGN cpu_ent {
|
|||||||
|
|
||||||
Thread* running_thread;
|
Thread* running_thread;
|
||||||
Thread* previous_thread;
|
Thread* previous_thread;
|
||||||
bool invoke_scheduler;
|
int32 invoke_scheduler;
|
||||||
bool disabled;
|
|
||||||
|
|
||||||
// CPU topology information
|
// CPU topology information
|
||||||
int topology_id[CPU_TOPOLOGY_LEVELS];
|
int topology_id[CPU_TOPOLOGY_LEVELS];
|
||||||
|
|||||||
@@ -134,7 +134,7 @@ enqueue(Thread* thread, bool newOne)
|
|||||||
|
|
||||||
if (targetCPU->ID() == smp_get_current_cpu()) {
|
if (targetCPU->ID() == smp_get_current_cpu()) {
|
||||||
gCPU[targetCPU->ID()].invoke_scheduler = true;
|
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,
|
smp_send_ici(targetCPU->ID(), SMP_MSG_RESCHEDULE, 0, 0, 0,
|
||||||
NULL, SMP_MSG_FLAG_ASYNC);
|
NULL, SMP_MSG_FLAG_ASYNC);
|
||||||
}
|
}
|
||||||
@@ -321,7 +321,7 @@ reschedule(int32 nextState)
|
|||||||
SCHEDULER_ENTER_FUNCTION();
|
SCHEDULER_ENTER_FUNCTION();
|
||||||
|
|
||||||
int32 thisCPU = smp_get_current_cpu();
|
int32 thisCPU = smp_get_current_cpu();
|
||||||
gCPU[thisCPU].invoke_scheduler = false;
|
atomic_set(&gCPU[thisCPU].invoke_scheduler, false);
|
||||||
|
|
||||||
CPUEntry* cpu = CPUEntry::GetCPU(thisCPU);
|
CPUEntry* cpu = CPUEntry::GetCPU(thisCPU);
|
||||||
CoreEntry* core = CoreEntry::GetCore(thisCPU);
|
CoreEntry* core = CoreEntry::GetCore(thisCPU);
|
||||||
|
|||||||
Reference in New Issue
Block a user