added 2 changesets to branch 'refs/remotes/pdziepak-github/scheduler' old head: 667617ad043a4587d8d366d5192d9ad291cfa37a new head: 7b55bf560cdf757d66223228bb13796a4e788c71 overview: https://github.com/pdziepak/Haiku/compare/667617a...7b55bf5 ---------------------------------------------------------------------------- 06ac482: scheduler: Work around GCC2 limitations in function inlining GCC2 won't inline a function if it is used before its definition. 7b55bf5: scheduler: Improve thread creation performance [ Pawel Dziepak <pdziepak@xxxxxxxxxxx> ] ---------------------------------------------------------------------------- 7 files changed, 386 insertions(+), 342 deletions(-) headers/private/kernel/smp.h | 9 +- src/system/kernel/scheduler/scheduler.cpp | 92 +---------- src/system/kernel/scheduler/scheduler_cpu.cpp | 98 +++-------- src/system/kernel/scheduler/scheduler_cpu.h | 117 +++++++------ src/system/kernel/scheduler/scheduler_locking.h | 158 ++++++++++++++++++ src/system/kernel/scheduler/scheduler_thread.cpp | 165 ++++++++++--------- src/system/kernel/scheduler/scheduler_thread.h | 89 +++++----- ############################################################################ Commit: 06ac482d9692c07e95af8516800001622e62e32a Author: Pawel Dziepak <pdziepak@xxxxxxxxxxx> Date: Sun Jan 5 04:55:13 2014 UTC scheduler: Work around GCC2 limitations in function inlining GCC2 won't inline a function if it is used before its definition. ---------------------------------------------------------------------------- diff --git a/headers/private/kernel/smp.h b/headers/private/kernel/smp.h index 88a89e4..3378f23 100644 --- a/headers/private/kernel/smp.h +++ b/headers/private/kernel/smp.h @@ -41,7 +41,7 @@ typedef void (*smp_call_func)(addr_t data1, int32 currentCPU, addr_t data2, addr class CPUSet { public: - CPUSet() { ClearAll(); } + inline CPUSet(); inline void ClearAll(); inline void SetAll(); @@ -92,6 +92,13 @@ int smp_intercpu_int_handler(int32 cpu); #endif +inline +CPUSet::CPUSet() +{ + memset(fBitmap, 0, sizeof(fBitmap)); +} + + inline void CPUSet::ClearAll() { diff --git a/src/system/kernel/scheduler/scheduler.cpp b/src/system/kernel/scheduler/scheduler.cpp index de6a49f..2916b5b 100644 --- a/src/system/kernel/scheduler/scheduler.cpp +++ b/src/system/kernel/scheduler/scheduler.cpp @@ -31,6 +31,7 @@ #include "scheduler_common.h" #include "scheduler_cpu.h" +#include "scheduler_locking.h" #include "scheduler_modes.h" #include "scheduler_profiler.h" #include "scheduler_thread.h" @@ -40,93 +41,6 @@ namespace Scheduler { -class SchedulerModeLocking { -public: - bool Lock(int* /* lockable */) - { - CPUEntry::GetCPU(smp_get_current_cpu())->EnterScheduler(); - return true; - } - - void Unlock(int* /* lockable */) - { - CPUEntry::GetCPU(smp_get_current_cpu())->ExitScheduler(); - } -}; - -class SchedulerModeLocker : - public AutoLocker<int, SchedulerModeLocking> { -public: - SchedulerModeLocker(bool alreadyLocked = false, bool lockIfNotLocked = true) - : - AutoLocker<int, SchedulerModeLocking>(NULL, alreadyLocked, - lockIfNotLocked) - { - } -}; - -class InterruptsSchedulerModeLocking { -public: - bool Lock(int* lockable) - { - *lockable = disable_interrupts(); - CPUEntry::GetCPU(smp_get_current_cpu())->EnterScheduler(); - return true; - } - - void Unlock(int* lockable) - { - CPUEntry::GetCPU(smp_get_current_cpu())->ExitScheduler(); - restore_interrupts(*lockable); - } -}; - -class InterruptsSchedulerModeLocker : - public AutoLocker<int, InterruptsSchedulerModeLocking> { -public: - InterruptsSchedulerModeLocker(bool alreadyLocked = false, - bool lockIfNotLocked = true) - : - AutoLocker<int, InterruptsSchedulerModeLocking>(&fState, alreadyLocked, - lockIfNotLocked) - { - } - -private: - int fState; -}; - -class InterruptsBigSchedulerLocking { -public: - bool Lock(int* lockable) - { - *lockable = disable_interrupts(); - for (int32 i = 0; i < smp_get_num_cpus(); i++) - CPUEntry::GetCPU(i)->LockScheduler(); - return true; - } - - void Unlock(int* lockable) - { - for (int32 i = 0; i < smp_get_num_cpus(); i++) - CPUEntry::GetCPU(i)->UnlockScheduler(); - restore_interrupts(*lockable); - } -}; - -class InterruptsBigSchedulerLocker : - public AutoLocker<int, InterruptsBigSchedulerLocking> { -public: - InterruptsBigSchedulerLocker() - : - AutoLocker<int, InterruptsBigSchedulerLocking>(&fState, false, true) - { - } - -private: - int fState; -}; - class ThreadEnqueuer : public ThreadProcessing { public: void operator()(ThreadData* thread); @@ -624,6 +538,8 @@ scheduler_on_thread_create(Thread* thread, bool idleThread) void scheduler_on_thread_init(Thread* thread) { + ASSERT(thread->scheduler_data != NULL); + if (thread_is_idle_thread(thread)) { static int32 sIdleThreadsID; int32 cpuID = atomic_add(&sIdleThreadsID, 1); diff --git a/src/system/kernel/scheduler/scheduler_cpu.cpp b/src/system/kernel/scheduler/scheduler_cpu.cpp index a88c041..7ec4ab5 100644 --- a/src/system/kernel/scheduler/scheduler_cpu.cpp +++ b/src/system/kernel/scheduler/scheduler_cpu.cpp @@ -392,14 +392,6 @@ CoreEntry::Remove(ThreadData* thread) } -inline ThreadData* -CoreEntry::PeekThread() const -{ - SCHEDULER_ENTER_FUNCTION(); - return fRunQueue.PeekMaximum(); -} - - void CoreEntry::UpdateLoad(int32 delta) { @@ -454,26 +446,6 @@ CoreEntry::UpdateLoad(int32 delta) } -inline void -CoreEntry::CPUGoesIdle(CPUEntry* /* cpu */) -{ - ASSERT(fCPUIdleCount < fCPUCount); - - if (++fCPUIdleCount == fCPUCount) - fPackage->CoreGoesIdle(this); -} - - -inline void -CoreEntry::CPUWakesUp(CPUEntry* /* cpu */) -{ - ASSERT(fCPUIdleCount > 0); - - if (fCPUIdleCount-- == fCPUCount) - fPackage->CoreWakesUp(this); -} - - void CoreEntry::AddCPU(CPUEntry* cpu) { @@ -599,48 +571,6 @@ PackageEntry::Init(int32 id) } -inline void -PackageEntry::CoreGoesIdle(CoreEntry* core) -{ - SCHEDULER_ENTER_FUNCTION(); - - WriteSpinLocker _(fCoreLock); - - ASSERT(fIdleCoreCount >= 0); - ASSERT(fIdleCoreCount < fCoreCount); - - fIdleCoreCount++; - fIdleCores.Add(core); - - if (fIdleCoreCount == fCoreCount) { - // package goes idle - WriteSpinLocker _(gIdlePackageLock); - gIdlePackageList.Add(this); - } -} - - -inline void -PackageEntry::CoreWakesUp(CoreEntry* core) -{ - SCHEDULER_ENTER_FUNCTION(); - - WriteSpinLocker _(fCoreLock); - - ASSERT(fIdleCoreCount > 0); - ASSERT(fIdleCoreCount <= fCoreCount); - - fIdleCoreCount--; - fIdleCores.Remove(core); - - if (fIdleCoreCount + 1 == fCoreCount) { - // package wakes up - WriteSpinLocker _(gIdlePackageLock); - gIdlePackageList.Remove(this); - } -} - - void PackageEntry::AddIdleCore(CoreEntry* core) { diff --git a/src/system/kernel/scheduler/scheduler_cpu.h b/src/system/kernel/scheduler/scheduler_cpu.h index c76ccf1..b62ee5f 100644 --- a/src/system/kernel/scheduler/scheduler_cpu.h +++ b/src/system/kernel/scheduler/scheduler_cpu.h @@ -85,7 +85,7 @@ public: static inline CPUEntry* GetCPU(int32 cpu); private: - inline void _RequestPerformanceLevel( + void _RequestPerformanceLevel( ThreadData* threadData); int32 fCPUNumber; @@ -112,21 +112,6 @@ public: void Dump(); }; -class CPURunQueueLocking { -public: - inline bool Lock(CPUEntry* cpu) - { - cpu->LockRunQueue(); - return true; - } - - inline void Unlock(CPUEntry* cpu) - { - cpu->UnlockRunQueue(); - } -}; - -typedef AutoLocker<CPUEntry, CPURunQueueLocking> CPURunQueueLocker; class CoreEntry : public MinMaxHeapLinkImpl<CoreEntry, int32>, public DoublyLinkedListLinkImpl<CoreEntry> { @@ -205,37 +190,6 @@ private: friend class DebugDumper; } CACHE_LINE_ALIGN; -class CoreRunQueueLocking { -public: - inline bool Lock(CoreEntry* core) - { - core->LockRunQueue(); - return true; - } - - inline void Unlock(CoreEntry* core) - { - core->UnlockRunQueue(); - } -}; - -typedef AutoLocker<CoreEntry, CoreRunQueueLocking> CoreRunQueueLocker; - -class CoreCPUHeapLocking { -public: - inline bool Lock(CoreEntry* core) - { - core->LockCPUHeap(); - return true; - } - - inline void Unlock(CoreEntry* core) - { - core->UnlockCPUHeap(); - } -}; - -typedef AutoLocker<CoreEntry, CoreCPUHeapLocking> CoreCPUHeapLocker; class CoreLoadHeap : public MinMaxHeap<CoreEntry, int32> { public: @@ -402,6 +356,14 @@ CoreEntry::IncreaseActiveTime(bigtime_t activeTime) } +inline ThreadData* +CoreEntry::PeekThread() const +{ + SCHEDULER_ENTER_FUNCTION(); + return fRunQueue.PeekMaximum(); +} + + inline bigtime_t CoreEntry::GetActiveTime() const { @@ -435,6 +397,73 @@ CoreEntry::StarvationCounter() const } +/* 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 + passes. +*/ +inline void +PackageEntry::CoreGoesIdle(CoreEntry* core) +{ + SCHEDULER_ENTER_FUNCTION(); + + WriteSpinLocker _(fCoreLock); + + ASSERT(fIdleCoreCount >= 0); + ASSERT(fIdleCoreCount < fCoreCount); + + fIdleCoreCount++; + fIdleCores.Add(core); + + if (fIdleCoreCount == fCoreCount) { + // package goes idle + WriteSpinLocker _(gIdlePackageLock); + gIdlePackageList.Add(this); + } +} + + +inline void +PackageEntry::CoreWakesUp(CoreEntry* core) +{ + SCHEDULER_ENTER_FUNCTION(); + + WriteSpinLocker _(fCoreLock); + + ASSERT(fIdleCoreCount > 0); + ASSERT(fIdleCoreCount <= fCoreCount); + + fIdleCoreCount--; + fIdleCores.Remove(core); + + if (fIdleCoreCount + 1 == fCoreCount) { + // package wakes up + WriteSpinLocker _(gIdlePackageLock); + gIdlePackageList.Remove(this); + } +} + + +inline void +CoreEntry::CPUGoesIdle(CPUEntry* /* cpu */) +{ + ASSERT(fCPUIdleCount < fCPUCount); + + if (++fCPUIdleCount == fCPUCount) + fPackage->CoreGoesIdle(this); +} + + +inline void +CoreEntry::CPUWakesUp(CPUEntry* /* cpu */) +{ + ASSERT(fCPUIdleCount > 0); + + if (fCPUIdleCount-- == fCPUCount) + fPackage->CoreWakesUp(this); +} + + /* static */ inline CoreEntry* CoreEntry::GetCore(int32 cpu) { diff --git a/src/system/kernel/scheduler/scheduler_locking.h b/src/system/kernel/scheduler/scheduler_locking.h new file mode 100644 index 0000000..044015c --- /dev/null +++ b/src/system/kernel/scheduler/scheduler_locking.h @@ -0,0 +1,158 @@ +/* + * Copyright 2014, Paweł Dziepak, pdziepak@xxxxxxxxxxx. + * Distributed under the terms of the MIT License. + */ +#ifndef KERNEL_SCHEDULER_LOCKING_H +#define KERNEL_SCHEDULER_LOCKING_H + + +#include <util/AutoLock.h> + +#include "scheduler_cpu.h" + + +namespace Scheduler { + + +class CPURunQueueLocking { +public: + inline bool Lock(CPUEntry* cpu) + { + cpu->LockRunQueue(); + return true; + } + + inline void Unlock(CPUEntry* cpu) + { + cpu->UnlockRunQueue(); + } +}; + +typedef AutoLocker<CPUEntry, CPURunQueueLocking> CPURunQueueLocker; + + +class CoreRunQueueLocking { +public: + inline bool Lock(CoreEntry* core) + { + core->LockRunQueue(); + return true; + } + + inline void Unlock(CoreEntry* core) + { + core->UnlockRunQueue(); + } +}; + +typedef AutoLocker<CoreEntry, CoreRunQueueLocking> CoreRunQueueLocker; + +class CoreCPUHeapLocking { +public: + inline bool Lock(CoreEntry* core) + { + core->LockCPUHeap(); + return true; + } + + inline void Unlock(CoreEntry* core) + { + core->UnlockCPUHeap(); + } +}; + +typedef AutoLocker<CoreEntry, CoreCPUHeapLocking> CoreCPUHeapLocker; + +class SchedulerModeLocking { +public: + bool Lock(int* /* lockable */) + { + CPUEntry::GetCPU(smp_get_current_cpu())->EnterScheduler(); + return true; + } + + void Unlock(int* /* lockable */) + { + CPUEntry::GetCPU(smp_get_current_cpu())->ExitScheduler(); + } +}; + +class SchedulerModeLocker : + public AutoLocker<int, SchedulerModeLocking> { +public: + SchedulerModeLocker(bool alreadyLocked = false, bool lockIfNotLocked = true) + : + AutoLocker<int, SchedulerModeLocking>(NULL, alreadyLocked, + lockIfNotLocked) + { + } +}; + +class InterruptsSchedulerModeLocking { +public: + bool Lock(int* lockable) + { + *lockable = disable_interrupts(); + CPUEntry::GetCPU(smp_get_current_cpu())->EnterScheduler(); + return true; + } + + void Unlock(int* lockable) + { + CPUEntry::GetCPU(smp_get_current_cpu())->ExitScheduler(); + restore_interrupts(*lockable); + } +}; + +class InterruptsSchedulerModeLocker : + public AutoLocker<int, InterruptsSchedulerModeLocking> { +public: + InterruptsSchedulerModeLocker(bool alreadyLocked = false, + bool lockIfNotLocked = true) + : + AutoLocker<int, InterruptsSchedulerModeLocking>(&fState, alreadyLocked, + lockIfNotLocked) + { + } + +private: + int fState; +}; + +class InterruptsBigSchedulerLocking { +public: + bool Lock(int* lockable) + { + *lockable = disable_interrupts(); + for (int32 i = 0; i < smp_get_num_cpus(); i++) + CPUEntry::GetCPU(i)->LockScheduler(); + return true; + } + + void Unlock(int* lockable) + { + for (int32 i = 0; i < smp_get_num_cpus(); i++) + CPUEntry::GetCPU(i)->UnlockScheduler(); + restore_interrupts(*lockable); + } +}; + +class InterruptsBigSchedulerLocker : + public AutoLocker<int, InterruptsBigSchedulerLocking> { +public: + InterruptsBigSchedulerLocker() + : + AutoLocker<int, InterruptsBigSchedulerLocking>(&fState, false, true) + { + } + +private: + int fState; +}; + + +} // namespace Scheduler + + +#endif // KERNEL_SCHEDULER_LOCKING_H + diff --git a/src/system/kernel/scheduler/scheduler_thread.cpp b/src/system/kernel/scheduler/scheduler_thread.cpp index ec84ee4..aef21a5 100644 --- a/src/system/kernel/scheduler/scheduler_thread.cpp +++ b/src/system/kernel/scheduler/scheduler_thread.cpp @@ -12,6 +12,58 @@ using namespace Scheduler; static bigtime_t sQuantumLengths[THREAD_MAX_SET_PRIORITY + 1]; +inline CoreEntry* +ThreadData::_ChooseCore() const +{ + SCHEDULER_ENTER_FUNCTION(); + + ASSERT(!gSingleCore); + return gCurrentMode->choose_core(this); +} + + +inline CPUEntry* +ThreadData::_ChooseCPU(CoreEntry* core, bool& rescheduleNeeded) const +{ + SCHEDULER_ENTER_FUNCTION(); + + int32 threadPriority = GetEffectivePriority(); + + if (fThread->previous_cpu != NULL) { + CPUEntry* previousCPU = &gCPUEntries[fThread->previous_cpu->cpu_num]; + if (previousCPU->Core() == core && !fThread->previous_cpu->disabled) { + CoreCPUHeapLocker _(core); + if (CPUPriorityHeap::GetKey(previousCPU) < threadPriority) { + previousCPU->UpdatePriority(threadPriority); + rescheduleNeeded = true; + return previousCPU; + } + } + } + + CoreCPUHeapLocker _(core); + CPUEntry* cpu = core->CPUHeap()->PeekRoot(); + ASSERT(cpu != NULL); + + if (CPUPriorityHeap::GetKey(cpu) < threadPriority) { + cpu->UpdatePriority(threadPriority); + rescheduleNeeded = true; + } else + rescheduleNeeded = false; + + return cpu; +} + + +inline bigtime_t +ThreadData::_GetBaseQuantum() const +{ + SCHEDULER_ENTER_FUNCTION(); + + return sQuantumLengths[GetEffectivePriority()]; +} + + ThreadData::ThreadData(Thread* thread) : fThread(thread) @@ -190,6 +242,21 @@ ThreadData::ComputeQuantumLengths() } +inline int32 +ThreadData::_GetPenalty() const +{ + SCHEDULER_ENTER_FUNCTION(); + + int32 penalty = fPriorityPenalty; + + const int kMinimalPriority = _GetMinimalPriority(); + if (kMinimalPriority > 0) + penalty += fAdditionalPenalty % kMinimalPriority; + + return penalty; +} + + void ThreadData::_ComputeEffectivePriority() const { @@ -209,58 +276,6 @@ ThreadData::_ComputeEffectivePriority() const } -inline CoreEntry* -ThreadData::_ChooseCore() const -{ - SCHEDULER_ENTER_FUNCTION(); - - ASSERT(!gSingleCore); - return gCurrentMode->choose_core(this); -} - - -inline CPUEntry* -ThreadData::_ChooseCPU(CoreEntry* core, bool& rescheduleNeeded) const -{ - SCHEDULER_ENTER_FUNCTION(); - - int32 threadPriority = GetEffectivePriority(); - - if (fThread->previous_cpu != NULL) { - CPUEntry* previousCPU = &gCPUEntries[fThread->previous_cpu->cpu_num]; - if (previousCPU->Core() == core && !fThread->previous_cpu->disabled) { - CoreCPUHeapLocker _(core); - if (CPUPriorityHeap::GetKey(previousCPU) < threadPriority) { - previousCPU->UpdatePriority(threadPriority); - rescheduleNeeded = true; - return previousCPU; - } - } - } - - CoreCPUHeapLocker _(core); - CPUEntry* cpu = core->CPUHeap()->PeekRoot(); - ASSERT(cpu != NULL); - - if (CPUPriorityHeap::GetKey(cpu) < threadPriority) { - cpu->UpdatePriority(threadPriority); - rescheduleNeeded = true; - } else - rescheduleNeeded = false; - - return cpu; -} - - -inline bigtime_t -ThreadData::_GetBaseQuantum() const -{ - SCHEDULER_ENTER_FUNCTION(); - - return sQuantumLengths[GetEffectivePriority()]; -} - - /* static */ bigtime_t ThreadData::_ScaleQuantum(bigtime_t maxQuantum, bigtime_t minQuantum, int32 maxPriority, int32 minPriority, int32 priority) diff --git a/src/system/kernel/scheduler/scheduler_thread.h b/src/system/kernel/scheduler/scheduler_thread.h index debcf2d..de932dd 100644 --- a/src/system/kernel/scheduler/scheduler_thread.h +++ b/src/system/kernel/scheduler/scheduler_thread.h @@ -11,6 +11,7 @@ #include "scheduler_common.h" #include "scheduler_cpu.h" +#include "scheduler_locking.h" #include "scheduler_profiler.h" @@ -19,6 +20,17 @@ namespace Scheduler { struct ThreadData : public DoublyLinkedListLinkImpl<ThreadData>, RunQueueLinkImpl<ThreadData> { +private: + inline void _InitBase(); + + inline int32 _GetMinimalPriority() const; + + inline CoreEntry* _ChooseCore() const; + inline CPUEntry* _ChooseCPU(CoreEntry* core, + bool& rescheduleNeeded) const; + + inline bigtime_t _GetBaseQuantum() const; + public: ThreadData(Thread* thread); @@ -72,17 +84,12 @@ public: inline void UnassignCore() { fCore = NULL; } static void ComputeQuantumLengths(); + private: inline int32 _GetPenalty() const; - inline int32 _GetMinimalPriority() const; void _ComputeEffectivePriority() const; - inline CoreEntry* _ChooseCore() const; - inline CPUEntry* _ChooseCPU(CoreEntry* core, - bool& rescheduleNeeded) const; - - inline bigtime_t _GetBaseQuantum() const; static bigtime_t _ScaleQuantum(bigtime_t maxQuantum, bigtime_t minQuantum, int32 maxPriority, int32 minPriority, int32 priority); @@ -121,6 +128,21 @@ public: }; +inline int32 +ThreadData::_GetMinimalPriority() const +{ + SCHEDULER_ENTER_FUNCTION(); + + const int32 kDivisor = 5; + + const int32 kMaximalPriority = 25; + const int32 kMinimalPriority = B_LOWEST_ACTIVE_PRIORITY; + + int32 priority = fThread->priority / kDivisor; + return std::max(std::min(priority, kMaximalPriority), kMinimalPriority); +} + + inline bool ThreadData::HasCacheExpired() const { @@ -259,6 +281,7 @@ ThreadData::Enqueue() SCHEDULER_ENTER_FUNCTION(); fThread->state = B_THREAD_READY; + ComputeLoad(); fWentSleepCount = 0; @@ -350,36 +373,6 @@ ThreadData::StartQuantum() } -inline int32 -ThreadData::_GetPenalty() const -{ - SCHEDULER_ENTER_FUNCTION(); - - int32 penalty = fPriorityPenalty; - - const int kMinimalPriority = _GetMinimalPriority(); - if (kMinimalPriority > 0) - penalty += fAdditionalPenalty % kMinimalPriority; - - return penalty; -} - - -inline int32 -ThreadData::_GetMinimalPriority() const -{ - SCHEDULER_ENTER_FUNCTION(); - - const int32 kDivisor = 5; - - const int32 kMaximalPriority = 25; - const int32 kMinimalPriority = B_LOWEST_ACTIVE_PRIORITY; - - int32 priority = fThread->priority / kDivisor; - return std::max(std::min(priority, kMaximalPriority), kMinimalPriority); -} - - } // namespace Scheduler ############################################################################ Commit: 7b55bf560cdf757d66223228bb13796a4e788c71 Author: Pawel Dziepak <pdziepak@xxxxxxxxxxx> Date: Mon Jan 6 00:18:37 2014 UTC scheduler: Improve thread creation performance ---------------------------------------------------------------------------- diff --git a/src/system/kernel/scheduler/scheduler.cpp b/src/system/kernel/scheduler/scheduler.cpp index 2916b5b..646c756 100644 --- a/src/system/kernel/scheduler/scheduler.cpp +++ b/src/system/kernel/scheduler/scheduler.cpp @@ -383,7 +383,7 @@ reschedule(int32 nextState) int32 thisCPU = smp_get_current_cpu(); - CPUEntry* cpu = &gCPUEntries[thisCPU]; + CPUEntry* cpu = CPUEntry::GetCPU(thisCPU); CoreEntry* core = CoreEntry::GetCore(thisCPU); TRACE("reschedule(): cpu %ld, current thread = %ld\n", thisCPU, diff --git a/src/system/kernel/scheduler/scheduler_cpu.cpp b/src/system/kernel/scheduler/scheduler_cpu.cpp index 7ec4ab5..771f1d7 100644 --- a/src/system/kernel/scheduler/scheduler_cpu.cpp +++ b/src/system/kernel/scheduler/scheduler_cpu.cpp @@ -124,6 +124,14 @@ CPUEntry::Remove(ThreadData* thread) inline ThreadData* +CoreEntry::PeekThread() const +{ + SCHEDULER_ENTER_FUNCTION(); + return fRunQueue.PeekMaximum(); +} + + +inline ThreadData* CPUEntry::PeekThread() const { SCHEDULER_ENTER_FUNCTION(); @@ -152,6 +160,9 @@ 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) @@ -164,6 +175,7 @@ CPUEntry::ComputeLoad() { SCHEDULER_ENTER_FUNCTION(); + ASSERT(gTrackLoad); ASSERT(fCPUNumber == smp_get_current_cpu()); int oldLoad = compute_load(fMeasureTime, fMeasureActiveTime, fLoad); @@ -244,10 +256,12 @@ CPUEntry::TrackActivity(ThreadData* oldThreadData, ThreadData* nextThreadData) oldThreadData->UpdateActivity(active); } - oldThreadData->ComputeLoad(); - nextThreadData->ComputeLoad(); - if (gTrackLoad && !cpuEntry->disabled) - ComputeLoad(); + if (gTrackLoad) { + oldThreadData->ComputeLoad(); + nextThreadData->ComputeLoad(); + if (!cpuEntry->disabled) + ComputeLoad(); + } Thread* nextThread = nextThreadData->GetThread(); if (!thread_is_idle_thread(nextThread)) { @@ -256,19 +270,17 @@ CPUEntry::TrackActivity(ThreadData* oldThreadData, ThreadData* nextThreadData) nextThreadData->SetLastInterruptTime(cpuEntry->interrupt_time); + if (gCPUFrequencyManagement) _RequestPerformanceLevel(nextThreadData); } } -inline void +void CPUEntry::_RequestPerformanceLevel(ThreadData* threadData) { SCHEDULER_ENTER_FUNCTION(); - if (!gCPUFrequencyManagement) - return; - if (gCPU[fCPUNumber].disabled) { decrease_cpu_performance(kCPUPerformanceScaleMax); return; diff --git a/src/system/kernel/scheduler/scheduler_cpu.h b/src/system/kernel/scheduler/scheduler_cpu.h index b62ee5f..1def98d 100644 --- a/src/system/kernel/scheduler/scheduler_cpu.h +++ b/src/system/kernel/scheduler/scheduler_cpu.h @@ -112,7 +112,6 @@ public: void Dump(); }; - class CoreEntry : public MinMaxHeapLinkImpl<CoreEntry, int32>, public DoublyLinkedListLinkImpl<CoreEntry> { public: @@ -190,7 +189,6 @@ private: friend class DebugDumper; } CACHE_LINE_ALIGN; - class CoreLoadHeap : public MinMaxHeap<CoreEntry, int32> { public: CoreLoadHeap() { } @@ -356,14 +354,6 @@ CoreEntry::IncreaseActiveTime(bigtime_t activeTime) } -inline ThreadData* -CoreEntry::PeekThread() const -{ - SCHEDULER_ENTER_FUNCTION(); - return fRunQueue.PeekMaximum(); -} - - inline bigtime_t CoreEntry::GetActiveTime() const { diff --git a/src/system/kernel/scheduler/scheduler_thread.cpp b/src/system/kernel/scheduler/scheduler_thread.cpp index aef21a5..6f9c818 100644 --- a/src/system/kernel/scheduler/scheduler_thread.cpp +++ b/src/system/kernel/scheduler/scheduler_thread.cpp @@ -12,6 +12,28 @@ using namespace Scheduler; static bigtime_t sQuantumLengths[THREAD_MAX_SET_PRIORITY + 1]; +void +ThreadData::_InitBase() +{ + fPriorityPenalty = 0; + fAdditionalPenalty = 0; + fEffectivePriority = fThread->priority; + + fTimeLeft = 0; + fStolenTime = 0; + + fMeasureActiveTime = 0; + fMeasureTime = 0; + fLoad = 0; + + fWentSleep = 0; + fWentSleepActive = 0; + fWentSleepCount = -1; + + fEnqueued = false; +} + + inline CoreEntry* ThreadData::_ChooseCore() const { @@ -30,7 +52,8 @@ ThreadData::_ChooseCPU(CoreEntry* core, bool& rescheduleNeeded) const int32 threadPriority = GetEffectivePriority(); if (fThread->previous_cpu != NULL) { - CPUEntry* previousCPU = &gCPUEntries[fThread->previous_cpu->cpu_num]; + CPUEntry* previousCPU + = CPUEntry::GetCPU(fThread->previous_cpu->cpu_num); if (previousCPU->Core() == core && !fThread->previous_cpu->disabled) { CoreCPUHeapLocker _(core); if (CPUPriorityHeap::GetKey(previousCPU) < threadPriority) { @@ -74,48 +97,18 @@ ThreadData::ThreadData(Thread* thread) void ThreadData::Init() { - fAdditionalPenalty = 0; - fEffectivePriority = -1; - - fTimeLeft = 0; - fStolenTime = 0; - - fMeasureActiveTime = 0; - fMeasureTime = 0; - fLoad = 0; + _InitBase(); - fWentSleep = 0; - fWentSleepActive = 0; - fWentSleepCount = -1; - - fEnqueued = false; - - Thread* currentThread = thread_get_current_thread(); - ASSERT(currentThread != NULL); - if (!thread_is_idle_thread(currentThread)) { - ThreadData* currentThreadData = currentThread->scheduler_data; - int32 penalty = currentThreadData->fPriorityPenalty; - - int32 minimalPriority = _GetMinimalPriority(); - if (fThread->priority - penalty >= minimalPriority) - fPriorityPenalty = penalty; - else - fPriorityPenalty = fThread->priority - minimalPriority; - - fCore = currentThreadData->fCore; - } else { - fPriorityPenalty = 0; - fAdditionalPenalty = 0; - - fCore = NULL; - } + ThreadData* currentThreadData = thread_get_current_thread()->scheduler_data; + fCore = currentThreadData->fCore; } void ThreadData::Init(CoreEntry* core) { - Init(); + _InitBase(); + fCore = core; } @@ -172,8 +165,7 @@ ThreadData::ComputeLoad() { SCHEDULER_ENTER_FUNCTION(); - if (!gTrackLoad) - return; + ASSERT(gTrackLoad); if (fLastInterruptTime > 0) { bigtime_t interruptTime = gCPU[smp_get_current_cpu()].interrupt_time; diff --git a/src/system/kernel/scheduler/scheduler_thread.h b/src/system/kernel/scheduler/scheduler_thread.h index de932dd..8d9cbdd 100644 --- a/src/system/kernel/scheduler/scheduler_thread.h +++ b/src/system/kernel/scheduler/scheduler_thread.h @@ -165,9 +165,6 @@ inline int32 ThreadData::GetEffectivePriority() const { SCHEDULER_ENTER_FUNCTION(); - - if (fEffectivePriority == -1) - _ComputeEffectivePriority(); return fEffectivePriority; } @@ -184,7 +181,6 @@ ThreadData::IncreasePenalty() TRACE("increasing thread %ld penalty\n", fThread->id); - fEffectivePriority = -1; int32 oldPenalty = fPriorityPenalty++; ASSERT(fThread->priority - oldPenalty >= B_LOWEST_ACTIVE_PRIORITY); @@ -194,6 +190,8 @@ ThreadData::IncreasePenalty() fPriorityPenalty = oldPenalty; fAdditionalPenalty++; } + + _ComputeEffectivePriority(); } @@ -202,13 +200,15 @@ ThreadData::CancelPenalty() { SCHEDULER_ENTER_FUNCTION(); - if (fPriorityPenalty != 0) { - TRACE("cancelling thread %ld penalty\n", fThread->id); - fEffectivePriority = -1; - } + int32 oldPenalty = fPriorityPenalty; fAdditionalPenalty = 0; fPriorityPenalty = 0; + + if (oldPenalty != 0) { + TRACE("cancelling thread %ld penalty\n", fThread->id); + _ComputeEffectivePriority(); + } } @@ -217,7 +217,7 @@ ThreadData::ShouldCancelPenalty() const { SCHEDULER_ENTER_FUNCTION(); - if (fCore == NULL || fWentSleep == 0) + if (fCore == NULL) return false; return fCore->StarvationCounter() != fWentSleepCount @@ -251,7 +251,8 @@ ThreadData::PutBack() { SCHEDULER_ENTER_FUNCTION(); - ComputeLoad(); + if (gTrackLoad) + ComputeLoad(); fWentSleepCount = -1; int32 priority = GetEffectivePriority(); @@ -282,7 +283,8 @@ ThreadData::Enqueue() fThread->state = B_THREAD_READY; - ComputeLoad(); + if (gTrackLoad) + ComputeLoad(); fWentSleepCount = 0; int32 priority = GetEffectivePriority();