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:
@@ -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,
|
||||
};
|
||||
|
||||
|
||||
@@ -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,
|
||||
};
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
};
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user