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.
This commit is contained in:
Pawel Dziepak
2014-04-09 03:24:34 +02:00
parent e439b00397
commit 1bba129c56
5 changed files with 30 additions and 30 deletions
+11 -10
View File
@@ -72,18 +72,19 @@ choose_core(const ThreadData* /* threadData */)
} }
static bool static CoreEntry*
should_rebalance(const ThreadData* threadData) rebalance(const ThreadData* threadData)
{ {
SCHEDULER_ENTER_FUNCTION(); SCHEDULER_ENTER_FUNCTION();
int32 coreLoad = threadData->Core()->GetLoad(); CoreEntry* core = threadData->Core();
int32 threadLoad = threadData->GetLoad() / threadData->Core()->CPUCount(); int32 coreLoad = core->GetLoad();
int32 threadLoad = threadData->GetLoad() / core->CPUCount();
// If the thread produces more than 50% of the load, leave it here. In // If the thread produces more than 50% of the load, leave it here. In
// such situation it is better to move other threads away. // such situation it is better to move other threads away.
if (threadLoad >= coreLoad / 2) if (threadLoad >= coreLoad / 2)
return false; return core;
// Get the least loaded core. // Get the least loaded core.
ReadSpinLocker coreLocker(gCoreHeapsLock); ReadSpinLocker coreLocker(gCoreHeapsLock);
@@ -93,18 +94,18 @@ should_rebalance(const ThreadData* threadData)
coreLocker.Unlock(); coreLocker.Unlock();
ASSERT(other != NULL); ASSERT(other != NULL);
if (other == threadData->Core()) if (other == core)
return false; return core;
// If there are idle cores give them some work unless that will cause // If there are idle cores give them some work unless that will cause
// the current core to become idle. // the current core to become idle.
int32 coreNewLoad = coreLoad - threadLoad; int32 coreNewLoad = coreLoad - threadLoad;
if (other->GetLoad() == 0 && coreNewLoad != 0) if (other->GetLoad() == 0 && coreNewLoad != 0)
return true; return other;
// Attempt to keep load balanced. // Attempt to keep load balanced.
int32 otherNewLoad = other->GetLoad() + threadLoad; 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, set_cpu_enabled,
has_cache_expired, has_cache_expired,
choose_core, choose_core,
should_rebalance, rebalance,
rebalance_irqs, rebalance_irqs,
}; };
+12 -12
View File
@@ -114,8 +114,8 @@ choose_core(const ThreadData* threadData)
} }
static bool static CoreEntry*
should_rebalance(const ThreadData* threadData) rebalance(const ThreadData* threadData)
{ {
SCHEDULER_ENTER_FUNCTION(); SCHEDULER_ENTER_FUNCTION();
@@ -128,15 +128,15 @@ should_rebalance(const ThreadData* threadData)
if (coreLoad > kHighLoad) { if (coreLoad > kHighLoad) {
if (sSmallTaskCore == core) { if (sSmallTaskCore == core) {
sSmallTaskCore = NULL; sSmallTaskCore = NULL;
choose_small_task_core(); CoreEntry* smallTaskCore = choose_small_task_core();
if (threadLoad > coreLoad / 3) if (threadLoad > coreLoad / 3)
return false; return core;
return coreLoad > kVeryHighLoad; return coreLoad > kVeryHighLoad ? smallTaskCore : core;
} }
if (threadLoad >= coreLoad / 2) if (threadLoad >= coreLoad / 2)
return false; return core;
ReadSpinLocker coreLocker(gCoreHeapsLock); ReadSpinLocker coreLocker(gCoreHeapsLock);
CoreEntry* other = gCoreLoadHeap.PeekMaximum(); CoreEntry* other = gCoreLoadHeap.PeekMaximum();
@@ -147,17 +147,17 @@ should_rebalance(const ThreadData* threadData)
int32 coreNewLoad = coreLoad - threadLoad; int32 coreNewLoad = coreLoad - threadLoad;
int32 otherNewLoad = other->GetLoad() + threadLoad; int32 otherNewLoad = other->GetLoad() + threadLoad;
return coreNewLoad - otherNewLoad >= kLoadDifference / 2; return coreNewLoad - otherNewLoad >= kLoadDifference / 2 ? other : core;
} }
if (coreLoad >= kMediumLoad) if (coreLoad >= kMediumLoad)
return false; return core;
CoreEntry* smallTaskCore = choose_small_task_core(); CoreEntry* smallTaskCore = choose_small_task_core();
if (smallTaskCore == NULL) if (smallTaskCore == NULL)
return false; return core;
return smallTaskCore != core return smallTaskCore->GetLoad() + threadLoad < kHighLoad
&& smallTaskCore->GetLoad() + threadLoad < kHighLoad; ? smallTaskCore : core;
} }
@@ -249,7 +249,7 @@ scheduler_mode_operations gSchedulerPowerSavingMode = {
set_cpu_enabled, set_cpu_enabled,
has_cache_expired, has_cache_expired,
choose_core, choose_core,
should_rebalance, rebalance,
rebalance_irqs, rebalance_irqs,
}; };
+2 -3
View File
@@ -111,9 +111,8 @@ enqueue(Thread* thread, bool newOne)
} else if (gSingleCore) } else if (gSingleCore)
targetCore = &gCoreEntries[0]; targetCore = &gCoreEntries[0];
else if (threadData->Core() != NULL else if (threadData->Core() != NULL
&& (!newOne || !threadData->HasCacheExpired()) && (!newOne || !threadData->HasCacheExpired())) {
&& !threadData->ShouldRebalance()) { targetCore = threadData->Rebalance();
targetCore = threadData->Core();
} }
bool rescheduleNeeded = threadData->ChooseCoreAndCPU(targetCore, targetCPU); bool rescheduleNeeded = threadData->ChooseCoreAndCPU(targetCore, targetCPU);
@@ -25,7 +25,7 @@ struct scheduler_mode_operations {
const Scheduler::ThreadData* threadData); const Scheduler::ThreadData* threadData);
Scheduler::CoreEntry* (*choose_core)( Scheduler::CoreEntry* (*choose_core)(
const Scheduler::ThreadData* threadData); const Scheduler::ThreadData* threadData);
bool (*should_rebalance)( Scheduler::CoreEntry* (*rebalance)(
const Scheduler::ThreadData* threadData); const Scheduler::ThreadData* threadData);
void (*rebalance_irqs)(bool idle); void (*rebalance_irqs)(bool idle);
}; };
@@ -44,7 +44,7 @@ public:
inline bool IsIdle() const; inline bool IsIdle() const;
inline bool HasCacheExpired() const; inline bool HasCacheExpired() const;
inline bool ShouldRebalance() const; inline CoreEntry* Rebalance() const;
inline int32 GetEffectivePriority() const; inline int32 GetEffectivePriority() const;
@@ -176,13 +176,13 @@ ThreadData::HasCacheExpired() const
} }
inline bool inline CoreEntry*
ThreadData::ShouldRebalance() const ThreadData::Rebalance() const
{ {
SCHEDULER_ENTER_FUNCTION(); SCHEDULER_ENTER_FUNCTION();
ASSERT(!gSingleCore); ASSERT(!gSingleCore);
return gCurrentMode->should_rebalance(this); return gCurrentMode->rebalance(this);
} }