From a57a7a8c6df4934623bcc4535f4f1b8bd46a39af Mon Sep 17 00:00:00 2001 From: Pawel Dziepak Date: Sun, 9 Mar 2014 15:21:01 +0100 Subject: [PATCH] scheduler: Fix load update on idle cores To make sure that load statistics are accurate on idle cores each time idle thread is scheduled a timer is set to update load when current load measurement interval elapses. However, core load is defined as the average load during last measurement interval and idle core may be still considered busy if it was not idle during entire measurement interval. Since, load update timer is a one shot timer that information will not be updated until the core becomes active again. To mitigate that issue load update timer is set to fire after two load measurement intervals had elapsed. --- src/system/kernel/scheduler/scheduler_cpu.cpp | 20 +++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/src/system/kernel/scheduler/scheduler_cpu.cpp b/src/system/kernel/scheduler/scheduler_cpu.cpp index 0f88fcea87..fa2688be35 100644 --- a/src/system/kernel/scheduler/scheduler_cpu.cpp +++ b/src/system/kernel/scheduler/scheduler_cpu.cpp @@ -309,7 +309,7 @@ CPUEntry::StartQuantumTimer(ThreadData* thread, bool wasPreempted) B_ONE_SHOT_RELATIVE_TIMER); } else if (gTrackCoreLoad) { add_timer(&cpu->quantum_timer, &CPUEntry::_UpdateLoadEvent, - kLoadMeasureInterval, B_ONE_SHOT_RELATIVE_TIMER); + kLoadMeasureInterval * 2, B_ONE_SHOT_RELATIVE_TIMER); fUpdateLoadEvent = true; } } @@ -536,28 +536,32 @@ CoreEntry::_UpdateLoad(bool forceUpdate) bigtime_t now = system_time(); bool intervalEnded = now >= kLoadMeasureInterval + fLastLoadUpdate; + bool intervalSkipped = now >= kLoadMeasureInterval * 2 + fLastLoadUpdate; if (!intervalEnded && !forceUpdate) return; WriteSpinLocker coreLocker(gCoreHeapsLock); - int32 newKey = GetLoad(); - int32 oldKey = CoreLoadHeap::GetKey(this); - - ASSERT(oldKey >= 0); - ASSERT(newKey >= 0); - + int32 newKey; if (intervalEnded) { WriteSpinLocker locker(fLoadLock); + newKey = intervalSkipped ? fCurrentLoad : GetLoad(); + ASSERT(fCurrentLoad >= 0); ASSERT(fLoad >= fCurrentLoad); fLoad = fCurrentLoad; fLoadMeasurementEpoch++; fLastLoadUpdate = now; - } + } else + newKey = GetLoad(); + + int32 oldKey = CoreLoadHeap::GetKey(this); + + ASSERT(oldKey >= 0); + ASSERT(newKey >= 0); if (oldKey == newKey) return;