[haiku-commits] BRANCH pdziepak-github.scheduler [f72fc8f] src/system/kernel/scheduler

  • From: pdziepak-github.scheduler <community@xxxxxxxxxxxx>
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Sat, 28 Dec 2013 22:15:32 +0100 (CET)

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) {


Other related posts: