added 3 changesets to branch 'refs/remotes/pdziepak-github/scheduler' old head: 51592558cc941f06948a58c48ff3ff462054a713 new head: f6ad3d77f7f4cd87f56e077983f7fe895588bcee overview: https://github.com/pdziepak/Haiku/compare/5159255...f6ad3d7 ---------------------------------------------------------------------------- cd486a1: scheduler: Improve recognition of CPU bound threads 6928199: scheduler: Keep track of the number of the ready threads f6ad3d7: scheduler: Introduce strong and weak priority penalties [ Pawel Dziepak <pdziepak@xxxxxxxxxxx> ] ---------------------------------------------------------------------------- 8 files changed, 172 insertions(+), 74 deletions(-) src/system/kernel/scheduler/low_latency.cpp | 8 +-- src/system/kernel/scheduler/power_saving.cpp | 2 - src/system/kernel/scheduler/scheduler.cpp | 18 +---- src/system/kernel/scheduler/scheduler_cpu.cpp | 64 +++++++++++------ src/system/kernel/scheduler/scheduler_cpu.h | 30 ++++++-- src/system/kernel/scheduler/scheduler_modes.h | 2 - src/system/kernel/scheduler/scheduler_thread.cpp | 46 +++++++++--- src/system/kernel/scheduler/scheduler_thread.h | 76 ++++++++++++++++---- ############################################################################ Commit: cd486a157ef7dfe2607603d1b65624499d647591 Author: Pawel Dziepak <pdziepak@xxxxxxxxxxx> Date: Wed Jan 8 03:36:28 2014 UTC scheduler: Improve recognition of CPU bound threads ---------------------------------------------------------------------------- diff --git a/src/system/kernel/scheduler/low_latency.cpp b/src/system/kernel/scheduler/low_latency.cpp index 09c6f71..51381c3 100644 --- a/src/system/kernel/scheduler/low_latency.cpp +++ b/src/system/kernel/scheduler/low_latency.cpp @@ -160,13 +160,11 @@ rebalance_irqs(bool idle) scheduler_mode_operations gSchedulerLowLatencyMode = { "low latency", - true, - 2000, - 700, - { 2, 30 }, + 100, + { 2, 25 }, - 60000, + 50000, switch_to_mode, set_cpu_enabled, diff --git a/src/system/kernel/scheduler/power_saving.cpp b/src/system/kernel/scheduler/power_saving.cpp index b41bbe7..66efc8c 100644 --- a/src/system/kernel/scheduler/power_saving.cpp +++ b/src/system/kernel/scheduler/power_saving.cpp @@ -236,8 +236,6 @@ rebalance_irqs(bool idle) scheduler_mode_operations gSchedulerPowerSavingMode = { "power saving", - false, - 3000, 1000, { 3, 60 }, diff --git a/src/system/kernel/scheduler/scheduler.cpp b/src/system/kernel/scheduler/scheduler.cpp index ca04585..0ee4cd0 100644 --- a/src/system/kernel/scheduler/scheduler.cpp +++ b/src/system/kernel/scheduler/scheduler.cpp @@ -404,8 +404,6 @@ reschedule(int32 nextState) if (oldThreadData->HasQuantumEnded(oldThread->cpu->preempted, oldThread->has_yielded)) { - oldThreadData->IncreasePenalty(); - TRACE("enqueueing thread %ld into run queue priority = %ld\n", oldThread->id, oldThreadData->GetEffectivePriority()); putOldThreadAtBack = true; @@ -419,7 +417,6 @@ reschedule(int32 nextState) case THREAD_STATE_FREE_ON_RESCHED: break; default: - oldThreadData->IncreasePenalty(); oldThreadData->GoesAway(); TRACE("not enqueueing thread %ld into run queue next_state = %ld\n", oldThread->id, nextState); diff --git a/src/system/kernel/scheduler/scheduler_cpu.cpp b/src/system/kernel/scheduler/scheduler_cpu.cpp index 9f9eb48..4bdb566 100644 --- a/src/system/kernel/scheduler/scheduler_cpu.cpp +++ b/src/system/kernel/scheduler/scheduler_cpu.cpp @@ -21,7 +21,6 @@ public: static void DumpCPURunQueue(CPUEntry* cpu); static void DumpCoreRunQueue(CoreEntry* core); static void DumpIdleCoresInPackage(PackageEntry* package); - }; @@ -43,7 +42,8 @@ ThreadRunQueue::Dump() const kprintf("%p %-7" B_PRId32 " %-8" B_PRId32 " %-8" B_PRId32 " %s\n", thread, thread->id, thread->priority, - threadData->GetEffectivePriority(), thread->name); + thread->priority - threadData->GetEffectivePriority(), + thread->name); } } } @@ -159,9 +159,6 @@ CPUEntry::UpdatePriority(int32 priority) return; fCore->CPUHeap()->ModifyKey(this, priority); - if (gSingleCore) - return; - if (oldPriority == B_IDLE_PRIORITY) fCore->CPUWakesUp(this); else if (priority == B_IDLE_PRIORITY) @@ -345,6 +342,7 @@ CoreEntry::CoreEntry() fCPUCount(0), fCPUIdleCount(0), fStarvationCounter(0), + fStarvationCounterIdle(0), fThreadCount(0), fActiveTime(0), fLoad(0), @@ -380,8 +378,6 @@ CoreEntry::PushBack(ThreadData* thread, int32 priority) SCHEDULER_ENTER_FUNCTION(); fRunQueue.PushBack(thread, priority); - fThreadList.Insert(thread); - atomic_add(&fThreadCount, 1); } @@ -393,12 +389,13 @@ CoreEntry::Remove(ThreadData* thread) ASSERT(thread->IsEnqueued()); thread->SetDequeued(); - if (thread_is_idle_thread(thread->GetThread()) - || fThreadList.Head() == thread) { + + ASSERT(!thread_is_idle_thread(thread->GetThread())); + if (thread->GetEffectivePriority() == B_LOWEST_ACTIVE_PRIORITY + || thread->IsCPUBound()) { atomic_add(&fStarvationCounter, 1); } - if (thread->WentSleepCount() == 0) - fThreadList.Remove(thread); + fRunQueue.Remove(thread); atomic_add(&fThreadCount, -1); } @@ -548,8 +545,8 @@ CoreLoadHeap::Dump() CoreEntry* entry = PeekMinimum(); while (entry) { int32 key = GetKey(entry); - kprintf("%4" B_PRId32 " %3" B_PRId32 "%%\n", entry->ID(), - entry->GetLoad() / 10); + kprintf("%4" B_PRId32 " %3" B_PRId32 "%% %7" B_PRId32 "\n", entry->ID(), + entry->GetLoad() / 10, entry->ThreadCount()); RemoveMinimum(); sDebugCoreHeap.Insert(entry, key); @@ -647,7 +644,7 @@ DebugDumper::DumpIdleCoresInPackage(PackageEntry* package) static int -dump_run_queue(int argc, char **argv) +dump_run_queue(int /* argc */, char** /* argv */) { int32 cpuCount = smp_get_num_cpus(); int32 coreCount = gCoreCount; @@ -665,9 +662,9 @@ dump_run_queue(int argc, char **argv) static int -dump_cpu_heap(int argc, char** argv) +dump_cpu_heap(int /* argc */, char** /* argv */) { - kprintf("core load\n"); + kprintf("core load threads\n"); gCoreLoadHeap.Dump(); kprintf("\n"); gCoreHighLoadHeap.Dump(); @@ -685,7 +682,7 @@ dump_cpu_heap(int argc, char** argv) static int -dump_idle_cores(int argc, char** argv) +dump_idle_cores(int /* argc */, char** /* argv */) { kprintf("Idle packages:\n"); IdlePackageList::ReverseIterator idleIterator diff --git a/src/system/kernel/scheduler/scheduler_cpu.h b/src/system/kernel/scheduler/scheduler_cpu.h index 1def98d..95f20bc 100644 --- a/src/system/kernel/scheduler/scheduler_cpu.h +++ b/src/system/kernel/scheduler/scheduler_cpu.h @@ -150,6 +150,7 @@ public: void UpdateLoad(int32 delta); inline int32 StarvationCounter() const; + inline int32 StarvationCounterIdle() const; inline void CPUGoesIdle(CPUEntry* cpu); inline void CPUWakesUp(CPUEntry* cpu); @@ -174,7 +175,7 @@ private: spinlock fCPULock; int32 fStarvationCounter; - DoublyLinkedList<ThreadData> fThreadList; + int32 fStarvationCounterIdle; int32 fThreadCount; ThreadRunQueue fRunQueue; @@ -387,6 +388,14 @@ CoreEntry::StarvationCounter() const } +inline int32 +CoreEntry::StarvationCounterIdle() const +{ + SCHEDULER_ENTER_FUNCTION(); + return fStarvationCounterIdle; +} + + /* PackageEntry::CoreGoesIdle and PackageEntry::CoreWakesUp have to be defined before CoreEntry::CPUGoesIdle and CoreEntry::CPUWakesUp. If they weren't GCC2 wouldn't inline them as, apparently, it doesn't do enough optimization @@ -437,8 +446,13 @@ PackageEntry::CoreWakesUp(CoreEntry* core) inline void CoreEntry::CPUGoesIdle(CPUEntry* /* cpu */) { - ASSERT(fCPUIdleCount < fCPUCount); + atomic_add(&fStarvationCounter, 1); + atomic_add(&fStarvationCounterIdle, 1); + + if (gSingleCore) + return; + ASSERT(fCPUIdleCount < fCPUCount); if (++fCPUIdleCount == fCPUCount) fPackage->CoreGoesIdle(this); } @@ -447,8 +461,10 @@ CoreEntry::CPUGoesIdle(CPUEntry* /* cpu */) inline void CoreEntry::CPUWakesUp(CPUEntry* /* cpu */) { - ASSERT(fCPUIdleCount > 0); + if (gSingleCore) + return; + ASSERT(fCPUIdleCount > 0); if (fCPUIdleCount-- == fCPUCount) fPackage->CoreWakesUp(this); } diff --git a/src/system/kernel/scheduler/scheduler_modes.h b/src/system/kernel/scheduler/scheduler_modes.h index 09670dd..820912a 100644 --- a/src/system/kernel/scheduler/scheduler_modes.h +++ b/src/system/kernel/scheduler/scheduler_modes.h @@ -13,8 +13,6 @@ struct scheduler_mode_operations { const char* name; - bool avoid_boost; - bigtime_t base_quantum; bigtime_t minimal_quantum; bigtime_t quantum_multipliers[2]; diff --git a/src/system/kernel/scheduler/scheduler_thread.cpp b/src/system/kernel/scheduler/scheduler_thread.cpp index af4b40a..e7a2445 100644 --- a/src/system/kernel/scheduler/scheduler_thread.cpp +++ b/src/system/kernel/scheduler/scheduler_thread.cpp @@ -19,6 +19,9 @@ ThreadData::_InitBase() fAdditionalPenalty = 0; fEffectivePriority = fThread->priority; + fReceivedPenalty = false; + fHasSlept = false; + fTimeLeft = 0; fStolenTime = 0; @@ -28,7 +31,8 @@ ThreadData::_InitBase() fWentSleep = 0; fWentSleepActive = 0; - fWentSleepCount = -1; + fWentSleepCount = 0; + fWentSleepCountIdle = 0; fEnqueued = false; } @@ -124,7 +128,25 @@ ThreadData::Dump() const additionalPenalty = fAdditionalPenalty % kMinimalPriority; kprintf("\tadditional_penalty:\t%" B_PRId32 " (%" B_PRId32 ")\n", additionalPenalty, fAdditionalPenalty); - kprintf("\tstolen_time:\t\t%" B_PRId64 "\n", fStolenTime); + 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("\tstolen_time:\t\t%" B_PRId64 " us\n", fStolenTime); + kprintf("\tquantum_start:\t\t%" B_PRId64 " us\n", fQuantumStart); kprintf("\tload:\t\t\t%" B_PRId32 "%%\n", fLoad / 10); kprintf("\twent_sleep:\t\t%" B_PRId64 "\n", fWentSleep); kprintf("\twent_sleep_active:\t%" B_PRId64 "\n", fWentSleepActive); diff --git a/src/system/kernel/scheduler/scheduler_thread.h b/src/system/kernel/scheduler/scheduler_thread.h index 5c8d052..fd28497 100644 --- a/src/system/kernel/scheduler/scheduler_thread.h +++ b/src/system/kernel/scheduler/scheduler_thread.h @@ -44,10 +44,11 @@ public: inline int32 GetEffectivePriority() const; - inline void IncreasePenalty(); inline void CancelPenalty(); inline bool ShouldCancelPenalty() const; + inline bool IsCPUBound() const { return fAdditionalPenalty != 0; } + bool ChooseCoreAndCPU(CoreEntry*& targetCore, CPUEntry*& targetCPU); @@ -58,7 +59,6 @@ public: inline void GoesAway(); inline bigtime_t WentSleep() const { return fWentSleep; } inline bigtime_t WentSleepActive() const { return fWentSleepActive; } - inline bigtime_t WentSleepCount() const { return fWentSleepCount; } inline void PutBack(); inline void Enqueue(); @@ -83,6 +83,7 @@ public: static void ComputeQuantumLengths(); private: + inline void _IncreasePenalty(); inline int32 _GetPenalty() const; void _ComputeEffectivePriority() const; @@ -98,6 +99,7 @@ private: bigtime_t fWentSleep; bigtime_t fWentSleepActive; int32 fWentSleepCount; + int32 fWentSleepCountIdle; bool fEnqueued; @@ -105,6 +107,8 @@ private: int32 fPriorityPenalty; int32 fAdditionalPenalty; + bool fReceivedPenalty; + bool fHasSlept; mutable int32 fEffectivePriority; @@ -167,7 +171,7 @@ ThreadData::GetEffectivePriority() const inline void -ThreadData::IncreasePenalty() +ThreadData::_IncreasePenalty() { SCHEDULER_ENTER_FUNCTION(); @@ -178,6 +182,7 @@ ThreadData::IncreasePenalty() TRACE("increasing thread %ld penalty\n", fThread->id); + fReceivedPenalty = true; int32 oldPenalty = fPriorityPenalty++; ASSERT(fThread->priority - oldPenalty >= B_LOWEST_ACTIVE_PRIORITY); @@ -216,9 +221,16 @@ ThreadData::ShouldCancelPenalty() const if (fCore == NULL) return false; + if (system_time() - fWentSleep > gCurrentMode->minimal_quantum * 2) + return false; + + if (GetEffectivePriority() != B_LOWEST_ACTIVE_PRIORITY + && !IsCPUBound()) { + if (fCore->StarvationCounter() != fWentSleepCount) + return true; + } - return fCore->StarvationCounter() != fWentSleepCount - && system_time() - fWentSleep > gCurrentMode->base_quantum; + return fCore->StarvationCounterIdle() != fWentSleepCountIdle; } @@ -238,10 +250,15 @@ ThreadData::GoesAway() { SCHEDULER_ENTER_FUNCTION(); + if (!fReceivedPenalty) + _IncreasePenalty(); + fHasSlept = true; + fLastInterruptTime = 0; fWentSleep = system_time(); fWentSleepCount = fCore->StarvationCounter(); + fWentSleepCountIdle = fCore->StarvationCounterIdle(); fWentSleepActive = fCore->GetActiveTime(); } @@ -253,7 +270,6 @@ ThreadData::PutBack() if (gTrackLoad) ComputeLoad(); - fWentSleepCount = -1; int32 priority = GetEffectivePriority(); @@ -285,7 +301,6 @@ ThreadData::Enqueue() if (gTrackLoad) ComputeLoad(); - fWentSleepCount = 0; int32 priority = GetEffectivePriority(); @@ -328,7 +343,7 @@ ThreadData::Dequeue() CoreRunQueueLocker _(fCore); if (!fEnqueued) return false; - ASSERT(fWentSleepCount < 1); + fCore->Remove(this); ASSERT(!fEnqueued); return true; @@ -354,15 +369,25 @@ ThreadData::HasQuantumEnded(bool wasPreempted, bool hasYielded) } bigtime_t timeUsed = system_time() - fQuantumStart; - fTimeLeft -= timeUsed; + if (timeUsed > 0); + fTimeLeft -= timeUsed; fTimeLeft = std::max(fTimeLeft, bigtime_t(0)); // too little time left, it's better make the next quantum a bit longer - if (wasPreempted || fTimeLeft <= gCurrentMode->minimal_quantum) { + int32 skipTime = gCurrentMode->minimal_quantum; + skipTime -= skipTime / 10; + if (wasPreempted || fTimeLeft <= skipTime) { fStolenTime += fTimeLeft; fTimeLeft = 0; } + if (fTimeLeft == 0) { + if (!fReceivedPenalty && !fHasSlept) + _IncreasePenalty(); + fReceivedPenalty = false; + fHasSlept = false; + } + return fTimeLeft == 0; } ############################################################################ Commit: 6928199bc882d48c9f08bfb15162f044e9751464 Author: Pawel Dziepak <pdziepak@xxxxxxxxxxx> Date: Wed Jan 8 04:02:04 2014 UTC scheduler: Keep track of the number of the ready threads ---------------------------------------------------------------------------- diff --git a/src/system/kernel/scheduler/scheduler.cpp b/src/system/kernel/scheduler/scheduler.cpp index 0ee4cd0..babf25b 100644 --- a/src/system/kernel/scheduler/scheduler.cpp +++ b/src/system/kernel/scheduler/scheduler.cpp @@ -53,20 +53,6 @@ bool gSingleCore; bool gCPUFrequencyManagement; bool gTrackLoad; -CPUEntry* gCPUEntries; - -CoreEntry* gCoreEntries; -CoreLoadHeap gCoreLoadHeap; -CoreLoadHeap gCoreHighLoadHeap; -rw_spinlock gCoreHeapsLock = B_RW_SPINLOCK_INITIALIZER; -int32 gCoreCount; - -PackageEntry* gPackageEntries; -IdlePackageList gIdlePackageList; -rw_spinlock gIdlePackageLock = B_RW_SPINLOCK_INITIALIZER; -int32 gPackageCount; - - } // namespace Scheduler using namespace Scheduler; @@ -415,6 +401,7 @@ reschedule(int32 nextState) break; case THREAD_STATE_FREE_ON_RESCHED: + oldThreadData->Dies(); break; default: oldThreadData->GoesAway(); diff --git a/src/system/kernel/scheduler/scheduler_cpu.cpp b/src/system/kernel/scheduler/scheduler_cpu.cpp index 4bdb566..d715e72 100644 --- a/src/system/kernel/scheduler/scheduler_cpu.cpp +++ b/src/system/kernel/scheduler/scheduler_cpu.cpp @@ -13,6 +13,25 @@ #include "scheduler_thread.h" +namespace Scheduler { + + +CPUEntry* gCPUEntries; + +CoreEntry* gCoreEntries; +CoreLoadHeap gCoreLoadHeap; +CoreLoadHeap gCoreHighLoadHeap; +rw_spinlock gCoreHeapsLock = B_RW_SPINLOCK_INITIALIZER; +int32 gCoreCount; + +PackageEntry* gPackageEntries; +IdlePackageList gIdlePackageList; +rw_spinlock gIdlePackageLock = B_RW_SPINLOCK_INITIALIZER; +int32 gPackageCount; + + +} // namespace Scheduler + using namespace Scheduler; @@ -340,7 +359,7 @@ CPUPriorityHeap::Dump() CoreEntry::CoreEntry() : fCPUCount(0), - fCPUIdleCount(0), + fIdleCPUCount(0), fStarvationCounter(0), fStarvationCounterIdle(0), fThreadCount(0), @@ -459,9 +478,9 @@ void CoreEntry::AddCPU(CPUEntry* cpu) { ASSERT(fCPUCount >= 0); - ASSERT(fCPUIdleCount >= 0); + ASSERT(fIdleCPUCount >= 0); - fCPUIdleCount++; + fIdleCPUCount++; if (fCPUCount++ == 0) { // core has been reenabled fLoad = 0; @@ -479,9 +498,9 @@ void CoreEntry::RemoveCPU(CPUEntry* cpu, ThreadProcessing& threadPostProcessing) { ASSERT(fCPUCount > 0); - ASSERT(fCPUIdleCount > 0); + ASSERT(fIdleCPUCount > 0); - fCPUIdleCount--; + fIdleCPUCount--; if (--fCPUCount == 0) { // core has been disabled if (fHighLoad) { @@ -545,8 +564,10 @@ CoreLoadHeap::Dump() CoreEntry* entry = PeekMinimum(); while (entry) { int32 key = GetKey(entry); + + int32 activeCPUs = entry->CPUCount() - entry->IdleCPUCount(); kprintf("%4" B_PRId32 " %3" B_PRId32 "%% %7" B_PRId32 "\n", entry->ID(), - entry->GetLoad() / 10, entry->ThreadCount()); + entry->GetLoad() / 10, entry->ThreadCount() + activeCPUs); RemoveMinimum(); sDebugCoreHeap.Insert(entry, key); @@ -664,6 +685,8 @@ dump_run_queue(int /* argc */, char** /* argv */) static int dump_cpu_heap(int /* argc */, char** /* argv */) { + kprintf("Total ready threads: %" B_PRId32 "\n\n", gReadyThreadCount); + kprintf("core load threads\n"); gCoreLoadHeap.Dump(); kprintf("\n"); diff --git a/src/system/kernel/scheduler/scheduler_cpu.h b/src/system/kernel/scheduler/scheduler_cpu.h index 95f20bc..6c1d209 100644 --- a/src/system/kernel/scheduler/scheduler_cpu.h +++ b/src/system/kernel/scheduler/scheduler_cpu.h @@ -123,6 +123,8 @@ public: inline PackageEntry* Package() const { return fPackage; } inline int32 CPUCount() const { return fCPUCount; } + inline int32 IdleCPUCount() const + { return fIdleCPUCount; } inline void LockCPUHeap(); inline void UnlockCPUHeap(); @@ -170,7 +172,7 @@ private: PackageEntry* fPackage; int32 fCPUCount; - int32 fCPUIdleCount; + int32 fIdleCPUCount; CPUPriorityHeap fCPUHeap; spinlock fCPULock; @@ -452,8 +454,8 @@ CoreEntry::CPUGoesIdle(CPUEntry* /* cpu */) if (gSingleCore) return; - ASSERT(fCPUIdleCount < fCPUCount); - if (++fCPUIdleCount == fCPUCount) + ASSERT(fIdleCPUCount < fCPUCount); + if (++fIdleCPUCount == fCPUCount) fPackage->CoreGoesIdle(this); } @@ -464,8 +466,8 @@ CoreEntry::CPUWakesUp(CPUEntry* /* cpu */) if (gSingleCore) return; - ASSERT(fCPUIdleCount > 0); - if (fCPUIdleCount-- == fCPUCount) + ASSERT(fIdleCPUCount > 0); + if (fIdleCPUCount-- == fCPUCount) fPackage->CoreWakesUp(this); } diff --git a/src/system/kernel/scheduler/scheduler_thread.cpp b/src/system/kernel/scheduler/scheduler_thread.cpp index e7a2445..63f4450 100644 --- a/src/system/kernel/scheduler/scheduler_thread.cpp +++ b/src/system/kernel/scheduler/scheduler_thread.cpp @@ -6,6 +6,14 @@ #include "scheduler_thread.h" +namespace Scheduler { + + +int32 gReadyThreadCount; + + +} // namespace Scheduler + using namespace Scheduler; diff --git a/src/system/kernel/scheduler/scheduler_thread.h b/src/system/kernel/scheduler/scheduler_thread.h index fd28497..8966920 100644 --- a/src/system/kernel/scheduler/scheduler_thread.h +++ b/src/system/kernel/scheduler/scheduler_thread.h @@ -57,6 +57,8 @@ public: inline void SetStolenInterruptTime(bigtime_t interruptTime); inline void GoesAway(); + inline void Dies(); + inline bigtime_t WentSleep() const { return fWentSleep; } inline bigtime_t WentSleepActive() const { return fWentSleepActive; } @@ -128,6 +130,8 @@ public: virtual void operator()(ThreadData* thread) = 0; }; +extern int32 gReadyThreadCount; + inline int32 ThreadData::_GetMinimalPriority() const @@ -260,6 +264,16 @@ ThreadData::GoesAway() fWentSleepCount = fCore->StarvationCounter(); fWentSleepCountIdle = fCore->StarvationCounterIdle(); fWentSleepActive = fCore->GetActiveTime(); + + atomic_add(&gReadyThreadCount, -1); +} + + +inline void +ThreadData::Dies() +{ + SCHEDULER_ENTER_FUNCTION(); + atomic_add(&gReadyThreadCount, -1); } @@ -297,6 +311,9 @@ ThreadData::Enqueue() { SCHEDULER_ENTER_FUNCTION(); + if (fThread->state != B_THREAD_READY && fThread->state != B_THREAD_RUNNING) + atomic_add(&gReadyThreadCount, 1); + fThread->state = B_THREAD_READY; if (gTrackLoad) ############################################################################ Commit: f6ad3d77f7f4cd87f56e077983f7fe895588bcee Author: Pawel Dziepak <pdziepak@xxxxxxxxxxx> Date: Wed Jan 8 06:03:22 2014 UTC scheduler: Introduce strong and weak priority penalties ---------------------------------------------------------------------------- diff --git a/src/system/kernel/scheduler/low_latency.cpp b/src/system/kernel/scheduler/low_latency.cpp index 51381c3..3b567cb 100644 --- a/src/system/kernel/scheduler/low_latency.cpp +++ b/src/system/kernel/scheduler/low_latency.cpp @@ -164,7 +164,7 @@ scheduler_mode_operations gSchedulerLowLatencyMode = { 100, { 2, 25 }, - 50000, + 10000, switch_to_mode, set_cpu_enabled, diff --git a/src/system/kernel/scheduler/scheduler_thread.cpp b/src/system/kernel/scheduler/scheduler_thread.cpp index 63f4450..a16cf32 100644 --- a/src/system/kernel/scheduler/scheduler_thread.cpp +++ b/src/system/kernel/scheduler/scheduler_thread.cpp @@ -217,14 +217,14 @@ ThreadData::ComputeQuantum() quantum += fStolenTime; fStolenTime = 0; - 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); + int32 threadCount = fCore->ThreadCount() / fCore->CPUCount(); + if (threadCount >= 1) { + quantum + = std::min(gCurrentMode->maximum_latency / threadCount, quantum); + quantum = std::max(quantum, gCurrentMode->minimal_quantum); + } fTimeLeft = quantum; - return quantum; } diff --git a/src/system/kernel/scheduler/scheduler_thread.h b/src/system/kernel/scheduler/scheduler_thread.h index 8966920..92e5f23 100644 --- a/src/system/kernel/scheduler/scheduler_thread.h +++ b/src/system/kernel/scheduler/scheduler_thread.h @@ -44,11 +44,11 @@ public: inline int32 GetEffectivePriority() const; + inline bool IsCPUBound() const; + inline void CancelPenalty(); inline bool ShouldCancelPenalty() const; - inline bool IsCPUBound() const { return fAdditionalPenalty != 0; } - bool ChooseCoreAndCPU(CoreEntry*& targetCore, CPUEntry*& targetCPU); @@ -85,7 +85,7 @@ public: static void ComputeQuantumLengths(); private: - inline void _IncreasePenalty(); + inline void _IncreasePenalty(bool strong); inline int32 _GetPenalty() const; void _ComputeEffectivePriority() const; @@ -175,7 +175,7 @@ ThreadData::GetEffectivePriority() const inline void -ThreadData::_IncreasePenalty() +ThreadData::_IncreasePenalty(bool strong) { SCHEDULER_ENTER_FUNCTION(); @@ -187,12 +187,14 @@ ThreadData::_IncreasePenalty() TRACE("increasing thread %ld penalty\n", fThread->id); fReceivedPenalty = true; - int32 oldPenalty = fPriorityPenalty++; + int32 oldPenalty = fPriorityPenalty; + if (strong) + fPriorityPenalty++; ASSERT(fThread->priority - oldPenalty >= B_LOWEST_ACTIVE_PRIORITY); const int kMinimalPriority = _GetMinimalPriority(); - if (fThread->priority - oldPenalty <= kMinimalPriority) { + if (!strong || fThread->priority - oldPenalty <= kMinimalPriority) { fPriorityPenalty = oldPenalty; fAdditionalPenalty++; } @@ -201,6 +203,14 @@ ThreadData::_IncreasePenalty() } +inline bool +ThreadData::IsCPUBound() const +{ + SCHEDULER_ENTER_FUNCTION(); + return fAdditionalPenalty != 0 && fPriorityPenalty != 0; +} + + inline void ThreadData::CancelPenalty() { @@ -255,7 +265,7 @@ ThreadData::GoesAway() SCHEDULER_ENTER_FUNCTION(); if (!fReceivedPenalty) - _IncreasePenalty(); + _IncreasePenalty(false); fHasSlept = true; fLastInterruptTime = 0; @@ -400,7 +410,7 @@ ThreadData::HasQuantumEnded(bool wasPreempted, bool hasYielded) if (fTimeLeft == 0) { if (!fReceivedPenalty && !fHasSlept) - _IncreasePenalty(); + _IncreasePenalty(true); fReceivedPenalty = false; fHasSlept = false; }