added 5 changesets to branch 'refs/remotes/pdziepak-github/scheduler' old head: 50e4f3f6a5fcaf207ce0331d04230ecc0258beaa new head: f72fc8fe8b6e172b5c2a9ee4eaee78efc9302ce6 overview: https://github.com/pdziepak/Haiku/compare/50e4f3f...f72fc8f ---------------------------------------------------------------------------- 40a5c85: scheduler: Ignore time used by the profiler implementation 61ecda1: scheduler: Fix double release of run queue lock e3d1e86: scheduler: Profile RunQueue implementation 098bc0e: scheduler: profiler: Use nanosecond as a main time unit f72fc8f: scheduler: Use single ended heap for CPU heap [ Pawel Dziepak <pdziepak@xxxxxxxxxxx> ] ---------------------------------------------------------------------------- 9 files changed, 90 insertions(+), 39 deletions(-) src/system/kernel/scheduler/RunQueue.h | 12 ++++ src/system/kernel/scheduler/low_latency.cpp | 2 +- src/system/kernel/scheduler/power_saving.cpp | 4 +- src/system/kernel/scheduler/scheduler_cpu.cpp | 68 +++++++++++++------- src/system/kernel/scheduler/scheduler_cpu.h | 9 ++- .../kernel/scheduler/scheduler_profiler.cpp | 26 ++++++-- src/system/kernel/scheduler/scheduler_profiler.h | 5 +- src/system/kernel/scheduler/scheduler_thread.cpp | 2 +- src/system/kernel/scheduler/scheduler_thread.h | 1 - ############################################################################ Commit: 40a5c857b1c2dc25c3b6533c013ba3897afba9ed Author: Pawel Dziepak <pdziepak@xxxxxxxxxxx> Date: Sat Dec 28 17:55:39 2013 UTC scheduler: Ignore time used by the profiler implementation ---------------------------------------------------------------------------- diff --git a/src/system/kernel/scheduler/scheduler_profiler.cpp b/src/system/kernel/scheduler/scheduler_profiler.cpp index e0746c1..64759f5 100644 --- a/src/system/kernel/scheduler/scheduler_profiler.cpp +++ b/src/system/kernel/scheduler/scheduler_profiler.cpp @@ -55,6 +55,8 @@ Profiler::Profiler() void Profiler::EnterFunction(int32 cpu, const char* functionName) { + bigtime_t start = system_time(); + FunctionData* function = _FindFunction(functionName); if (function == NULL) return; @@ -67,27 +69,39 @@ Profiler::EnterFunction(int32 cpu, const char* functionName) ASSERT(fFunctionStackPointers[cpu] < kMaxFunctionStackEntries); stackEntry->fFunction = function; - stackEntry->fEntryTime = system_time(); + stackEntry->fEntryTime = start; stackEntry->fOthersTime = 0; + + bigtime_t stop = system_time(); + stackEntry->fProfilerTime = stop - start; } void Profiler::ExitFunction(int32 cpu, const char* functionName) { + bigtime_t start = system_time(); + ASSERT(fFunctionStackPointers[cpu] > 0); fFunctionStackPointers[cpu]--; FunctionEntry* stackEntry = &fFunctionStacks[cpu][fFunctionStackPointers[cpu]]; - bigtime_t timeSpent = system_time() - stackEntry->fEntryTime; + bigtime_t timeSpent = start - stackEntry->fEntryTime; + timeSpent -= stackEntry->fProfilerTime; + atomic_add64(&stackEntry->fFunction->fTimeInclusive, timeSpent); atomic_add64(&stackEntry->fFunction->fTimeExclusive, timeSpent - stackEntry->fOthersTime); + bigtime_t profilerTime = stackEntry->fProfilerTime; if (fFunctionStackPointers[cpu] > 0) { stackEntry = &fFunctionStacks[cpu][fFunctionStackPointers[cpu] - 1]; stackEntry->fOthersTime += timeSpent; + stackEntry->fProfilerTime += profilerTime; + + bigtime_t stop = system_time(); + stackEntry->fProfilerTime += stop - start; } } diff --git a/src/system/kernel/scheduler/scheduler_profiler.h b/src/system/kernel/scheduler/scheduler_profiler.h index fb87c16..2b99982 100644 --- a/src/system/kernel/scheduler/scheduler_profiler.h +++ b/src/system/kernel/scheduler/scheduler_profiler.h @@ -57,6 +57,7 @@ private: bigtime_t fEntryTime; bigtime_t fOthersTime; + bigtime_t fProfilerTime; }; uint32 _FunctionCount() const; ############################################################################ Commit: 61ecda1dd391fbddda537fd4a4cce981132142ac Author: Pawel Dziepak <pdziepak@xxxxxxxxxxx> Date: Sat Dec 28 19:11:30 2013 UTC scheduler: Fix double release of run queue lock ---------------------------------------------------------------------------- diff --git a/src/system/kernel/scheduler/scheduler_thread.h b/src/system/kernel/scheduler/scheduler_thread.h index 38434e4..7bea75b 100644 --- a/src/system/kernel/scheduler/scheduler_thread.h +++ b/src/system/kernel/scheduler/scheduler_thread.h @@ -244,7 +244,6 @@ ThreadData::PutBack() cpu->PushFront(this, priority); } else fCore->PushFront(this, priority); - fCore->UnlockRunQueue(); } ############################################################################ Commit: e3d1e865b3a09df3b6e7104b659ba0d598c08c97 Author: Pawel Dziepak <pdziepak@xxxxxxxxxxx> Date: Sat Dec 28 19:39:42 2013 UTC scheduler: Profile RunQueue implementation ---------------------------------------------------------------------------- diff --git a/src/system/kernel/scheduler/RunQueue.h b/src/system/kernel/scheduler/RunQueue.h index b0ee6ca..6ad9fc4 100644 --- a/src/system/kernel/scheduler/RunQueue.h +++ b/src/system/kernel/scheduler/RunQueue.h @@ -11,6 +11,8 @@ #include <util/Bitmap.h> +#include "scheduler_profiler.h" + template<typename Element> struct RunQueueLink { @@ -245,6 +247,8 @@ RUN_QUEUE_TEMPLATE_LIST Element* RUN_QUEUE_CLASS_NAME::PeekMaximum() const { + SCHEDULER_ENTER_FUNCTION(); + int priority = fBitmap.GetHighestSet(); if (priority < 0) return NULL; @@ -268,6 +272,8 @@ void RUN_QUEUE_CLASS_NAME::PushFront(Element* element, unsigned int priority) { + SCHEDULER_ENTER_FUNCTION(); + ASSERT(priority <= MaxPriority); RunQueueLink<Element>* elementLink = sGetLink(element); @@ -295,6 +301,8 @@ void RUN_QUEUE_CLASS_NAME::PushBack(Element* element, unsigned int priority) { + SCHEDULER_ENTER_FUNCTION(); + ASSERT(priority <= MaxPriority); RunQueueLink<Element>* elementLink = sGetLink(element); @@ -321,6 +329,8 @@ RUN_QUEUE_TEMPLATE_LIST void RUN_QUEUE_CLASS_NAME::Remove(Element* element) { + SCHEDULER_ENTER_FUNCTION(); + RunQueueLink<Element>* elementLink = sGetLink(element); unsigned int priority = elementLink->fPriority; @@ -351,6 +361,8 @@ RUN_QUEUE_TEMPLATE_LIST Element* RUN_QUEUE_CLASS_NAME::GetHead(unsigned int priority) const { + SCHEDULER_ENTER_FUNCTION(); + ASSERT(priority <= MaxPriority); return fHeads[priority]; } ############################################################################ Commit: 098bc0e680cd857dcc24ee69b2e50794f1a83514 Author: Pawel Dziepak <pdziepak@xxxxxxxxxxx> Date: Sat Dec 28 20:03:43 2013 UTC scheduler: profiler: Use nanosecond as a main time unit ---------------------------------------------------------------------------- diff --git a/src/system/kernel/scheduler/scheduler_profiler.cpp b/src/system/kernel/scheduler/scheduler_profiler.cpp index 64759f5..12a2042 100644 --- a/src/system/kernel/scheduler/scheduler_profiler.cpp +++ b/src/system/kernel/scheduler/scheduler_profiler.cpp @@ -55,7 +55,7 @@ Profiler::Profiler() void Profiler::EnterFunction(int32 cpu, const char* functionName) { - bigtime_t start = system_time(); + nanotime_t start = system_time_nsecs(); FunctionData* function = _FindFunction(functionName); if (function == NULL) @@ -72,7 +72,7 @@ Profiler::EnterFunction(int32 cpu, const char* functionName) stackEntry->fEntryTime = start; stackEntry->fOthersTime = 0; - bigtime_t stop = system_time(); + nanotime_t stop = system_time_nsecs(); stackEntry->fProfilerTime = stop - start; } @@ -80,27 +80,27 @@ Profiler::EnterFunction(int32 cpu, const char* functionName) void Profiler::ExitFunction(int32 cpu, const char* functionName) { - bigtime_t start = system_time(); + nanotime_t start = system_time_nsecs(); ASSERT(fFunctionStackPointers[cpu] > 0); fFunctionStackPointers[cpu]--; FunctionEntry* stackEntry = &fFunctionStacks[cpu][fFunctionStackPointers[cpu]]; - bigtime_t timeSpent = start - stackEntry->fEntryTime; + nanotime_t timeSpent = start - stackEntry->fEntryTime; timeSpent -= stackEntry->fProfilerTime; atomic_add64(&stackEntry->fFunction->fTimeInclusive, timeSpent); atomic_add64(&stackEntry->fFunction->fTimeExclusive, timeSpent - stackEntry->fOthersTime); - bigtime_t profilerTime = stackEntry->fProfilerTime; + nanotime_t profilerTime = stackEntry->fProfilerTime; if (fFunctionStackPointers[cpu] > 0) { stackEntry = &fFunctionStacks[cpu][fFunctionStackPointers[cpu] - 1]; stackEntry->fOthersTime += timeSpent; stackEntry->fProfilerTime += profilerTime; - bigtime_t stop = system_time(); + nanotime_t stop = system_time_nsecs(); stackEntry->fProfilerTime += stop - start; } } @@ -126,7 +126,7 @@ Profiler::DumpTimeInclusive(uint32 maxCount) uint32 count = _FunctionCount(); qsort(fFunctionData, count, sizeof(FunctionData), - &_CompareFunctions<bigtime_t, &FunctionData::fTimeInclusive>); + &_CompareFunctions<nanotime_t, &FunctionData::fTimeInclusive>); if (maxCount > 0) count = std::min(count, maxCount); @@ -140,7 +140,7 @@ Profiler::DumpTimeExclusive(uint32 maxCount) uint32 count = _FunctionCount(); qsort(fFunctionData, count, sizeof(FunctionData), - &_CompareFunctions<bigtime_t, &FunctionData::fTimeExclusive>); + &_CompareFunctions<nanotime_t, &FunctionData::fTimeExclusive>); if (maxCount > 0) count = std::min(count, maxCount); @@ -154,7 +154,7 @@ Profiler::DumpTimeInclusivePerCall(uint32 maxCount) uint32 count = _FunctionCount(); qsort(fFunctionData, count, sizeof(FunctionData), - &_CompareFunctionsPerCall<bigtime_t, &FunctionData::fTimeInclusive>); + &_CompareFunctionsPerCall<nanotime_t, &FunctionData::fTimeInclusive>); if (maxCount > 0) count = std::min(count, maxCount); @@ -168,7 +168,7 @@ Profiler::DumpTimeExclusivePerCall(uint32 maxCount) uint32 count = _FunctionCount(); qsort(fFunctionData, count, sizeof(FunctionData), - &_CompareFunctionsPerCall<bigtime_t, &FunctionData::fTimeExclusive>); + &_CompareFunctionsPerCall<nanotime_t, &FunctionData::fTimeExclusive>); if (maxCount > 0) count = std::min(count, maxCount); diff --git a/src/system/kernel/scheduler/scheduler_profiler.h b/src/system/kernel/scheduler/scheduler_profiler.h index 2b99982..d2c1bfc 100644 --- a/src/system/kernel/scheduler/scheduler_profiler.h +++ b/src/system/kernel/scheduler/scheduler_profiler.h @@ -55,9 +55,9 @@ private: struct FunctionEntry { FunctionData* fFunction; - bigtime_t fEntryTime; - bigtime_t fOthersTime; - bigtime_t fProfilerTime; + nanotime_t fEntryTime; + nanotime_t fOthersTime; + nanotime_t fProfilerTime; }; uint32 _FunctionCount() const; ############################################################################ Commit: f72fc8fe8b6e172b5c2a9ee4eaee78efc9302ce6 Author: Pawel Dziepak <pdziepak@xxxxxxxxxxx> Date: Sat Dec 28 20:47:35 2013 UTC scheduler: Use single ended heap for CPU heap ---------------------------------------------------------------------------- diff --git a/src/system/kernel/scheduler/low_latency.cpp b/src/system/kernel/scheduler/low_latency.cpp index f76673b..1e0c79d 100644 --- a/src/system/kernel/scheduler/low_latency.cpp +++ b/src/system/kernel/scheduler/low_latency.cpp @@ -138,7 +138,7 @@ rebalance_irqs(bool idle) other = gCoreHighLoadHeap.PeekMinimum(); coreLocker.Unlock(); - int32 newCPU = other->CPUHeap()->PeekMinimum()->ID(); + int32 newCPU = other->CPUHeap()->PeekRoot()->ID(); ASSERT(other != NULL); diff --git a/src/system/kernel/scheduler/power_saving.cpp b/src/system/kernel/scheduler/power_saving.cpp index c1da765..4239fd1 100644 --- a/src/system/kernel/scheduler/power_saving.cpp +++ b/src/system/kernel/scheduler/power_saving.cpp @@ -174,7 +174,7 @@ pack_irqs() irq_assignment* irq = (irq_assignment*)list_get_first_item(&cpu->irqs); locker.Unlock(); - int32 newCPU = smallTaskCore->CPUHeap()->PeekMinimum()->ID(); + int32 newCPU = smallTaskCore->CPUHeap()->PeekRoot()->ID(); if (newCPU != cpu->cpu_num) assign_io_interrupt_to_cpu(irq->irq, newCPU); @@ -219,7 +219,7 @@ rebalance_irqs(bool idle) coreLocker.Unlock(); if (other == NULL) return; - int32 newCPU = other->CPUHeap()->PeekMinimum()->ID(); + int32 newCPU = other->CPUHeap()->PeekRoot()->ID(); CoreEntry* core = CoreEntry::GetCore(smp_get_current_cpu()); if (other == core) diff --git a/src/system/kernel/scheduler/scheduler_cpu.cpp b/src/system/kernel/scheduler/scheduler_cpu.cpp index ef6c9bc..753f9b3 100644 --- a/src/system/kernel/scheduler/scheduler_cpu.cpp +++ b/src/system/kernel/scheduler/scheduler_cpu.cpp @@ -146,22 +146,15 @@ CPUEntry::UpdatePriority(int32 priority) if (gCPU[fCPUNumber].disabled) return; - CPUPriorityHeap* cpuHeap = fCore->CPUHeap(); - int32 corePriority = CPUPriorityHeap::GetKey(cpuHeap->PeekMaximum()); - cpuHeap->ModifyKey(this, priority); - - if (gSingleCore) - return; - - int32 maxPriority = CPUPriorityHeap::GetKey(cpuHeap->PeekMaximum()); - if (corePriority == maxPriority) + int32 oldPriority = CPUPriorityHeap::GetKey(this); + if (oldPriority == priority) return; + fCore->CPUHeap()->ModifyKey(this, priority); - PackageEntry* packageEntry = fCore->Package(); - if (maxPriority == B_IDLE_PRIORITY) - packageEntry->CoreGoesIdle(fCore); - else if (corePriority == B_IDLE_PRIORITY) - packageEntry->CoreWakesUp(fCore); + if (oldPriority == B_IDLE_PRIORITY) + fCore->CPUWakesUp(this); + else if (priority == B_IDLE_PRIORITY) + fCore->CPUGoesIdle(this); } @@ -292,7 +285,7 @@ CPUEntry::_RequestPerformanceLevel(ThreadData* threadData) CPUPriorityHeap::CPUPriorityHeap(int32 cpuCount) : - MinMaxHeap<CPUEntry, int32>(cpuCount) + Heap<CPUEntry, int32>(cpuCount) { } @@ -301,25 +294,25 @@ void CPUPriorityHeap::Dump() { kprintf("cpu priority load\n"); - CPUEntry* entry = PeekMinimum(); + CPUEntry* entry = PeekRoot(); while (entry) { int32 cpu = entry->ID(); int32 key = GetKey(entry); kprintf("%3" B_PRId32 " %8" B_PRId32 " %3" B_PRId32 "%%\n", cpu, key, entry->GetLoad() / 10); - RemoveMinimum(); + RemoveRoot(); sDebugCPUHeap.Insert(entry, key); - entry = PeekMinimum(); + entry = PeekRoot(); } - entry = sDebugCPUHeap.PeekMinimum(); + entry = sDebugCPUHeap.PeekRoot(); while (entry) { int32 key = GetKey(entry); - sDebugCPUHeap.RemoveMinimum(); + sDebugCPUHeap.RemoveRoot(); Insert(entry, key); - entry = sDebugCPUHeap.PeekMinimum(); + entry = sDebugCPUHeap.PeekRoot(); } } @@ -327,6 +320,7 @@ CPUPriorityHeap::Dump() CoreEntry::CoreEntry() : fCPUCount(0), + fCPUIdleCount(0), fStarvationCounter(0), fThreadCount(0), fActiveTime(0), @@ -449,10 +443,33 @@ 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) { ASSERT(fCPUCount >= 0); + ASSERT(fCPUIdleCount >= 0); + + fCPUIdleCount++; if (fCPUCount++ == 0) { // core has been reenabled fLoad = 0; @@ -470,6 +487,9 @@ void CoreEntry::RemoveCPU(CPUEntry* cpu, ThreadProcessing& threadPostProcessing) { ASSERT(fCPUCount > 0); + ASSERT(fCPUIdleCount > 0); + + fCPUIdleCount--; if (--fCPUCount == 0) { // core has been disabled if (fHighLoad) { @@ -499,9 +519,9 @@ CoreEntry::RemoveCPU(CPUEntry* cpu, ThreadProcessing& threadPostProcessing) fThreadCount = 0; } - fCPUHeap.ModifyKey(cpu, THREAD_MAX_SET_PRIORITY + 1); - ASSERT(fCPUHeap.PeekMaximum() == cpu); - fCPUHeap.RemoveMaximum(); + fCPUHeap.ModifyKey(cpu, -1); + ASSERT(fCPUHeap.PeekRoot() == cpu); + fCPUHeap.RemoveRoot(); ASSERT(cpu->GetLoad() >= 0 && cpu->GetLoad() <= kMaxLoad); fLoad -= cpu->GetLoad(); diff --git a/src/system/kernel/scheduler/scheduler_cpu.h b/src/system/kernel/scheduler/scheduler_cpu.h index 9115f67..2ea2774 100644 --- a/src/system/kernel/scheduler/scheduler_cpu.h +++ b/src/system/kernel/scheduler/scheduler_cpu.h @@ -11,6 +11,7 @@ #include <thread.h> #include <util/AutoLock.h> #include <util/MinMaxHeap.h> +#include <util/Heap.h> #include <cpufreq.h> @@ -41,7 +42,7 @@ public: void Dump() const; }; -class CPUEntry : public MinMaxHeapLinkImpl<CPUEntry, int32> { +class CPUEntry : public HeapLinkImpl<CPUEntry, int32> { public: CPUEntry(); @@ -99,7 +100,7 @@ private: friend class DebugDumper; } CACHE_LINE_ALIGN; -class CPUPriorityHeap : public MinMaxHeap<CPUEntry, int32> { +class CPUPriorityHeap : public Heap<CPUEntry, int32> { public: CPUPriorityHeap() { } CPUPriorityHeap(int32 cpuCount); @@ -146,6 +147,9 @@ public: inline int32 StarvationCounter() const; + inline void CPUGoesIdle(CPUEntry* cpu); + inline void CPUWakesUp(CPUEntry* cpu); + void AddCPU(CPUEntry* cpu); void RemoveCPU(CPUEntry* cpu, ThreadProcessing& @@ -161,6 +165,7 @@ private: PackageEntry* fPackage; int32 fCPUCount; + int32 fCPUIdleCount; CPUPriorityHeap fCPUHeap; spinlock fCPULock; diff --git a/src/system/kernel/scheduler/scheduler_thread.cpp b/src/system/kernel/scheduler/scheduler_thread.cpp index de6a64b..4db6516 100644 --- a/src/system/kernel/scheduler/scheduler_thread.cpp +++ b/src/system/kernel/scheduler/scheduler_thread.cpp @@ -205,7 +205,7 @@ ThreadData::_ChooseCPU(CoreEntry* core, bool& rescheduleNeeded) const } CoreCPUHeapLocker _(core); - CPUEntry* cpu = core->CPUHeap()->PeekMinimum(); + CPUEntry* cpu = core->CPUHeap()->PeekRoot(); ASSERT(cpu != NULL); if (CPUPriorityHeap::GetKey(cpu) < threadPriority) {