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