scheduler: Migrate threads less often in power saving mode
This commit is contained in:
@@ -30,9 +30,6 @@ has_cache_expired(Thread* thread)
|
|||||||
{
|
{
|
||||||
ASSERT(!gSingleCore);
|
ASSERT(!gSingleCore);
|
||||||
|
|
||||||
if (thread_is_idle_thread(thread))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
scheduler_thread_data* schedulerThreadData = thread->scheduler_data;
|
scheduler_thread_data* schedulerThreadData = thread->scheduler_data;
|
||||||
ASSERT(schedulerThreadData->previous_core >= 0);
|
ASSERT(schedulerThreadData->previous_core >= 0);
|
||||||
|
|
||||||
|
|||||||
@@ -36,9 +36,6 @@ has_cache_expired(Thread* thread)
|
|||||||
{
|
{
|
||||||
ASSERT(!gSingleCore);
|
ASSERT(!gSingleCore);
|
||||||
|
|
||||||
if (thread_is_idle_thread(thread))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
scheduler_thread_data* schedulerThreadData = thread->scheduler_data;
|
scheduler_thread_data* schedulerThreadData = thread->scheduler_data;
|
||||||
ASSERT(schedulerThreadData->previous_core >= 0);
|
ASSERT(schedulerThreadData->previous_core >= 0);
|
||||||
|
|
||||||
@@ -46,19 +43,6 @@ has_cache_expired(Thread* thread)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static bool
|
|
||||||
try_small_task_packing(Thread* thread)
|
|
||||||
{
|
|
||||||
ReadSpinLocker locker(gCoreHeapsLock);
|
|
||||||
|
|
||||||
int32 core = sSmallTaskCore;
|
|
||||||
return (core == -1 && gCoreLoadHeap->PeekMaximum() != NULL)
|
|
||||||
|| (core != -1
|
|
||||||
&& get_core_load(&gCoreEntries[core]) + thread->scheduler_data->load
|
|
||||||
< kHighLoad);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static int32
|
static int32
|
||||||
choose_small_task_core(void)
|
choose_small_task_core(void)
|
||||||
{
|
{
|
||||||
@@ -107,24 +91,27 @@ choose_core(Thread* thread)
|
|||||||
{
|
{
|
||||||
CoreEntry* entry;
|
CoreEntry* entry;
|
||||||
|
|
||||||
if (try_small_task_packing(thread)) {
|
int32 core = -1;
|
||||||
// try to pack all threads on one core
|
// try to pack all threads on one core
|
||||||
entry = &gCoreEntries[choose_small_task_core()];
|
core = choose_small_task_core();
|
||||||
|
|
||||||
|
if (core != -1
|
||||||
|
&& get_core_load(&gCoreEntries[core]) + thread->scheduler_data->load
|
||||||
|
< kHighLoad) {
|
||||||
|
entry = &gCoreEntries[core];
|
||||||
} else {
|
} else {
|
||||||
ReadSpinLocker coreLocker(gCoreHeapsLock);
|
ReadSpinLocker coreLocker(gCoreHeapsLock);
|
||||||
if (gCoreLoadHeap->PeekMinimum() != NULL) {
|
// run immediately on already woken core
|
||||||
// run immediately on already woken core
|
entry = gCoreLoadHeap->PeekMinimum();
|
||||||
entry = gCoreLoadHeap->PeekMinimum();
|
if (entry == NULL) {
|
||||||
} else {
|
|
||||||
coreLocker.Unlock();
|
coreLocker.Unlock();
|
||||||
|
|
||||||
entry = choose_idle_core();
|
entry = choose_idle_core();
|
||||||
|
|
||||||
coreLocker.Lock();
|
if (entry == NULL) {
|
||||||
if (entry == NULL)
|
coreLocker.Lock();
|
||||||
entry = gCoreLoadHeap->PeekMinimum();
|
|
||||||
if (entry == NULL)
|
|
||||||
entry = gCoreHighLoadHeap->PeekMinimum();
|
entry = gCoreHighLoadHeap->PeekMinimum();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -138,9 +125,6 @@ should_rebalance(Thread* thread)
|
|||||||
{
|
{
|
||||||
ASSERT(!gSingleCore);
|
ASSERT(!gSingleCore);
|
||||||
|
|
||||||
if (thread_is_idle_thread(thread))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
scheduler_thread_data* schedulerThreadData = thread->scheduler_data;
|
scheduler_thread_data* schedulerThreadData = thread->scheduler_data;
|
||||||
ASSERT(schedulerThreadData->previous_core >= 0);
|
ASSERT(schedulerThreadData->previous_core >= 0);
|
||||||
|
|
||||||
@@ -151,13 +135,16 @@ should_rebalance(Thread* thread)
|
|||||||
if (coreLoad > kHighLoad) {
|
if (coreLoad > kHighLoad) {
|
||||||
ReadSpinLocker coreLocker(gCoreHeapsLock);
|
ReadSpinLocker coreLocker(gCoreHeapsLock);
|
||||||
if (sSmallTaskCore == core) {
|
if (sSmallTaskCore == core) {
|
||||||
if (coreLoad - schedulerThreadData->load < kHighLoad)
|
sSmallTaskCore = -1;
|
||||||
return true;
|
|
||||||
|
|
||||||
choose_small_task_core();
|
choose_small_task_core();
|
||||||
|
if (schedulerThreadData->load > coreLoad / 3)
|
||||||
|
return false;
|
||||||
return coreLoad > kVeryHighLoad;
|
return coreLoad > kVeryHighLoad;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (schedulerThreadData->load >= coreLoad / 2)
|
||||||
|
return false;
|
||||||
|
|
||||||
CoreEntry* other = gCoreLoadHeap->PeekMaximum();
|
CoreEntry* other = gCoreLoadHeap->PeekMaximum();
|
||||||
if (other == NULL)
|
if (other == NULL)
|
||||||
other = gCoreHighLoadHeap->PeekMinimum();
|
other = gCoreHighLoadHeap->PeekMinimum();
|
||||||
@@ -165,10 +152,15 @@ should_rebalance(Thread* thread)
|
|||||||
return coreLoad - get_core_load(other) >= kLoadDifference / 2;
|
return coreLoad - get_core_load(other) >= kLoadDifference / 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (coreLoad >= kMediumLoad)
|
||||||
|
return false;
|
||||||
|
|
||||||
int32 smallTaskCore = choose_small_task_core();
|
int32 smallTaskCore = choose_small_task_core();
|
||||||
if (smallTaskCore == -1)
|
if (smallTaskCore == -1)
|
||||||
return false;
|
return false;
|
||||||
return smallTaskCore != core;
|
return smallTaskCore != core
|
||||||
|
&& get_core_load(&gCoreEntries[smallTaskCore])
|
||||||
|
+ thread->scheduler_data->load < kHighLoad;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -120,7 +120,8 @@ CoreEntry::CoreEntry()
|
|||||||
fCPUCount(0),
|
fCPUCount(0),
|
||||||
fThreadCount(0),
|
fThreadCount(0),
|
||||||
fActiveTime(0),
|
fActiveTime(0),
|
||||||
fLoad(0)
|
fLoad(0),
|
||||||
|
fHighLoad(false)
|
||||||
{
|
{
|
||||||
B_INITIALIZE_SPINLOCK(&fCPULock);
|
B_INITIALIZE_SPINLOCK(&fCPULock);
|
||||||
B_INITIALIZE_SPINLOCK(&fQueueLock);
|
B_INITIALIZE_SPINLOCK(&fQueueLock);
|
||||||
@@ -264,6 +265,7 @@ dump_cpu_heap(int argc, char** argv)
|
|||||||
{
|
{
|
||||||
kprintf("core load\n");
|
kprintf("core load\n");
|
||||||
dump_core_load_heap(gCoreLoadHeap);
|
dump_core_load_heap(gCoreLoadHeap);
|
||||||
|
kprintf("\n");
|
||||||
dump_core_load_heap(gCoreHighLoadHeap);
|
dump_core_load_heap(gCoreHighLoadHeap);
|
||||||
|
|
||||||
for (int32 i = 0; i < gCoreCount; i++) {
|
for (int32 i = 0; i < gCoreCount; i++) {
|
||||||
@@ -376,23 +378,32 @@ update_load_heaps(int32 core)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
if (newKey > kHighLoad) {
|
if (newKey > kHighLoad) {
|
||||||
if (oldKey <= kHighLoad) {
|
if (!entry->fHighLoad) {
|
||||||
gCoreLoadHeap->ModifyKey(entry, -1);
|
gCoreLoadHeap->ModifyKey(entry, -1);
|
||||||
ASSERT(gCoreLoadHeap->PeekMinimum() == entry);
|
ASSERT(gCoreLoadHeap->PeekMinimum() == entry);
|
||||||
gCoreLoadHeap->RemoveMinimum();
|
gCoreLoadHeap->RemoveMinimum();
|
||||||
|
|
||||||
gCoreHighLoadHeap->Insert(entry, newKey);
|
gCoreHighLoadHeap->Insert(entry, newKey);
|
||||||
|
|
||||||
|
entry->fHighLoad = true;
|
||||||
} else
|
} else
|
||||||
gCoreHighLoadHeap->ModifyKey(entry, newKey);
|
gCoreHighLoadHeap->ModifyKey(entry, newKey);
|
||||||
} else {
|
} else if (newKey < kMediumLoad) {
|
||||||
if (oldKey > kHighLoad) {
|
if (entry->fHighLoad) {
|
||||||
gCoreHighLoadHeap->ModifyKey(entry, -1);
|
gCoreHighLoadHeap->ModifyKey(entry, -1);
|
||||||
ASSERT(gCoreHighLoadHeap->PeekMinimum() == entry);
|
ASSERT(gCoreHighLoadHeap->PeekMinimum() == entry);
|
||||||
gCoreHighLoadHeap->RemoveMinimum();
|
gCoreHighLoadHeap->RemoveMinimum();
|
||||||
|
|
||||||
gCoreLoadHeap->Insert(entry, newKey);
|
gCoreLoadHeap->Insert(entry, newKey);
|
||||||
|
|
||||||
|
entry->fHighLoad = false;
|
||||||
} else
|
} else
|
||||||
gCoreLoadHeap->ModifyKey(entry, newKey);
|
gCoreLoadHeap->ModifyKey(entry, newKey);
|
||||||
|
} else {
|
||||||
|
if (entry->fHighLoad)
|
||||||
|
gCoreHighLoadHeap->ModifyKey(entry, newKey);
|
||||||
|
else
|
||||||
|
gCoreLoadHeap->ModifyKey(entry, newKey);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ const bigtime_t kCacheExpire = 100000;
|
|||||||
const int kLowLoad = kMaxLoad * 20 / 100;
|
const int kLowLoad = kMaxLoad * 20 / 100;
|
||||||
const int kTargetLoad = kMaxLoad * 55 / 100;
|
const int kTargetLoad = kMaxLoad * 55 / 100;
|
||||||
const int kHighLoad = kMaxLoad * 70 / 100;
|
const int kHighLoad = kMaxLoad * 70 / 100;
|
||||||
|
const int kMediumLoad = (kHighLoad + kTargetLoad) / 2;
|
||||||
const int kVeryHighLoad = (kMaxLoad + kHighLoad) / 2;
|
const int kVeryHighLoad = (kMaxLoad + kHighLoad) / 2;
|
||||||
|
|
||||||
const int kLoadDifference = kMaxLoad * 20 / 100;
|
const int kLoadDifference = kMaxLoad * 20 / 100;
|
||||||
@@ -83,6 +84,7 @@ struct CoreEntry : public MinMaxHeapLinkImpl<CoreEntry, int32>,
|
|||||||
bigtime_t fActiveTime;
|
bigtime_t fActiveTime;
|
||||||
|
|
||||||
int32 fLoad;
|
int32 fLoad;
|
||||||
|
bool fHighLoad;
|
||||||
} CACHE_LINE_ALIGN;
|
} CACHE_LINE_ALIGN;
|
||||||
typedef MinMaxHeap<CoreEntry, int32> CoreLoadHeap;
|
typedef MinMaxHeap<CoreEntry, int32> CoreLoadHeap;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user