From 1bba129c56656a5c140fc8d1202ae1cac761d49b Mon Sep 17 00:00:00 2001 From: Pawel Dziepak Date: Tue, 8 Apr 2014 22:21:14 +0200 Subject: [PATCH] scheduler: Let ThreadData::ShouldRebalance() choose the actual core Currently, ThreadData::ShouldRebalance() (and mode specific functions it calls) only decides whether to migrate thread to another core or not. However, in most cases it actually needs to find the best candidate for new core so it could as well return that information. --- src/system/kernel/scheduler/low_latency.cpp | 21 ++++++++-------- src/system/kernel/scheduler/power_saving.cpp | 24 +++++++++---------- src/system/kernel/scheduler/scheduler.cpp | 5 ++-- src/system/kernel/scheduler/scheduler_modes.h | 2 +- .../kernel/scheduler/scheduler_thread.h | 8 +++---- 5 files changed, 30 insertions(+), 30 deletions(-) diff --git a/src/system/kernel/scheduler/low_latency.cpp b/src/system/kernel/scheduler/low_latency.cpp index bca90fd0b5..5b405393a0 100644 --- a/src/system/kernel/scheduler/low_latency.cpp +++ b/src/system/kernel/scheduler/low_latency.cpp @@ -72,18 +72,19 @@ choose_core(const ThreadData* /* threadData */) } -static bool -should_rebalance(const ThreadData* threadData) +static CoreEntry* +rebalance(const ThreadData* threadData) { SCHEDULER_ENTER_FUNCTION(); - int32 coreLoad = threadData->Core()->GetLoad(); - int32 threadLoad = threadData->GetLoad() / threadData->Core()->CPUCount(); + CoreEntry* core = threadData->Core(); + int32 coreLoad = core->GetLoad(); + int32 threadLoad = threadData->GetLoad() / core->CPUCount(); // If the thread produces more than 50% of the load, leave it here. In // such situation it is better to move other threads away. if (threadLoad >= coreLoad / 2) - return false; + return core; // Get the least loaded core. ReadSpinLocker coreLocker(gCoreHeapsLock); @@ -93,18 +94,18 @@ should_rebalance(const ThreadData* threadData) coreLocker.Unlock(); ASSERT(other != NULL); - if (other == threadData->Core()) - return false; + if (other == core) + return core; // If there are idle cores give them some work unless that will cause // the current core to become idle. int32 coreNewLoad = coreLoad - threadLoad; if (other->GetLoad() == 0 && coreNewLoad != 0) - return true; + return other; // Attempt to keep load balanced. int32 otherNewLoad = other->GetLoad() + threadLoad; - return coreNewLoad - otherNewLoad >= kLoadDifference; + return coreNewLoad - otherNewLoad >= kLoadDifference ? other : core; } @@ -168,7 +169,7 @@ scheduler_mode_operations gSchedulerLowLatencyMode = { set_cpu_enabled, has_cache_expired, choose_core, - should_rebalance, + rebalance, rebalance_irqs, }; diff --git a/src/system/kernel/scheduler/power_saving.cpp b/src/system/kernel/scheduler/power_saving.cpp index f9b4b62fca..9cbe24b874 100644 --- a/src/system/kernel/scheduler/power_saving.cpp +++ b/src/system/kernel/scheduler/power_saving.cpp @@ -114,8 +114,8 @@ choose_core(const ThreadData* threadData) } -static bool -should_rebalance(const ThreadData* threadData) +static CoreEntry* +rebalance(const ThreadData* threadData) { SCHEDULER_ENTER_FUNCTION(); @@ -128,15 +128,15 @@ should_rebalance(const ThreadData* threadData) if (coreLoad > kHighLoad) { if (sSmallTaskCore == core) { sSmallTaskCore = NULL; - choose_small_task_core(); + CoreEntry* smallTaskCore = choose_small_task_core(); if (threadLoad > coreLoad / 3) - return false; - return coreLoad > kVeryHighLoad; + return core; + return coreLoad > kVeryHighLoad ? smallTaskCore : core; } if (threadLoad >= coreLoad / 2) - return false; + return core; ReadSpinLocker coreLocker(gCoreHeapsLock); CoreEntry* other = gCoreLoadHeap.PeekMaximum(); @@ -147,17 +147,17 @@ should_rebalance(const ThreadData* threadData) int32 coreNewLoad = coreLoad - threadLoad; int32 otherNewLoad = other->GetLoad() + threadLoad; - return coreNewLoad - otherNewLoad >= kLoadDifference / 2; + return coreNewLoad - otherNewLoad >= kLoadDifference / 2 ? other : core; } if (coreLoad >= kMediumLoad) - return false; + return core; CoreEntry* smallTaskCore = choose_small_task_core(); if (smallTaskCore == NULL) - return false; - return smallTaskCore != core - && smallTaskCore->GetLoad() + threadLoad < kHighLoad; + return core; + return smallTaskCore->GetLoad() + threadLoad < kHighLoad + ? smallTaskCore : core; } @@ -249,7 +249,7 @@ scheduler_mode_operations gSchedulerPowerSavingMode = { set_cpu_enabled, has_cache_expired, choose_core, - should_rebalance, + rebalance, rebalance_irqs, }; diff --git a/src/system/kernel/scheduler/scheduler.cpp b/src/system/kernel/scheduler/scheduler.cpp index 67f99e2381..27022e371c 100644 --- a/src/system/kernel/scheduler/scheduler.cpp +++ b/src/system/kernel/scheduler/scheduler.cpp @@ -111,9 +111,8 @@ enqueue(Thread* thread, bool newOne) } else if (gSingleCore) targetCore = &gCoreEntries[0]; else if (threadData->Core() != NULL - && (!newOne || !threadData->HasCacheExpired()) - && !threadData->ShouldRebalance()) { - targetCore = threadData->Core(); + && (!newOne || !threadData->HasCacheExpired())) { + targetCore = threadData->Rebalance(); } bool rescheduleNeeded = threadData->ChooseCoreAndCPU(targetCore, targetCPU); diff --git a/src/system/kernel/scheduler/scheduler_modes.h b/src/system/kernel/scheduler/scheduler_modes.h index 820912afd9..2d0979d92a 100644 --- a/src/system/kernel/scheduler/scheduler_modes.h +++ b/src/system/kernel/scheduler/scheduler_modes.h @@ -25,7 +25,7 @@ struct scheduler_mode_operations { const Scheduler::ThreadData* threadData); Scheduler::CoreEntry* (*choose_core)( const Scheduler::ThreadData* threadData); - bool (*should_rebalance)( + Scheduler::CoreEntry* (*rebalance)( const Scheduler::ThreadData* threadData); void (*rebalance_irqs)(bool idle); }; diff --git a/src/system/kernel/scheduler/scheduler_thread.h b/src/system/kernel/scheduler/scheduler_thread.h index 1127b69127..73e581e282 100644 --- a/src/system/kernel/scheduler/scheduler_thread.h +++ b/src/system/kernel/scheduler/scheduler_thread.h @@ -44,7 +44,7 @@ public: inline bool IsIdle() const; inline bool HasCacheExpired() const; - inline bool ShouldRebalance() const; + inline CoreEntry* Rebalance() const; inline int32 GetEffectivePriority() const; @@ -176,13 +176,13 @@ ThreadData::HasCacheExpired() const } -inline bool -ThreadData::ShouldRebalance() const +inline CoreEntry* +ThreadData::Rebalance() const { SCHEDULER_ENTER_FUNCTION(); ASSERT(!gSingleCore); - return gCurrentMode->should_rebalance(this); + return gCurrentMode->rebalance(this); }