scheduler: Add scheduler profiler

A bit hackish implementation of a profiler for the scheduler.
SCHEDULER_ENTER_FUNCTION at the begining of each function aren't nice and
usage of __PRETTY_FUNCTION__ isn't any better (both gcc and clang support
it though), but it was quick to implement and doesn't lose information
on inlined functions. It's just a tool, not an integral part of the kernal
anyway.
This commit is contained in:
Pawel Dziepak
2013-12-26 19:40:50 +01:00
parent ebe5420f84
commit 96dcc73b39
10 changed files with 580 additions and 19 deletions
+1
View File
@@ -66,6 +66,7 @@ KernelMergeObject kernel_core.o :
power_saving.cpp power_saving.cpp
scheduler.cpp scheduler.cpp
scheduler_cpu.cpp scheduler_cpu.cpp
scheduler_profiler.cpp
scheduler_thread.cpp scheduler_thread.cpp
scheduler_tracing.cpp scheduler_tracing.cpp
scheduling_analysis.cpp scheduling_analysis.cpp
+8 -2
View File
@@ -9,6 +9,7 @@
#include "scheduler_common.h" #include "scheduler_common.h"
#include "scheduler_cpu.h" #include "scheduler_cpu.h"
#include "scheduler_modes.h" #include "scheduler_modes.h"
#include "scheduler_profiler.h"
#include "scheduler_thread.h" #include "scheduler_thread.h"
@@ -33,10 +34,9 @@ set_cpu_enabled(int32 /* cpu */, bool /* enabled */)
static bool static bool
has_cache_expired(const ThreadData* threadData) has_cache_expired(const ThreadData* threadData)
{ {
ASSERT(!gSingleCore); SCHEDULER_ENTER_FUNCTION();
CoreEntry* core = threadData->Core(); CoreEntry* core = threadData->Core();
bigtime_t activeTime = core->GetActiveTime(); bigtime_t activeTime = core->GetActiveTime();
return activeTime - threadData->WentSleepActive() > kCacheExpire; return activeTime - threadData->WentSleepActive() > kCacheExpire;
} }
@@ -45,6 +45,8 @@ has_cache_expired(const ThreadData* threadData)
static CoreEntry* static CoreEntry*
choose_core(const ThreadData* /* threadData */) choose_core(const ThreadData* /* threadData */)
{ {
SCHEDULER_ENTER_FUNCTION();
// wake new package // wake new package
PackageEntry* package = gIdlePackageList.Last(); PackageEntry* package = gIdlePackageList.Last();
if (package == NULL) { if (package == NULL) {
@@ -72,6 +74,8 @@ choose_core(const ThreadData* /* threadData */)
static bool static bool
should_rebalance(const ThreadData* threadData) should_rebalance(const ThreadData* threadData)
{ {
SCHEDULER_ENTER_FUNCTION();
int32 coreLoad = threadData->Core()->GetLoad(); int32 coreLoad = threadData->Core()->GetLoad();
// If the thread produces more than 50% of the load, leave it here. In // If the thread produces more than 50% of the load, leave it here. In
@@ -104,6 +108,8 @@ should_rebalance(const ThreadData* threadData)
static void static void
rebalance_irqs(bool idle) rebalance_irqs(bool idle)
{ {
SCHEDULER_ENTER_FUNCTION();
if (idle) if (idle)
return; return;
+14 -2
View File
@@ -10,6 +10,7 @@
#include "scheduler_common.h" #include "scheduler_common.h"
#include "scheduler_cpu.h" #include "scheduler_cpu.h"
#include "scheduler_modes.h" #include "scheduler_modes.h"
#include "scheduler_profiler.h"
#include "scheduler_thread.h" #include "scheduler_thread.h"
@@ -39,8 +40,7 @@ set_cpu_enabled(int32 cpu, bool enabled)
static bool static bool
has_cache_expired(const ThreadData* threadData) has_cache_expired(const ThreadData* threadData)
{ {
ASSERT(!gSingleCore); SCHEDULER_ENTER_FUNCTION();
return system_time() - threadData->WentSleep() > kCacheExpire; return system_time() - threadData->WentSleep() > kCacheExpire;
} }
@@ -48,6 +48,8 @@ has_cache_expired(const ThreadData* threadData)
static CoreEntry* static CoreEntry*
choose_small_task_core() choose_small_task_core()
{ {
SCHEDULER_ENTER_FUNCTION();
ReadSpinLocker locker(gCoreHeapsLock); ReadSpinLocker locker(gCoreHeapsLock);
CoreEntry* core = gCoreLoadHeap.PeekMaximum(); CoreEntry* core = gCoreLoadHeap.PeekMaximum();
locker.Unlock(); locker.Unlock();
@@ -66,6 +68,8 @@ choose_small_task_core()
static CoreEntry* static CoreEntry*
choose_idle_core() choose_idle_core()
{ {
SCHEDULER_ENTER_FUNCTION();
PackageEntry* package = PackageEntry::GetLeastIdlePackage(); PackageEntry* package = PackageEntry::GetLeastIdlePackage();
if (package == NULL) if (package == NULL)
@@ -81,6 +85,8 @@ choose_idle_core()
static CoreEntry* static CoreEntry*
choose_core(const ThreadData* threadData) choose_core(const ThreadData* threadData)
{ {
SCHEDULER_ENTER_FUNCTION();
CoreEntry* core = NULL; CoreEntry* core = NULL;
// try to pack all threads on one core // try to pack all threads on one core
@@ -111,6 +117,8 @@ choose_core(const ThreadData* threadData)
static bool static bool
should_rebalance(const ThreadData* threadData) should_rebalance(const ThreadData* threadData)
{ {
SCHEDULER_ENTER_FUNCTION();
ASSERT(!gSingleCore); ASSERT(!gSingleCore);
CoreEntry* core = threadData->Core(); CoreEntry* core = threadData->Core();
@@ -151,6 +159,8 @@ should_rebalance(const ThreadData* threadData)
static inline void static inline void
pack_irqs() pack_irqs()
{ {
SCHEDULER_ENTER_FUNCTION();
CoreEntry* smallTaskCore = atomic_pointer_get(&sSmallTaskCore); CoreEntry* smallTaskCore = atomic_pointer_get(&sSmallTaskCore);
if (smallTaskCore == NULL) if (smallTaskCore == NULL)
return; return;
@@ -177,6 +187,8 @@ pack_irqs()
static void static void
rebalance_irqs(bool idle) rebalance_irqs(bool idle)
{ {
SCHEDULER_ENTER_FUNCTION();
if (idle && sSmallTaskCore != NULL) { if (idle && sSmallTaskCore != NULL) {
pack_irqs(); pack_irqs();
return; return;
+24 -13
View File
@@ -32,6 +32,7 @@
#include "scheduler_common.h" #include "scheduler_common.h"
#include "scheduler_cpu.h" #include "scheduler_cpu.h"
#include "scheduler_modes.h" #include "scheduler_modes.h"
#include "scheduler_profiler.h"
#include "scheduler_thread.h" #include "scheduler_thread.h"
#include "scheduler_tracing.h" #include "scheduler_tracing.h"
@@ -192,7 +193,7 @@ scheduler_dump_thread_data(Thread* thread)
static void static void
enqueue(Thread* thread, bool newOne) enqueue(Thread* thread, bool newOne)
{ {
ASSERT(thread != NULL); SCHEDULER_ENTER_FUNCTION();
ThreadData* threadData = thread->scheduler_data; ThreadData* threadData = thread->scheduler_data;
@@ -243,10 +244,8 @@ enqueue(Thread* thread, bool newOne)
void void
scheduler_enqueue_in_run_queue(Thread *thread) scheduler_enqueue_in_run_queue(Thread *thread)
{ {
#if KDEBUG ASSERT(!are_interrupts_enabled());
if (are_interrupts_enabled()) SCHEDULER_ENTER_FUNCTION();
panic("scheduler_enqueue_in_run_queue: called with interrupts enabled");
#endif
SchedulerModeLocker _; SchedulerModeLocker _;
@@ -267,14 +266,13 @@ scheduler_enqueue_in_run_queue(Thread *thread)
int32 int32
scheduler_set_thread_priority(Thread *thread, int32 priority) scheduler_set_thread_priority(Thread *thread, int32 priority)
{ {
#if KDEBUG ASSERT(are_interrupts_enabled());
if (!are_interrupts_enabled())
panic("scheduler_set_thread_priority: called with interrupts disabled");
#endif
InterruptsSpinLocker _(thread->scheduler_lock); InterruptsSpinLocker _(thread->scheduler_lock);
SchedulerModeLocker modeLocker; SchedulerModeLocker modeLocker;
SCHEDULER_ENTER_FUNCTION();
ThreadData* threadData = thread->scheduler_data; ThreadData* threadData = thread->scheduler_data;
int32 oldPriority = thread->priority; int32 oldPriority = thread->priority;
@@ -431,6 +429,8 @@ switch_thread(Thread* fromThread, Thread* toThread)
static inline void static inline void
update_thread_times(Thread* oldThread, Thread* nextThread) update_thread_times(Thread* oldThread, Thread* nextThread)
{ {
SCHEDULER_ENTER_FUNCTION();
bigtime_t now = system_time(); bigtime_t now = system_time();
if (oldThread == nextThread) { if (oldThread == nextThread) {
SpinLocker _(oldThread->time_lock); SpinLocker _(oldThread->time_lock);
@@ -459,6 +459,7 @@ static void
reschedule(int32 nextState) reschedule(int32 nextState)
{ {
ASSERT(!are_interrupts_enabled()); ASSERT(!are_interrupts_enabled());
SCHEDULER_ENTER_FUNCTION();
SchedulerModeLocker modeLocker; SchedulerModeLocker modeLocker;
@@ -584,6 +585,9 @@ reschedule(int32 nextState)
nextThreadData->StartQuantum(); nextThreadData->StartQuantum();
modeLocker.Unlock(); modeLocker.Unlock();
SCHEDULER_EXIT_FUNCTION();
if (nextThread != oldThread) if (nextThread != oldThread)
switch_thread(oldThread, nextThread); switch_thread(oldThread, nextThread);
} }
@@ -596,10 +600,8 @@ reschedule(int32 nextState)
void void
scheduler_reschedule(int32 nextState) scheduler_reschedule(int32 nextState)
{ {
#if KDEBUG ASSERT(!are_interrupts_enabled());
if (are_interrupts_enabled()) SCHEDULER_ENTER_FUNCTION();
panic("scheduler_reschedule: called with interrupts enabled");
#endif
if (!sSchedulerEnabled) { if (!sSchedulerEnabled) {
Thread* thread = thread_get_current_thread(); Thread* thread = thread_get_current_thread();
@@ -652,6 +654,7 @@ void
scheduler_start() scheduler_start()
{ {
InterruptsSpinLocker _(thread_get_current_thread()->scheduler_lock); InterruptsSpinLocker _(thread_get_current_thread()->scheduler_lock);
SCHEDULER_ENTER_FUNCTION();
reschedule(B_THREAD_READY); reschedule(B_THREAD_READY);
} }
@@ -847,6 +850,10 @@ scheduler_init()
" cache level%s\n", cpuCount, cpuCount != 1 ? "s" : "", " cache level%s\n", cpuCount, cpuCount != 1 ? "s" : "",
gCPUCacheLevelCount, gCPUCacheLevelCount != 1 ? "s" : ""); gCPUCacheLevelCount, gCPUCacheLevelCount != 1 ? "s" : "");
#ifdef SCHEDULER_PROFILING
Profiling::Profiler::Initialize();
#endif
status_t result = init(); status_t result = init();
if (result != B_OK) if (result != B_OK)
panic("scheduler_init: failed to initialize scheduler\n"); panic("scheduler_init: failed to initialize scheduler\n");
@@ -923,6 +930,10 @@ _user_estimate_max_scheduling_latency(thread_id id)
} }
BReference<Thread> threadReference(thread, true); BReference<Thread> threadReference(thread, true);
#ifdef SCHEDULER_PROFILING
InterruptsLocker _;
#endif
ThreadData* threadData = thread->scheduler_data; ThreadData* threadData = thread->scheduler_data;
CoreEntry* core = threadData->Core(); CoreEntry* core = threadData->Core();
if (core == NULL) if (core == NULL)
@@ -99,6 +99,7 @@ CPUEntry::Stop()
void void
CPUEntry::PushFront(ThreadData* thread, int32 priority) CPUEntry::PushFront(ThreadData* thread, int32 priority)
{ {
SCHEDULER_ENTER_FUNCTION();
fRunQueue.PushFront(thread, priority); fRunQueue.PushFront(thread, priority);
} }
@@ -106,6 +107,7 @@ CPUEntry::PushFront(ThreadData* thread, int32 priority)
void void
CPUEntry::PushBack(ThreadData* thread, int32 priority) CPUEntry::PushBack(ThreadData* thread, int32 priority)
{ {
SCHEDULER_ENTER_FUNCTION();
fRunQueue.PushBack(thread, priority); fRunQueue.PushBack(thread, priority);
} }
@@ -113,6 +115,7 @@ CPUEntry::PushBack(ThreadData* thread, int32 priority)
void void
CPUEntry::Remove(ThreadData* thread) CPUEntry::Remove(ThreadData* thread)
{ {
SCHEDULER_ENTER_FUNCTION();
ASSERT(thread->IsEnqueued()); ASSERT(thread->IsEnqueued());
thread->SetDequeued(); thread->SetDequeued();
fRunQueue.Remove(thread); fRunQueue.Remove(thread);
@@ -122,6 +125,7 @@ CPUEntry::Remove(ThreadData* thread)
inline ThreadData* inline ThreadData*
CPUEntry::PeekThread() const CPUEntry::PeekThread() const
{ {
SCHEDULER_ENTER_FUNCTION();
return fRunQueue.PeekMaximum(); return fRunQueue.PeekMaximum();
} }
@@ -129,6 +133,7 @@ CPUEntry::PeekThread() const
ThreadData* ThreadData*
CPUEntry::PeekIdleThread() const CPUEntry::PeekIdleThread() const
{ {
SCHEDULER_ENTER_FUNCTION();
return fRunQueue.GetHead(B_IDLE_PRIORITY); return fRunQueue.GetHead(B_IDLE_PRIORITY);
} }
@@ -136,6 +141,8 @@ CPUEntry::PeekIdleThread() const
void void
CPUEntry::UpdatePriority(int32 priority) CPUEntry::UpdatePriority(int32 priority)
{ {
SCHEDULER_ENTER_FUNCTION();
if (gCPU[fCPUNumber].disabled) if (gCPU[fCPUNumber].disabled)
return; return;
@@ -161,6 +168,8 @@ CPUEntry::UpdatePriority(int32 priority)
void void
CPUEntry::ComputeLoad() CPUEntry::ComputeLoad()
{ {
SCHEDULER_ENTER_FUNCTION();
ASSERT(!gSingleCore); ASSERT(!gSingleCore);
ASSERT(fCPUNumber == smp_get_current_cpu()); ASSERT(fCPUNumber == smp_get_current_cpu());
@@ -181,6 +190,8 @@ CPUEntry::ComputeLoad()
ThreadData* ThreadData*
CPUEntry::ChooseNextThread(ThreadData* oldThread, bool putAtBack) CPUEntry::ChooseNextThread(ThreadData* oldThread, bool putAtBack)
{ {
SCHEDULER_ENTER_FUNCTION();
CoreRunQueueLocker _(fCore); CoreRunQueueLocker _(fCore);
ThreadData* sharedThread = fCore->PeekThread(); ThreadData* sharedThread = fCore->PeekThread();
@@ -217,6 +228,8 @@ CPUEntry::ChooseNextThread(ThreadData* oldThread, bool putAtBack)
void void
CPUEntry::TrackActivity(ThreadData* oldThreadData, ThreadData* nextThreadData) CPUEntry::TrackActivity(ThreadData* oldThreadData, ThreadData* nextThreadData)
{ {
SCHEDULER_ENTER_FUNCTION();
cpu_ent* cpuEntry = &gCPU[fCPUNumber]; cpu_ent* cpuEntry = &gCPU[fCPUNumber];
Thread* oldThread = oldThreadData->GetThread(); Thread* oldThread = oldThreadData->GetThread();
@@ -252,6 +265,8 @@ CPUEntry::TrackActivity(ThreadData* oldThreadData, ThreadData* nextThreadData)
inline void inline void
CPUEntry::_RequestPerformanceLevel(ThreadData* threadData) CPUEntry::_RequestPerformanceLevel(ThreadData* threadData)
{ {
SCHEDULER_ENTER_FUNCTION();
int32 load = std::max(threadData->GetLoad(), fCore->GetLoad()); int32 load = std::max(threadData->GetLoad(), fCore->GetLoad());
load = std::min(std::max(load, int32(0)), kMaxLoad); load = std::min(std::max(load, int32(0)), kMaxLoad);
@@ -332,6 +347,8 @@ CoreEntry::Init(int32 id, PackageEntry* package)
void void
CoreEntry::PushFront(ThreadData* thread, int32 priority) CoreEntry::PushFront(ThreadData* thread, int32 priority)
{ {
SCHEDULER_ENTER_FUNCTION();
fRunQueue.PushFront(thread, priority); fRunQueue.PushFront(thread, priority);
atomic_add(&fThreadCount, 1); atomic_add(&fThreadCount, 1);
} }
@@ -340,6 +357,8 @@ CoreEntry::PushFront(ThreadData* thread, int32 priority)
void void
CoreEntry::PushBack(ThreadData* thread, int32 priority) CoreEntry::PushBack(ThreadData* thread, int32 priority)
{ {
SCHEDULER_ENTER_FUNCTION();
fRunQueue.PushBack(thread, priority); fRunQueue.PushBack(thread, priority);
fThreadList.Insert(thread); fThreadList.Insert(thread);
@@ -350,6 +369,8 @@ CoreEntry::PushBack(ThreadData* thread, int32 priority)
void void
CoreEntry::Remove(ThreadData* thread) CoreEntry::Remove(ThreadData* thread)
{ {
SCHEDULER_ENTER_FUNCTION();
ASSERT(thread->IsEnqueued()); ASSERT(thread->IsEnqueued());
thread->SetDequeued(); thread->SetDequeued();
if (thread_is_idle_thread(thread->GetThread()) if (thread_is_idle_thread(thread->GetThread())
@@ -366,6 +387,7 @@ CoreEntry::Remove(ThreadData* thread)
inline ThreadData* inline ThreadData*
CoreEntry::PeekThread() const CoreEntry::PeekThread() const
{ {
SCHEDULER_ENTER_FUNCTION();
return fRunQueue.PeekMaximum(); return fRunQueue.PeekMaximum();
} }
@@ -373,6 +395,8 @@ CoreEntry::PeekThread() const
void void
CoreEntry::UpdateLoad(int32 delta) CoreEntry::UpdateLoad(int32 delta)
{ {
SCHEDULER_ENTER_FUNCTION();
if (fCPUCount == 0) { if (fCPUCount == 0) {
fLoad = 0; fLoad = 0;
return; return;
@@ -544,6 +568,8 @@ PackageEntry::Init(int32 id)
inline void inline void
PackageEntry::CoreGoesIdle(CoreEntry* core) PackageEntry::CoreGoesIdle(CoreEntry* core)
{ {
SCHEDULER_ENTER_FUNCTION();
WriteSpinLocker _(fCoreLock); WriteSpinLocker _(fCoreLock);
ASSERT(fIdleCoreCount >= 0); ASSERT(fIdleCoreCount >= 0);
@@ -563,6 +589,8 @@ PackageEntry::CoreGoesIdle(CoreEntry* core)
inline void inline void
PackageEntry::CoreWakesUp(CoreEntry* core) PackageEntry::CoreWakesUp(CoreEntry* core)
{ {
SCHEDULER_ENTER_FUNCTION();
WriteSpinLocker _(fCoreLock); WriteSpinLocker _(fCoreLock);
ASSERT(fIdleCoreCount > 0); ASSERT(fIdleCoreCount > 0);
+24 -2
View File
@@ -17,6 +17,7 @@
#include "RunQueue.h" #include "RunQueue.h"
#include "scheduler_common.h" #include "scheduler_common.h"
#include "scheduler_modes.h" #include "scheduler_modes.h"
#include "scheduler_profiler.h"
namespace Scheduler { namespace Scheduler {
@@ -277,6 +278,7 @@ extern int32 gPackageCount;
inline void inline void
CPUEntry::EnterScheduler() CPUEntry::EnterScheduler()
{ {
SCHEDULER_ENTER_FUNCTION();
acquire_read_spinlock(&fSchedulerModeLock); acquire_read_spinlock(&fSchedulerModeLock);
} }
@@ -284,6 +286,7 @@ CPUEntry::EnterScheduler()
inline void inline void
CPUEntry::ExitScheduler() CPUEntry::ExitScheduler()
{ {
SCHEDULER_ENTER_FUNCTION();
release_read_spinlock(&fSchedulerModeLock); release_read_spinlock(&fSchedulerModeLock);
} }
@@ -291,6 +294,7 @@ CPUEntry::ExitScheduler()
inline void inline void
CPUEntry::LockScheduler() CPUEntry::LockScheduler()
{ {
SCHEDULER_ENTER_FUNCTION();
acquire_write_spinlock(&fSchedulerModeLock); acquire_write_spinlock(&fSchedulerModeLock);
} }
@@ -298,6 +302,7 @@ CPUEntry::LockScheduler()
inline void inline void
CPUEntry::UnlockScheduler() CPUEntry::UnlockScheduler()
{ {
SCHEDULER_ENTER_FUNCTION();
release_write_spinlock(&fSchedulerModeLock); release_write_spinlock(&fSchedulerModeLock);
} }
@@ -305,6 +310,7 @@ CPUEntry::UnlockScheduler()
inline void inline void
CPUEntry::IncreaseActiveTime(bigtime_t activeTime) CPUEntry::IncreaseActiveTime(bigtime_t activeTime)
{ {
SCHEDULER_ENTER_FUNCTION();
fMeasureActiveTime += activeTime; fMeasureActiveTime += activeTime;
} }
@@ -312,6 +318,7 @@ CPUEntry::IncreaseActiveTime(bigtime_t activeTime)
/* static */ inline CPUEntry* /* static */ inline CPUEntry*
CPUEntry::GetCPU(int32 cpu) CPUEntry::GetCPU(int32 cpu)
{ {
SCHEDULER_ENTER_FUNCTION();
return &gCPUEntries[cpu]; return &gCPUEntries[cpu];
} }
@@ -319,6 +326,7 @@ CPUEntry::GetCPU(int32 cpu)
inline void inline void
CoreEntry::LockCPUHeap() CoreEntry::LockCPUHeap()
{ {
SCHEDULER_ENTER_FUNCTION();
acquire_spinlock(&fCPULock); acquire_spinlock(&fCPULock);
} }
@@ -326,6 +334,7 @@ CoreEntry::LockCPUHeap()
inline void inline void
CoreEntry::UnlockCPUHeap() CoreEntry::UnlockCPUHeap()
{ {
SCHEDULER_ENTER_FUNCTION();
release_spinlock(&fCPULock); release_spinlock(&fCPULock);
} }
@@ -333,6 +342,7 @@ CoreEntry::UnlockCPUHeap()
inline CPUPriorityHeap* inline CPUPriorityHeap*
CoreEntry::CPUHeap() CoreEntry::CPUHeap()
{ {
SCHEDULER_ENTER_FUNCTION();
return &fCPUHeap; return &fCPUHeap;
} }
@@ -340,6 +350,7 @@ CoreEntry::CPUHeap()
inline void inline void
CoreEntry::LockRunQueue() CoreEntry::LockRunQueue()
{ {
SCHEDULER_ENTER_FUNCTION();
acquire_spinlock(&fQueueLock); acquire_spinlock(&fQueueLock);
} }
@@ -347,6 +358,7 @@ CoreEntry::LockRunQueue()
inline void inline void
CoreEntry::UnlockRunQueue() CoreEntry::UnlockRunQueue()
{ {
SCHEDULER_ENTER_FUNCTION();
release_spinlock(&fQueueLock); release_spinlock(&fQueueLock);
} }
@@ -354,6 +366,7 @@ CoreEntry::UnlockRunQueue()
inline void inline void
CoreEntry::IncreaseActiveTime(bigtime_t activeTime) CoreEntry::IncreaseActiveTime(bigtime_t activeTime)
{ {
SCHEDULER_ENTER_FUNCTION();
WriteSequentialLocker _(fActiveTimeLock); WriteSequentialLocker _(fActiveTimeLock);
fActiveTime += activeTime; fActiveTime += activeTime;
} }
@@ -362,14 +375,14 @@ CoreEntry::IncreaseActiveTime(bigtime_t activeTime)
inline bigtime_t inline bigtime_t
CoreEntry::GetActiveTime() const CoreEntry::GetActiveTime() const
{ {
bigtime_t activeTime; SCHEDULER_ENTER_FUNCTION();
bigtime_t activeTime;
uint32 count; uint32 count;
do { do {
count = acquire_read_seqlock(&fActiveTimeLock); count = acquire_read_seqlock(&fActiveTimeLock);
activeTime = fActiveTime; activeTime = fActiveTime;
} while (!release_read_seqlock(&fActiveTimeLock, count)); } while (!release_read_seqlock(&fActiveTimeLock, count));
return activeTime; return activeTime;
} }
@@ -377,6 +390,8 @@ CoreEntry::GetActiveTime() const
inline int32 inline int32
CoreEntry::GetLoad() const CoreEntry::GetLoad() const
{ {
SCHEDULER_ENTER_FUNCTION();
ASSERT(fCPUCount >= 0); ASSERT(fCPUCount >= 0);
return fLoad / fCPUCount; return fLoad / fCPUCount;
} }
@@ -385,6 +400,7 @@ CoreEntry::GetLoad() const
inline int32 inline int32
CoreEntry::StarvationCounter() const CoreEntry::StarvationCounter() const
{ {
SCHEDULER_ENTER_FUNCTION();
return fStarvationCounter; return fStarvationCounter;
} }
@@ -392,6 +408,7 @@ CoreEntry::StarvationCounter() const
/* static */ inline CoreEntry* /* static */ inline CoreEntry*
CoreEntry::GetCore(int32 cpu) CoreEntry::GetCore(int32 cpu)
{ {
SCHEDULER_ENTER_FUNCTION();
return gCPUEntries[cpu].Core(); return gCPUEntries[cpu].Core();
} }
@@ -399,6 +416,7 @@ CoreEntry::GetCore(int32 cpu)
inline CoreEntry* inline CoreEntry*
PackageEntry::GetIdleCore() const PackageEntry::GetIdleCore() const
{ {
SCHEDULER_ENTER_FUNCTION();
return fIdleCores.Last(); return fIdleCores.Last();
} }
@@ -406,6 +424,8 @@ PackageEntry::GetIdleCore() const
/* static */ inline PackageEntry* /* static */ inline PackageEntry*
PackageEntry::GetMostIdlePackage() PackageEntry::GetMostIdlePackage()
{ {
SCHEDULER_ENTER_FUNCTION();
PackageEntry* current = &gPackageEntries[0]; PackageEntry* current = &gPackageEntries[0];
for (int32 i = 1; i < gPackageCount; i++) { for (int32 i = 1; i < gPackageCount; i++) {
if (gPackageEntries[i].fIdleCoreCount > current->fIdleCoreCount) if (gPackageEntries[i].fIdleCoreCount > current->fIdleCoreCount)
@@ -422,6 +442,8 @@ PackageEntry::GetMostIdlePackage()
/* static */ inline PackageEntry* /* static */ inline PackageEntry*
PackageEntry::GetLeastIdlePackage() PackageEntry::GetLeastIdlePackage()
{ {
SCHEDULER_ENTER_FUNCTION();
PackageEntry* package = NULL; PackageEntry* package = NULL;
for (int32 i = 0; i < gPackageCount; i++) { for (int32 i = 0; i < gPackageCount; i++) {
@@ -0,0 +1,298 @@
/*
* Copyright 2013, Paweł Dziepak, pdziepak@quarnos.org.
* Distributed under the terms of the MIT License.
*/
#include "scheduler_profiler.h"
#include <debug.h>
#include <util/AutoLock.h>
#include <algorithm>
#ifdef SCHEDULER_PROFILING
using namespace Scheduler;
using namespace Scheduler::Profiling;
static Profiler* sProfiler;
static int dump_profiler(int argc, char** argv);
Profiler::Profiler()
:
kMaxFunctionEntries(1024),
kMaxFunctionStackEntries(512),
fFunctionData(new(std::nothrow) FunctionData[kMaxFunctionEntries]),
fStatus(B_OK)
{
B_INITIALIZE_SPINLOCK(&fFunctionLock);
if (fFunctionData == NULL) {
fStatus = B_NO_MEMORY;
return;
}
memset(fFunctionData, 0, sizeof(FunctionData) * kMaxFunctionEntries);
for (int32 i = 0; i < smp_get_num_cpus(); i++) {
fFunctionStacks[i]
= new(std::nothrow) FunctionEntry[kMaxFunctionStackEntries];
if (fFunctionStacks[i] == NULL) {
fStatus = B_NO_MEMORY;
return;
}
memset(fFunctionStacks[i], 0,
sizeof(FunctionEntry) * kMaxFunctionStackEntries);
}
memset(fFunctionStackPointers, 0, sizeof(int32) * smp_get_num_cpus());
}
void
Profiler::EnterFunction(int32 cpu, const char* functionName)
{
FunctionData* function = _FindFunction(functionName);
if (function == NULL)
return;
atomic_add((int32*)&function->fCalled, 1);
FunctionEntry* stackEntry
= &fFunctionStacks[cpu][fFunctionStackPointers[cpu]];
fFunctionStackPointers[cpu]++;
ASSERT(fFunctionStackPointers[cpu] < kMaxFunctionStackEntries);
stackEntry->fFunction = function;
stackEntry->fEntryTime = system_time();
stackEntry->fOthersTime = 0;
}
void
Profiler::ExitFunction(int32 cpu, const char* functionName)
{
ASSERT(fFunctionStackPointers[cpu] > 0);
fFunctionStackPointers[cpu]--;
FunctionEntry* stackEntry
= &fFunctionStacks[cpu][fFunctionStackPointers[cpu]];
bigtime_t timeSpent = system_time() - stackEntry->fEntryTime;
atomic_add64(&stackEntry->fFunction->fTimeInclusive, timeSpent);
atomic_add64(&stackEntry->fFunction->fTimeExclusive,
timeSpent - stackEntry->fOthersTime);
if (fFunctionStackPointers[cpu] > 0) {
stackEntry = &fFunctionStacks[cpu][fFunctionStackPointers[cpu] - 1];
stackEntry->fOthersTime += timeSpent;
}
}
void
Profiler::DumpCalled(uint32 maxCount)
{
uint32 count = _FunctionCount();
qsort(fFunctionData, count, sizeof(FunctionData),
&_CompareFunctions<uint32, &FunctionData::fCalled>);
if (maxCount > 0)
count = std::min(count, maxCount);
_Dump(count);
}
void
Profiler::DumpTimeInclusive(uint32 maxCount)
{
uint32 count = _FunctionCount();
qsort(fFunctionData, count, sizeof(FunctionData),
&_CompareFunctions<bigtime_t, &FunctionData::fTimeInclusive>);
if (maxCount > 0)
count = std::min(count, maxCount);
_Dump(count);
}
void
Profiler::DumpTimeExclusive(uint32 maxCount)
{
uint32 count = _FunctionCount();
qsort(fFunctionData, count, sizeof(FunctionData),
&_CompareFunctions<bigtime_t, &FunctionData::fTimeExclusive>);
if (maxCount > 0)
count = std::min(count, maxCount);
_Dump(count);
}
void
Profiler::DumpTimeInclusivePerCall(uint32 maxCount)
{
uint32 count = _FunctionCount();
qsort(fFunctionData, count, sizeof(FunctionData),
&_CompareFunctionsPerCall<bigtime_t, &FunctionData::fTimeInclusive>);
if (maxCount > 0)
count = std::min(count, maxCount);
_Dump(count);
}
void
Profiler::DumpTimeExclusivePerCall(uint32 maxCount)
{
uint32 count = _FunctionCount();
qsort(fFunctionData, count, sizeof(FunctionData),
&_CompareFunctionsPerCall<bigtime_t, &FunctionData::fTimeExclusive>);
if (maxCount > 0)
count = std::min(count, maxCount);
_Dump(count);
}
/* static */ Profiler*
Profiler::Get()
{
return sProfiler;
}
/* static */ void
Profiler::Initialize()
{
sProfiler = new(std::nothrow) Profiler;
if (sProfiler == NULL || sProfiler->GetStatus() != B_OK)
panic("Scheduler::Profiling::Profiler: could not initialize profiler");
add_debugger_command_etc("scheduler_profiler", &dump_profiler,
"Show data collected by scheduler profiler",
"[ <field> [ <count> ] ]\n"
"Shows data collected by scheduler profiler\n"
" <field> - Field used to sort functions. Available: called,"
" time-inclusive, time-inclusive-per-call, time-exclusive,"
" time-exclusive-per-call.\n"
" (defaults to \"called\")\n"
" <count> - Maximum number of showed functions.\n", 0);
}
uint32
Profiler::_FunctionCount() const
{
uint32 count;
for (count = 0; count < kMaxFunctionEntries; count++) {
if (fFunctionData[count].fFunction == NULL)
break;
}
return count;
}
void
Profiler::_Dump(uint32 count)
{
kprintf("Function calls (%" B_PRId32 " functions):\n", count);
kprintf(" called time-inclusive per-call time-exclusive per-call "
"function\n");
for (uint32 i = 0; i < count; i++) {
FunctionData* function = &fFunctionData[i];
kprintf("%10" B_PRId32 " %14" B_PRId64 " %8" B_PRId64 " %14" B_PRId64
" %8" B_PRId64 " %s\n", function->fCalled,
function->fTimeInclusive,
function->fTimeInclusive / function->fCalled,
function->fTimeExclusive,
function->fTimeExclusive / function->fCalled, function->fFunction);
}
}
Profiler::FunctionData*
Profiler::_FindFunction(const char* function)
{
for (uint32 i = 0; i < kMaxFunctionEntries; i++) {
if (fFunctionData[i].fFunction == NULL)
break;
if (!strcmp(fFunctionData[i].fFunction, function))
return fFunctionData + i;
}
SpinLocker _(fFunctionLock);
for (uint32 i = 0; i < kMaxFunctionEntries; i++) {
if (fFunctionData[i].fFunction == NULL) {
fFunctionData[i].fFunction = function;
return fFunctionData + i;
}
if (!strcmp(fFunctionData[i].fFunction, function))
return fFunctionData + i;
}
return NULL;
}
template<typename Type, Type Profiler::FunctionData::*Member>
/* static */ int
Profiler::_CompareFunctions(const void* _a, const void* _b)
{
const FunctionData* a = static_cast<const FunctionData*>(_a);
const FunctionData* b = static_cast<const FunctionData*>(_b);
return b->*Member - a->*Member;
}
template<typename Type, Type Profiler::FunctionData::*Member>
/* static */ int
Profiler::_CompareFunctionsPerCall(const void* _a, const void* _b)
{
const FunctionData* a = static_cast<const FunctionData*>(_a);
const FunctionData* b = static_cast<const FunctionData*>(_b);
return b->*Member / b->fCalled - a->*Member / a->fCalled;
}
static int
dump_profiler(int argc, char** argv)
{
if (argc < 2) {
Profiler::Get()->DumpCalled(0);
return 0;
}
int32 count = 0;
if (argc >= 3)
count = parse_expression(argv[2]);
count = std::max(count, int32(0));
if (!strcmp(argv[1], "called"))
Profiler::Get()->DumpCalled(count);
else if (!strcmp(argv[1], "time-inclusive"))
Profiler::Get()->DumpTimeInclusive(count);
else if (!strcmp(argv[1], "time-inclusive-per-call"))
Profiler::Get()->DumpTimeInclusivePerCall(count);
else if (!strcmp(argv[1], "time-exclusive"))
Profiler::Get()->DumpTimeExclusive(count);
else if (!strcmp(argv[1], "time-exclusive-per-call"))
Profiler::Get()->DumpTimeExclusivePerCall(count);
else
print_debugger_command_usage(argv[0]);
return 0;
}
#endif // SCHEDULER_PROFILING
@@ -0,0 +1,135 @@
/*
* Copyright 2013, Paweł Dziepak, pdziepak@quarnos.org.
* Distributed under the terms of the MIT License.
*/
#ifndef KERNEL_SCHEDULER_PROFILER_H
#define KERNEL_SCHEDULER_PROFILER_H
#include <smp.h>
//#define SCHEDULER_PROFILING
#ifdef SCHEDULER_PROFILING
#define SCHEDULER_ENTER_FUNCTION() \
Scheduler::Profiling::Function schedulerProfiler(__PRETTY_FUNCTION__)
#define SCHEDULER_EXIT_FUNCTION() \
schedulerProfiler.Exit()
namespace Scheduler {
namespace Profiling {
class Profiler {
public:
Profiler();
void EnterFunction(int32 cpu, const char* function);
void ExitFunction(int32 cpu, const char* function);
void DumpCalled(uint32 count);
void DumpTimeInclusive(uint32 count);
void DumpTimeExclusive(uint32 count);
void DumpTimeInclusivePerCall(uint32 count);
void DumpTimeExclusivePerCall(uint32 count);
status_t GetStatus() const { return fStatus; }
static Profiler* Get();
static void Initialize();
private:
struct FunctionData {
const char* fFunction;
uint32 fCalled;
bigtime_t fTimeInclusive;
bigtime_t fTimeExclusive;
};
struct FunctionEntry {
FunctionData* fFunction;
bigtime_t fEntryTime;
bigtime_t fOthersTime;
};
uint32 _FunctionCount() const;
void _Dump(uint32 count);
FunctionData* _FindFunction(const char* function);
template<typename Type, Type FunctionData::*Member>
static int _CompareFunctions(const void* a, const void* b);
template<typename Type, Type FunctionData::*Member>
static int _CompareFunctionsPerCall(const void* a,
const void* b);
const uint32 kMaxFunctionEntries;
const uint32 kMaxFunctionStackEntries;
FunctionEntry* fFunctionStacks[SMP_MAX_CPUS];
uint32 fFunctionStackPointers[SMP_MAX_CPUS];
FunctionData* fFunctionData;
spinlock fFunctionLock;
status_t fStatus;
};
class Function {
public:
inline Function(const char* functionName);
inline ~Function();
inline void Exit();
private:
const char* fFunctionName;
};
Function::Function(const char* functionName)
:
fFunctionName(functionName)
{
Profiler::Get()->EnterFunction(smp_get_current_cpu(), fFunctionName);
}
Function::~Function()
{
if (fFunctionName != NULL)
Exit();
}
void
Function::Exit()
{
Profiler::Get()->ExitFunction(smp_get_current_cpu(), fFunctionName);
fFunctionName = NULL;
}
} // namespace Profiling
} // namespace Scheduler
#else // SCHEDULER_PROFILING
#define SCHEDULER_ENTER_FUNCTION() (void)0
#define SCHEDULER_EXIT_FUNCTION() (void)0
#endif // !SCHEDULER_PROFILING
#endif // KERNEL_SCHEDULER_PROFILER_H
@@ -78,6 +78,8 @@ ThreadData::Dump() const
bool bool
ThreadData::ChooseCoreAndCPU(CoreEntry*& targetCore, CPUEntry*& targetCPU) ThreadData::ChooseCoreAndCPU(CoreEntry*& targetCore, CPUEntry*& targetCPU)
{ {
SCHEDULER_ENTER_FUNCTION();
bool rescheduleNeeded = false; bool rescheduleNeeded = false;
if (targetCore == NULL && targetCPU != NULL) if (targetCore == NULL && targetCPU != NULL)
@@ -100,6 +102,8 @@ ThreadData::ChooseCoreAndCPU(CoreEntry*& targetCore, CPUEntry*& targetCPU)
bigtime_t bigtime_t
ThreadData::ComputeQuantum() ThreadData::ComputeQuantum()
{ {
SCHEDULER_ENTER_FUNCTION();
bigtime_t quantum; bigtime_t quantum;
if (fTimeLeft != 0) if (fTimeLeft != 0)
quantum = fTimeLeft; quantum = fTimeLeft;
@@ -127,6 +131,8 @@ ThreadData::ComputeQuantum()
/* static */ void /* static */ void
ThreadData::ComputeQuantumLengths() ThreadData::ComputeQuantumLengths()
{ {
SCHEDULER_ENTER_FUNCTION();
for (int32 priority = 0; priority <= THREAD_MAX_SET_PRIORITY; priority++) { for (int32 priority = 0; priority <= THREAD_MAX_SET_PRIORITY; priority++) {
const bigtime_t kQuantum0 = gCurrentMode->base_quantum; const bigtime_t kQuantum0 = gCurrentMode->base_quantum;
if (priority >= B_URGENT_DISPLAY_PRIORITY) { if (priority >= B_URGENT_DISPLAY_PRIORITY) {
@@ -153,6 +159,8 @@ ThreadData::ComputeQuantumLengths()
void void
ThreadData::_ComputeEffectivePriority() const ThreadData::_ComputeEffectivePriority() const
{ {
SCHEDULER_ENTER_FUNCTION();
if (thread_is_idle_thread(fThread)) if (thread_is_idle_thread(fThread))
fEffectivePriority = B_IDLE_PRIORITY; fEffectivePriority = B_IDLE_PRIORITY;
else if (fThread->priority >= B_FIRST_REAL_TIME_PRIORITY) else if (fThread->priority >= B_FIRST_REAL_TIME_PRIORITY)
@@ -170,6 +178,8 @@ ThreadData::_ComputeEffectivePriority() const
inline CoreEntry* inline CoreEntry*
ThreadData::_ChooseCore() const ThreadData::_ChooseCore() const
{ {
SCHEDULER_ENTER_FUNCTION();
ASSERT(!gSingleCore); ASSERT(!gSingleCore);
return gCurrentMode->choose_core(this); return gCurrentMode->choose_core(this);
} }
@@ -178,6 +188,8 @@ ThreadData::_ChooseCore() const
inline CPUEntry* inline CPUEntry*
ThreadData::_ChooseCPU(CoreEntry* core, bool& rescheduleNeeded) const ThreadData::_ChooseCPU(CoreEntry* core, bool& rescheduleNeeded) const
{ {
SCHEDULER_ENTER_FUNCTION();
int32 threadPriority = GetEffectivePriority(); int32 threadPriority = GetEffectivePriority();
if (fThread->previous_cpu != NULL) { if (fThread->previous_cpu != NULL) {
@@ -209,6 +221,8 @@ ThreadData::_ChooseCPU(CoreEntry* core, bool& rescheduleNeeded) const
inline bigtime_t inline bigtime_t
ThreadData::_GetBaseQuantum() const ThreadData::_GetBaseQuantum() const
{ {
SCHEDULER_ENTER_FUNCTION();
return sQuantumLengths[GetEffectivePriority()]; return sQuantumLengths[GetEffectivePriority()];
} }
@@ -217,6 +231,8 @@ ThreadData::_GetBaseQuantum() const
ThreadData::_ScaleQuantum(bigtime_t maxQuantum, bigtime_t minQuantum, ThreadData::_ScaleQuantum(bigtime_t maxQuantum, bigtime_t minQuantum,
int32 maxPriority, int32 minPriority, int32 priority) int32 maxPriority, int32 minPriority, int32 priority)
{ {
SCHEDULER_ENTER_FUNCTION();
ASSERT(priority <= maxPriority); ASSERT(priority <= maxPriority);
ASSERT(priority >= minPriority); ASSERT(priority >= minPriority);
@@ -11,6 +11,7 @@
#include "scheduler_common.h" #include "scheduler_common.h"
#include "scheduler_cpu.h" #include "scheduler_cpu.h"
#include "scheduler_profiler.h"
namespace Scheduler { namespace Scheduler {
@@ -123,6 +124,7 @@ public:
inline bool inline bool
ThreadData::HasCacheExpired() const ThreadData::HasCacheExpired() const
{ {
SCHEDULER_ENTER_FUNCTION();
return gCurrentMode->has_cache_expired(this); return gCurrentMode->has_cache_expired(this);
} }
@@ -130,6 +132,8 @@ ThreadData::HasCacheExpired() const
inline bool inline bool
ThreadData::ShouldRebalance() const ThreadData::ShouldRebalance() const
{ {
SCHEDULER_ENTER_FUNCTION();
ASSERT(!gSingleCore); ASSERT(!gSingleCore);
return gCurrentMode->should_rebalance(this); return gCurrentMode->should_rebalance(this);
} }
@@ -138,6 +142,8 @@ ThreadData::ShouldRebalance() const
inline int32 inline int32
ThreadData::GetEffectivePriority() const ThreadData::GetEffectivePriority() const
{ {
SCHEDULER_ENTER_FUNCTION();
if (fEffectivePriority == -1) if (fEffectivePriority == -1)
_ComputeEffectivePriority(); _ComputeEffectivePriority();
return fEffectivePriority; return fEffectivePriority;
@@ -147,6 +153,8 @@ ThreadData::GetEffectivePriority() const
inline void inline void
ThreadData::IncreasePenalty() ThreadData::IncreasePenalty()
{ {
SCHEDULER_ENTER_FUNCTION();
if (fThread->priority < B_LOWEST_ACTIVE_PRIORITY) if (fThread->priority < B_LOWEST_ACTIVE_PRIORITY)
return; return;
if (fThread->priority >= B_FIRST_REAL_TIME_PRIORITY) if (fThread->priority >= B_FIRST_REAL_TIME_PRIORITY)
@@ -170,6 +178,8 @@ ThreadData::IncreasePenalty()
inline void inline void
ThreadData::CancelPenalty() ThreadData::CancelPenalty()
{ {
SCHEDULER_ENTER_FUNCTION();
if (fPriorityPenalty != 0) { if (fPriorityPenalty != 0) {
TRACE("cancelling thread %ld penalty\n", fThread->id); TRACE("cancelling thread %ld penalty\n", fThread->id);
fEffectivePriority = -1; fEffectivePriority = -1;
@@ -183,6 +193,8 @@ ThreadData::CancelPenalty()
inline bool inline bool
ThreadData::ShouldCancelPenalty() const ThreadData::ShouldCancelPenalty() const
{ {
SCHEDULER_ENTER_FUNCTION();
if (fCore == NULL) if (fCore == NULL)
return false; return false;
@@ -194,6 +206,7 @@ ThreadData::ShouldCancelPenalty() const
inline void inline void
ThreadData::IncreaseStolenTime(bigtime_t stolenTime) ThreadData::IncreaseStolenTime(bigtime_t stolenTime)
{ {
SCHEDULER_ENTER_FUNCTION();
fStolenTime += stolenTime; fStolenTime += stolenTime;
} }
@@ -201,6 +214,8 @@ ThreadData::IncreaseStolenTime(bigtime_t stolenTime)
inline void inline void
ThreadData::GoesAway() ThreadData::GoesAway()
{ {
SCHEDULER_ENTER_FUNCTION();
fLastInterruptTime = 0; fLastInterruptTime = 0;
fWentSleep = system_time(); fWentSleep = system_time();
@@ -212,6 +227,8 @@ ThreadData::GoesAway()
inline void inline void
ThreadData::PutBack() ThreadData::PutBack()
{ {
SCHEDULER_ENTER_FUNCTION();
ComputeLoad(); ComputeLoad();
fWentSleepCount = -1; fWentSleepCount = -1;
@@ -234,6 +251,8 @@ ThreadData::PutBack()
inline void inline void
ThreadData::Enqueue() ThreadData::Enqueue()
{ {
SCHEDULER_ENTER_FUNCTION();
fThread->state = B_THREAD_READY; fThread->state = B_THREAD_READY;
ComputeLoad(); ComputeLoad();
fWentSleepCount = 0; fWentSleepCount = 0;
@@ -256,6 +275,8 @@ ThreadData::Enqueue()
inline bool inline bool
ThreadData::Dequeue() ThreadData::Dequeue()
{ {
SCHEDULER_ENTER_FUNCTION();
CoreRunQueueLocker _(fCore); CoreRunQueueLocker _(fCore);
if (!fEnqueued) if (!fEnqueued)
return false; return false;
@@ -278,6 +299,8 @@ ThreadData::Dequeue()
inline void inline void
ThreadData::UpdateActivity(bigtime_t active) ThreadData::UpdateActivity(bigtime_t active)
{ {
SCHEDULER_ENTER_FUNCTION();
fMeasureActiveTime += active; fMeasureActiveTime += active;
CPUEntry::GetCPU(smp_get_current_cpu())->IncreaseActiveTime(active); CPUEntry::GetCPU(smp_get_current_cpu())->IncreaseActiveTime(active);
fCore->IncreaseActiveTime(active); fCore->IncreaseActiveTime(active);
@@ -287,6 +310,8 @@ ThreadData::UpdateActivity(bigtime_t active)
inline void inline void
ThreadData::ComputeLoad() ThreadData::ComputeLoad()
{ {
SCHEDULER_ENTER_FUNCTION();
if (fLastInterruptTime > 0) { if (fLastInterruptTime > 0) {
bigtime_t interruptTime = gCPU[smp_get_current_cpu()].interrupt_time; bigtime_t interruptTime = gCPU[smp_get_current_cpu()].interrupt_time;
interruptTime -= fLastInterruptTime; interruptTime -= fLastInterruptTime;
@@ -300,6 +325,8 @@ ThreadData::ComputeLoad()
inline bool inline bool
ThreadData::HasQuantumEnded(bool wasPreempted, bool hasYielded) ThreadData::HasQuantumEnded(bool wasPreempted, bool hasYielded)
{ {
SCHEDULER_ENTER_FUNCTION();
if (hasYielded) { if (hasYielded) {
fTimeLeft = 0; fTimeLeft = 0;
return true; return true;
@@ -322,6 +349,7 @@ ThreadData::HasQuantumEnded(bool wasPreempted, bool hasYielded)
inline void inline void
ThreadData::StartQuantum() ThreadData::StartQuantum()
{ {
SCHEDULER_ENTER_FUNCTION();
fQuantumStart = system_time(); fQuantumStart = system_time();
} }
@@ -329,6 +357,8 @@ ThreadData::StartQuantum()
inline int32 inline int32
ThreadData::_GetPenalty() const ThreadData::_GetPenalty() const
{ {
SCHEDULER_ENTER_FUNCTION();
int32 penalty = fPriorityPenalty; int32 penalty = fPriorityPenalty;
const int kMinimalPriority = _GetMinimalPriority(); const int kMinimalPriority = _GetMinimalPriority();
@@ -342,6 +372,8 @@ ThreadData::_GetPenalty() const
inline int32 inline int32
ThreadData::_GetMinimalPriority() const ThreadData::_GetMinimalPriority() const
{ {
SCHEDULER_ENTER_FUNCTION();
const int32 kDivisor = 5; const int32 kDivisor = 5;
const int32 kMaximalPriority = 25; const int32 kMaximalPriority = 25;