scheduler: Improve latencies

This commit is contained in:
Pawel Dziepak
2014-01-16 23:26:09 +01:00
parent 7f212f45c3
commit 093c220267
5 changed files with 89 additions and 124 deletions
+3 -3
View File
@@ -161,10 +161,10 @@ scheduler_mode_operations gSchedulerLowLatencyMode = {
"low latency",
1000,
50,
{ 2, 50 },
100,
{ 2, 5 },
50000,
5000,
switch_to_mode,
set_cpu_enabled,
+4 -4
View File
@@ -236,11 +236,11 @@ rebalance_irqs(bool idle)
scheduler_mode_operations gSchedulerPowerSavingMode = {
"power saving",
3000,
1000,
{ 3, 60 },
2000,
500,
{ 3, 10 },
200000,
20000,
switch_to_mode,
set_cpu_enabled,
+2 -2
View File
@@ -1,5 +1,5 @@
/*
* Copyright 2013, Paweł Dziepak, [email protected].
* Copyright 2013-2014, Paweł Dziepak, [email protected].
* Copyright 2009, Rene Gollent, [email protected].
* Copyright 2008-2011, Ingo Weinhold, [email protected].
* Copyright 2002-2010, Axel Dörfler, [email protected].
@@ -484,7 +484,7 @@ reschedule(int32 nextState)
oldThread->cpu->preempted = false;
if (!thread_is_idle_thread(nextThread)) {
bigtime_t quantum = nextThreadData->ComputeQuantum();
bigtime_t quantum = nextThreadData->GetQuantumLeft();
add_timer(quantumTimer, &reschedule_event, quantum,
B_ONE_SHOT_RELATIVE_TIMER);
@@ -19,10 +19,7 @@ ThreadData::_InitBase()
fAdditionalPenalty = 0;
fEffectivePriority = fThread->priority;
fReceivedPenalty = false;
fHasSlept = false;
fTimeLeft = 0;
fTimeUsed = 0;
fStolenTime = 0;
fMeasureAvailableActiveTime = 0;
@@ -111,11 +108,6 @@ ThreadData::Init()
fCore = currentThreadData->fCore;
if (fThread->priority < B_FIRST_REAL_TIME_PRIORITY) {
if (!thread_is_idle_thread(currentThread)
&& currentThread->priority < B_FIRST_REAL_TIME_PRIORITY) {
currentThreadData->_IncreasePenalty(false);
}
fPriorityPenalty = std::min(currentThreadData->fPriorityPenalty,
std::max(fThread->priority - _GetMinimalPriority(), int32(0)));
fAdditionalPenalty = currentThreadData->fAdditionalPenalty;
@@ -148,21 +140,8 @@ ThreadData::Dump() const
additionalPenalty, fAdditionalPenalty);
kprintf("\teffective_priority:\t%" B_PRId32 "\n", GetEffectivePriority());
kprintf("\treceived_penalty:\t%s\n", fReceivedPenalty ? "true" : "false");
kprintf("\thas_slept:\t\t%s\n", fHasSlept ? "true" : "false");
bigtime_t quantum = _GetBaseQuantum();
if (fThread->priority < B_FIRST_REAL_TIME_PRIORITY) {
int32 threadCount = (fCore->ThreadCount() + 1) / fCore->CPUCount();
threadCount = max_c(threadCount, 1);
quantum
= std::min(gCurrentMode->maximum_latency / threadCount, quantum);
quantum = std::max(quantum, gCurrentMode->minimal_quantum);
}
kprintf("\ttime_left:\t\t%" B_PRId64 " us (quantum: %" B_PRId64 " us)\n",
fTimeLeft, quantum);
kprintf("\ttime_used:\t\t%" B_PRId64 " us (quantum: %" B_PRId64 " us)\n",
fTimeUsed, ComputeQuantum());
kprintf("\tstolen_time:\t\t%" B_PRId64 " us\n", fStolenTime);
kprintf("\tquantum_start:\t\t%" B_PRId64 " us\n", fQuantumStart);
kprintf("\tneeded_load:\t\t%" B_PRId32 "%%\n", fNeededLoad / 10);
@@ -206,22 +185,14 @@ ThreadData::ChooseCoreAndCPU(CoreEntry*& targetCore, CPUEntry*& targetCPU)
bigtime_t
ThreadData::ComputeQuantum()
ThreadData::ComputeQuantum() const
{
SCHEDULER_ENTER_FUNCTION();
bigtime_t quantum;
if (fTimeLeft != 0)
quantum = fTimeLeft;
else
quantum = _GetBaseQuantum();
bigtime_t quantum = _GetBaseQuantum();
if (fThread->priority >= B_FIRST_REAL_TIME_PRIORITY)
return quantum;
quantum += fStolenTime;
fStolenTime = 0;
int32 threadCount = fCore->ThreadCount() / fCore->CPUCount();
if (threadCount >= 1) {
quantum
@@ -229,7 +200,6 @@ ThreadData::ComputeQuantum()
quantum = std::max(quantum, gCurrentMode->minimal_quantum);
}
fTimeLeft = quantum;
return quantum;
}
@@ -266,14 +236,7 @@ inline int32
ThreadData::_GetPenalty() const
{
SCHEDULER_ENTER_FUNCTION();
int32 penalty = fPriorityPenalty;
const int kMinimalPriority = _GetMinimalPriority();
if (kMinimalPriority > 0)
penalty += fAdditionalPenalty % kMinimalPriority;
return penalty;
return fPriorityPenalty;
}
@@ -304,6 +267,8 @@ ThreadData::_ComputeEffectivePriority() const
else {
fEffectivePriority = fThread->priority;
fEffectivePriority -= _GetPenalty();
if (fEffectivePriority > 0)
fEffectivePriority -= fAdditionalPenalty % fEffectivePriority;
ASSERT(fEffectivePriority < B_FIRST_REAL_TIME_PRIORITY);
ASSERT(fEffectivePriority >= B_LOWEST_ACTIVE_PRIORITY);
+72 -72
View File
@@ -56,6 +56,11 @@ public:
{ fLastInterruptTime = interruptTime; }
inline void SetStolenInterruptTime(bigtime_t interruptTime);
bigtime_t ComputeQuantum() const;
inline bigtime_t GetQuantumLeft();
inline void StartQuantum();
inline bool HasQuantumEnded(bool wasPreempted, bool hasYielded);
inline void Continues();
inline void GoesAway();
inline void Dies();
@@ -69,10 +74,6 @@ public:
inline void UpdateActivity(bigtime_t active);
inline bool HasQuantumEnded(bool wasPreempted, bool hasYielded);
bigtime_t ComputeQuantum();
inline void StartQuantum();
inline bool IsEnqueued() const { return fEnqueued; }
inline void SetDequeued() { fEnqueued = false; }
@@ -85,7 +86,7 @@ public:
static void ComputeQuantumLengths();
private:
inline void _IncreasePenalty(bool strong);
inline void _IncreasePenalty();
inline int32 _GetPenalty() const;
void _ComputeNeededLoad();
@@ -112,12 +113,10 @@ private:
int32 fPriorityPenalty;
int32 fAdditionalPenalty;
bool fReceivedPenalty;
bool fHasSlept;
mutable int32 fEffectivePriority;
bigtime_t fTimeLeft;
bigtime_t fTimeUsed;
bigtime_t fMeasureAvailableActiveTime;
bigtime_t fMeasureAvailableTime;
@@ -178,7 +177,7 @@ ThreadData::GetEffectivePriority() const
inline void
ThreadData::_IncreasePenalty(bool strong)
ThreadData::_IncreasePenalty()
{
SCHEDULER_ENTER_FUNCTION();
@@ -189,18 +188,10 @@ ThreadData::_IncreasePenalty(bool strong)
TRACE("increasing thread %ld penalty\n", fThread->id);
fReceivedPenalty = true;
int32 oldPenalty = fPriorityPenalty;
if (strong)
fPriorityPenalty++;
ASSERT(fThread->priority - oldPenalty >= B_LOWEST_ACTIVE_PRIORITY);
int32 oldPenalty = fPriorityPenalty++;
const int kMinimalPriority = _GetMinimalPriority();
if (!strong || fThread->priority - oldPenalty <= kMinimalPriority) {
if (fThread->priority - oldPenalty <= kMinimalPriority)
fPriorityPenalty = oldPenalty;
fAdditionalPenalty++;
}
_ComputeEffectivePriority();
}
@@ -210,7 +201,7 @@ inline bool
ThreadData::IsCPUBound() const
{
SCHEDULER_ENTER_FUNCTION();
return fAdditionalPenalty != 0 && fPriorityPenalty != 0;
return GetThread()->priority - fPriorityPenalty == _GetMinimalPriority();
}
@@ -220,8 +211,6 @@ ThreadData::CancelPenalty()
SCHEDULER_ENTER_FUNCTION();
int32 oldPenalty = fPriorityPenalty;
fAdditionalPenalty = 0;
fPriorityPenalty = 0;
if (oldPenalty != 0) {
@@ -239,8 +228,7 @@ ThreadData::ShouldCancelPenalty() const
if (fCore == NULL)
return false;
if (GetEffectivePriority() != B_LOWEST_ACTIVE_PRIORITY
&& !IsCPUBound()) {
if (GetEffectivePriority() != B_LOWEST_ACTIVE_PRIORITY && !IsCPUBound()) {
if (fCore->StarvationCounter() != fWentSleepCount)
return true;
}
@@ -259,6 +247,61 @@ ThreadData::SetStolenInterruptTime(bigtime_t interruptTime)
}
inline bigtime_t
ThreadData::GetQuantumLeft()
{
SCHEDULER_ENTER_FUNCTION();
bigtime_t stolenTime = std::min(fStolenTime, gCurrentMode->minimal_quantum);
ASSERT(stolenTime >= 0);
fStolenTime -= stolenTime;
bigtime_t quantum = ComputeQuantum() - fTimeUsed;
quantum += stolenTime;
quantum = std::max(quantum, gCurrentMode->minimal_quantum);
return quantum;
}
inline void
ThreadData::StartQuantum()
{
SCHEDULER_ENTER_FUNCTION();
fQuantumStart = system_time();
}
inline bool
ThreadData::HasQuantumEnded(bool wasPreempted, bool hasYielded)
{
SCHEDULER_ENTER_FUNCTION();
bigtime_t timeUsed = system_time() - fQuantumStart;
ASSERT(timeUsed >= 0);
fTimeUsed += timeUsed;
bigtime_t timeLeft = ComputeQuantum() - fTimeUsed;
timeLeft = std::max(bigtime_t(0), timeLeft);
// too little time left, it's better make the next quantum a bit longer
bigtime_t skipTime = gCurrentMode->minimal_quantum / 2;
if (hasYielded || wasPreempted || timeLeft <= skipTime) {
fStolenTime += timeLeft;
timeLeft = 0;
}
if (timeLeft == 0) {
fAdditionalPenalty++;
_IncreasePenalty();
fTimeUsed = 0;
return true;
}
return false;
}
inline void
ThreadData::Continues()
{
@@ -277,20 +320,17 @@ ThreadData::GoesAway()
ASSERT(fReady);
bigtime_t timeUsed = system_time() - fQuantumStart;
ASSERT(timeUsed >= 0);
fTimeLeft -= timeUsed;
if (!fReceivedPenalty)
_IncreasePenalty(false);
fHasSlept = true;
if (!HasQuantumEnded(false, false)) {
fAdditionalPenalty++;
_ComputeEffectivePriority();
}
fLastInterruptTime = 0;
fWentSleep = system_time();
fWentSleepActive = fCore->GetActiveTime();
fWentSleepCount = fCore->StarvationCounter();
fWentSleepCountIdle = fCore->StarvationCounterIdle();
fWentSleepActive = fCore->GetActiveTime();
if (gTrackCoreLoad)
fCore->UpdateLoad(-fNeededLoad);
@@ -415,46 +455,6 @@ ThreadData::UpdateActivity(bigtime_t active)
}
inline bool
ThreadData::HasQuantumEnded(bool wasPreempted, bool hasYielded)
{
SCHEDULER_ENTER_FUNCTION();
bigtime_t timeUsed = system_time() - fQuantumStart;
ASSERT(timeUsed >= 0);
fTimeLeft -= timeUsed;
if (hasYielded) {
fTimeLeft = 0;
return true;
}
// too little time left, it's better make the next quantum a bit longer
int32 skipTime = gCurrentMode->minimal_quantum / 2;
if (wasPreempted || fTimeLeft <= skipTime) {
fStolenTime += fTimeLeft;
fTimeLeft = 0;
}
if (fTimeLeft == 0) {
if (!fReceivedPenalty && !fHasSlept)
_IncreasePenalty(true);
fReceivedPenalty = false;
fHasSlept = false;
}
return fTimeLeft == 0;
}
inline void
ThreadData::StartQuantum()
{
SCHEDULER_ENTER_FUNCTION();
fQuantumStart = system_time();
}
inline void
ThreadData::UnassignCore(bool running)
{