scheduler: Work around GCC2 limitations in function inlining
GCC2 won't inline a function if it is used before its definition.
This commit is contained in:
@@ -41,7 +41,7 @@ typedef void (*smp_call_func)(addr_t data1, int32 currentCPU, addr_t data2, addr
|
|||||||
|
|
||||||
class CPUSet {
|
class CPUSet {
|
||||||
public:
|
public:
|
||||||
CPUSet() { ClearAll(); }
|
inline CPUSet();
|
||||||
|
|
||||||
inline void ClearAll();
|
inline void ClearAll();
|
||||||
inline void SetAll();
|
inline void SetAll();
|
||||||
@@ -92,6 +92,13 @@ int smp_intercpu_int_handler(int32 cpu);
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
inline
|
||||||
|
CPUSet::CPUSet()
|
||||||
|
{
|
||||||
|
memset(fBitmap, 0, sizeof(fBitmap));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
inline void
|
inline void
|
||||||
CPUSet::ClearAll()
|
CPUSet::ClearAll()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -31,6 +31,7 @@
|
|||||||
|
|
||||||
#include "scheduler_common.h"
|
#include "scheduler_common.h"
|
||||||
#include "scheduler_cpu.h"
|
#include "scheduler_cpu.h"
|
||||||
|
#include "scheduler_locking.h"
|
||||||
#include "scheduler_modes.h"
|
#include "scheduler_modes.h"
|
||||||
#include "scheduler_profiler.h"
|
#include "scheduler_profiler.h"
|
||||||
#include "scheduler_thread.h"
|
#include "scheduler_thread.h"
|
||||||
@@ -40,93 +41,6 @@
|
|||||||
namespace Scheduler {
|
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 {
|
class ThreadEnqueuer : public ThreadProcessing {
|
||||||
public:
|
public:
|
||||||
void operator()(ThreadData* thread);
|
void operator()(ThreadData* thread);
|
||||||
@@ -624,6 +538,8 @@ scheduler_on_thread_create(Thread* thread, bool idleThread)
|
|||||||
void
|
void
|
||||||
scheduler_on_thread_init(Thread* thread)
|
scheduler_on_thread_init(Thread* thread)
|
||||||
{
|
{
|
||||||
|
ASSERT(thread->scheduler_data != NULL);
|
||||||
|
|
||||||
if (thread_is_idle_thread(thread)) {
|
if (thread_is_idle_thread(thread)) {
|
||||||
static int32 sIdleThreadsID;
|
static int32 sIdleThreadsID;
|
||||||
int32 cpuID = atomic_add(&sIdleThreadsID, 1);
|
int32 cpuID = atomic_add(&sIdleThreadsID, 1);
|
||||||
|
|||||||
@@ -392,14 +392,6 @@ CoreEntry::Remove(ThreadData* thread)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
inline ThreadData*
|
|
||||||
CoreEntry::PeekThread() const
|
|
||||||
{
|
|
||||||
SCHEDULER_ENTER_FUNCTION();
|
|
||||||
return fRunQueue.PeekMaximum();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
CoreEntry::UpdateLoad(int32 delta)
|
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
|
void
|
||||||
CoreEntry::AddCPU(CPUEntry* cpu)
|
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
|
void
|
||||||
PackageEntry::AddIdleCore(CoreEntry* core)
|
PackageEntry::AddIdleCore(CoreEntry* core)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -85,7 +85,7 @@ public:
|
|||||||
static inline CPUEntry* GetCPU(int32 cpu);
|
static inline CPUEntry* GetCPU(int32 cpu);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
inline void _RequestPerformanceLevel(
|
void _RequestPerformanceLevel(
|
||||||
ThreadData* threadData);
|
ThreadData* threadData);
|
||||||
|
|
||||||
int32 fCPUNumber;
|
int32 fCPUNumber;
|
||||||
@@ -112,21 +112,6 @@ public:
|
|||||||
void Dump();
|
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>,
|
class CoreEntry : public MinMaxHeapLinkImpl<CoreEntry, int32>,
|
||||||
public DoublyLinkedListLinkImpl<CoreEntry> {
|
public DoublyLinkedListLinkImpl<CoreEntry> {
|
||||||
@@ -205,37 +190,6 @@ private:
|
|||||||
friend class DebugDumper;
|
friend class DebugDumper;
|
||||||
} CACHE_LINE_ALIGN;
|
} 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> {
|
class CoreLoadHeap : public MinMaxHeap<CoreEntry, int32> {
|
||||||
public:
|
public:
|
||||||
@@ -402,6 +356,14 @@ CoreEntry::IncreaseActiveTime(bigtime_t activeTime)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline ThreadData*
|
||||||
|
CoreEntry::PeekThread() const
|
||||||
|
{
|
||||||
|
SCHEDULER_ENTER_FUNCTION();
|
||||||
|
return fRunQueue.PeekMaximum();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
inline bigtime_t
|
inline bigtime_t
|
||||||
CoreEntry::GetActiveTime() const
|
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*
|
/* static */ inline CoreEntry*
|
||||||
CoreEntry::GetCore(int32 cpu)
|
CoreEntry::GetCore(int32 cpu)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -0,0 +1,158 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2014, Paweł Dziepak, pdziepak@quarnos.org.
|
||||||
|
* 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
|
||||||
|
|
||||||
@@ -12,6 +12,58 @@ using namespace Scheduler;
|
|||||||
static bigtime_t sQuantumLengths[THREAD_MAX_SET_PRIORITY + 1];
|
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)
|
ThreadData::ThreadData(Thread* thread)
|
||||||
:
|
:
|
||||||
fThread(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
|
void
|
||||||
ThreadData::_ComputeEffectivePriority() const
|
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
|
/* static */ bigtime_t
|
||||||
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)
|
||||||
|
|||||||
@@ -11,6 +11,7 @@
|
|||||||
|
|
||||||
#include "scheduler_common.h"
|
#include "scheduler_common.h"
|
||||||
#include "scheduler_cpu.h"
|
#include "scheduler_cpu.h"
|
||||||
|
#include "scheduler_locking.h"
|
||||||
#include "scheduler_profiler.h"
|
#include "scheduler_profiler.h"
|
||||||
|
|
||||||
|
|
||||||
@@ -19,6 +20,17 @@ namespace Scheduler {
|
|||||||
|
|
||||||
struct ThreadData : public DoublyLinkedListLinkImpl<ThreadData>,
|
struct ThreadData : public DoublyLinkedListLinkImpl<ThreadData>,
|
||||||
RunQueueLinkImpl<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:
|
public:
|
||||||
ThreadData(Thread* thread);
|
ThreadData(Thread* thread);
|
||||||
|
|
||||||
@@ -72,17 +84,12 @@ public:
|
|||||||
inline void UnassignCore() { fCore = NULL; }
|
inline void UnassignCore() { fCore = NULL; }
|
||||||
|
|
||||||
static void ComputeQuantumLengths();
|
static void ComputeQuantumLengths();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
inline int32 _GetPenalty() const;
|
inline int32 _GetPenalty() const;
|
||||||
inline int32 _GetMinimalPriority() const;
|
|
||||||
|
|
||||||
void _ComputeEffectivePriority() 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,
|
static bigtime_t _ScaleQuantum(bigtime_t maxQuantum,
|
||||||
bigtime_t minQuantum, int32 maxPriority,
|
bigtime_t minQuantum, int32 maxPriority,
|
||||||
int32 minPriority, int32 priority);
|
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
|
inline bool
|
||||||
ThreadData::HasCacheExpired() const
|
ThreadData::HasCacheExpired() const
|
||||||
{
|
{
|
||||||
@@ -259,6 +281,7 @@ ThreadData::Enqueue()
|
|||||||
SCHEDULER_ENTER_FUNCTION();
|
SCHEDULER_ENTER_FUNCTION();
|
||||||
|
|
||||||
fThread->state = B_THREAD_READY;
|
fThread->state = B_THREAD_READY;
|
||||||
|
|
||||||
ComputeLoad();
|
ComputeLoad();
|
||||||
fWentSleepCount = 0;
|
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
|
} // namespace Scheduler
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user