scheduler: Relax penalty cancellation requirements

Priority penalties were made more strict in order to prevent situation
when two or more high priority threads uses up all available CPU time
in such manner that they do not receive a penalty but starve low priority
threads.

However, a significant change to thread priorites has been made since and
now priority of all non real time threads varies in a range from 1 to
static priority minus penalty. This means that the scheduler is able to
prevent thread starvation without any complex penalty policies.
This commit is contained in:
Pawel Dziepak
2014-02-03 04:55:16 +01:00
parent 6155ab7b25
commit f116370edd
5 changed files with 5 additions and 56 deletions
+1 -1
View File
@@ -182,11 +182,11 @@ scheduler_set_thread_priority(Thread *thread, int32 priority)
TRACE("changing thread %ld priority to %ld (old: %ld, effective: %ld)\n", TRACE("changing thread %ld priority to %ld (old: %ld, effective: %ld)\n",
thread->id, priority, oldPriority, threadData->GetEffectivePriority()); thread->id, priority, oldPriority, threadData->GetEffectivePriority());
thread->priority = priority;
threadData->CancelPenalty(); threadData->CancelPenalty();
if (priority == thread->priority) if (priority == thread->priority)
return thread->priority; return thread->priority;
thread->priority = priority;
if (thread->state != B_THREAD_READY) { if (thread->state != B_THREAD_READY) {
if (thread->state == B_THREAD_RUNNING) { if (thread->state == B_THREAD_RUNNING) {
@@ -361,8 +361,6 @@ CoreEntry::CoreEntry()
: :
fCPUCount(0), fCPUCount(0),
fIdleCPUCount(0), fIdleCPUCount(0),
fStarvationCounter(0),
fStarvationCounterIdle(0),
fThreadCount(0), fThreadCount(0),
fActiveTime(0), fActiveTime(0),
fLoad(0), fLoad(0),
@@ -411,15 +409,11 @@ CoreEntry::Remove(ThreadData* thread)
{ {
SCHEDULER_ENTER_FUNCTION(); SCHEDULER_ENTER_FUNCTION();
ASSERT(!thread->IsIdle());
ASSERT(thread->IsEnqueued()); ASSERT(thread->IsEnqueued());
thread->SetDequeued(); thread->SetDequeued();
ASSERT(!thread_is_idle_thread(thread->GetThread()));
if (thread->GetEffectivePriority() == B_LOWEST_ACTIVE_PRIORITY
|| thread->IsCPUBound()) {
atomic_add(&fStarvationCounter, 1);
}
fRunQueue.Remove(thread); fRunQueue.Remove(thread);
atomic_add(&fThreadCount, -1); atomic_add(&fThreadCount, -1);
} }
@@ -154,9 +154,6 @@ public:
inline uint32 RemoveLoad(int32 load, bool force); inline uint32 RemoveLoad(int32 load, bool force);
inline void ChangeLoad(int32 delta); inline void ChangeLoad(int32 delta);
inline int32 StarvationCounter() const;
inline int32 StarvationCounterIdle() const;
inline void CPUGoesIdle(CPUEntry* cpu); inline void CPUGoesIdle(CPUEntry* cpu);
inline void CPUWakesUp(CPUEntry* cpu); inline void CPUWakesUp(CPUEntry* cpu);
@@ -181,9 +178,6 @@ private:
CPUPriorityHeap fCPUHeap; CPUPriorityHeap fCPUHeap;
spinlock fCPULock; spinlock fCPULock;
int32 fStarvationCounter;
int32 fStarvationCounterIdle;
int32 fThreadCount; int32 fThreadCount;
ThreadRunQueue fRunQueue; ThreadRunQueue fRunQueue;
spinlock fQueueLock; spinlock fQueueLock;
@@ -455,22 +449,6 @@ CoreEntry::ChangeLoad(int32 delta)
} }
inline int32
CoreEntry::StarvationCounter() const
{
SCHEDULER_ENTER_FUNCTION();
return fStarvationCounter;
}
inline int32
CoreEntry::StarvationCounterIdle() const
{
SCHEDULER_ENTER_FUNCTION();
return fStarvationCounterIdle;
}
/* PackageEntry::CoreGoesIdle and PackageEntry::CoreWakesUp have to be defined /* PackageEntry::CoreGoesIdle and PackageEntry::CoreWakesUp have to be defined
before CoreEntry::CPUGoesIdle and CoreEntry::CPUWakesUp. If they weren't before CoreEntry::CPUGoesIdle and CoreEntry::CPUWakesUp. If they weren't
GCC2 wouldn't inline them as, apparently, it doesn't do enough optimization GCC2 wouldn't inline them as, apparently, it doesn't do enough optimization
@@ -521,9 +499,6 @@ PackageEntry::CoreWakesUp(CoreEntry* core)
inline void inline void
CoreEntry::CPUGoesIdle(CPUEntry* /* cpu */) CoreEntry::CPUGoesIdle(CPUEntry* /* cpu */)
{ {
atomic_add(&fStarvationCounter, 1);
atomic_add(&fStarvationCounterIdle, 1);
if (gSingleCore) if (gSingleCore)
return; return;
@@ -22,7 +22,6 @@ ThreadData::_InitBase()
fAdditionalPenalty = 0; fAdditionalPenalty = 0;
fEffectivePriority = GetPriority(); fEffectivePriority = GetPriority();
fBaseQuantum = sQuantumLengths[GetEffectivePriority()]; fBaseQuantum = sQuantumLengths[GetEffectivePriority()];
fCPUBound = false;
fTimeUsed = 0; fTimeUsed = 0;
fStolenTime = 0; fStolenTime = 0;
@@ -35,8 +34,6 @@ ThreadData::_InitBase()
fWentSleep = 0; fWentSleep = 0;
fWentSleepActive = 0; fWentSleepActive = 0;
fWentSleepCount = 0;
fWentSleepCountIdle = 0;
fEnqueued = false; fEnqueued = false;
fReady = false; fReady = false;
@@ -144,7 +141,6 @@ ThreadData::Dump() const
kprintf("\tneeded_load:\t\t%" B_PRId32 "%%\n", fNeededLoad / 10); kprintf("\tneeded_load:\t\t%" B_PRId32 "%%\n", fNeededLoad / 10);
kprintf("\twent_sleep:\t\t%" B_PRId64 "\n", fWentSleep); kprintf("\twent_sleep:\t\t%" B_PRId64 "\n", fWentSleep);
kprintf("\twent_sleep_active:\t%" B_PRId64 "\n", fWentSleepActive); kprintf("\twent_sleep_active:\t%" B_PRId64 "\n", fWentSleepActive);
kprintf("\twent_sleep_count:\t%" B_PRId32 "\n", fWentSleepCount);
kprintf("\tcore:\t\t\t%" B_PRId32 "\n", kprintf("\tcore:\t\t\t%" B_PRId32 "\n",
fCore != NULL ? fCore->ID() : -1); fCore != NULL ? fCore->ID() : -1);
if (fCore != NULL && HasCacheExpired()) if (fCore != NULL && HasCacheExpired())
+2 -18
View File
@@ -48,8 +48,6 @@ public:
inline int32 GetEffectivePriority() const; inline int32 GetEffectivePriority() const;
inline bool IsCPUBound() const { return fCPUBound; }
inline void StartCPUTime(); inline void StartCPUTime();
inline void StopCPUTime(); inline void StopCPUTime();
@@ -109,15 +107,12 @@ private:
bigtime_t fWentSleep; bigtime_t fWentSleep;
bigtime_t fWentSleepActive; bigtime_t fWentSleepActive;
int32 fWentSleepCount;
int32 fWentSleepCountIdle;
bool fEnqueued; bool fEnqueued;
bool fReady; bool fReady;
Thread* fThread; Thread* fThread;
bool fCPUBound;
int32 fPriorityPenalty; int32 fPriorityPenalty;
int32 fAdditionalPenalty; int32 fAdditionalPenalty;
@@ -211,10 +206,8 @@ ThreadData::_IncreasePenalty()
int32 oldPenalty = fPriorityPenalty++; int32 oldPenalty = fPriorityPenalty++;
const int kMinimalPriority = _GetMinimalPriority(); const int kMinimalPriority = _GetMinimalPriority();
if (GetPriority() - oldPenalty <= kMinimalPriority) { if (GetPriority() - oldPenalty <= kMinimalPriority)
fPriorityPenalty = oldPenalty; fPriorityPenalty = oldPenalty;
fCPUBound = true;
}
_ComputeEffectivePriority(); _ComputeEffectivePriority();
} }
@@ -256,7 +249,6 @@ ThreadData::CancelPenalty()
int32 oldPenalty = fPriorityPenalty; int32 oldPenalty = fPriorityPenalty;
fPriorityPenalty = 0; fPriorityPenalty = 0;
fCPUBound = false;
if (oldPenalty != 0) { if (oldPenalty != 0) {
TRACE("cancelling thread %ld penalty\n", fThread->id); TRACE("cancelling thread %ld penalty\n", fThread->id);
@@ -272,13 +264,7 @@ ThreadData::ShouldCancelPenalty() const
if (fCore == NULL) if (fCore == NULL)
return false; return false;
return system_time() - fWentSleep > gCurrentMode->base_quantum / 2;
if (GetEffectivePriority() != B_LOWEST_ACTIVE_PRIORITY && !IsCPUBound()) {
if (fCore->StarvationCounter() != fWentSleepCount)
return true;
}
return fCore->StarvationCounterIdle() != fWentSleepCountIdle;
} }
@@ -374,8 +360,6 @@ ThreadData::GoesAway()
fWentSleep = system_time(); fWentSleep = system_time();
fWentSleepActive = fCore->GetActiveTime(); fWentSleepActive = fCore->GetActiveTime();
fWentSleepCount = fCore->StarvationCounter();
fWentSleepCountIdle = fCore->StarvationCounterIdle();
if (gTrackCoreLoad) if (gTrackCoreLoad)
fLoadMeasurementEpoch = fCore->RemoveLoad(fNeededLoad, false); fLoadMeasurementEpoch = fCore->RemoveLoad(fNeededLoad, false);