scheduler: Improve thread creation performance
This commit is contained in:
@@ -383,7 +383,7 @@ reschedule(int32 nextState)
|
|||||||
|
|
||||||
int32 thisCPU = smp_get_current_cpu();
|
int32 thisCPU = smp_get_current_cpu();
|
||||||
|
|
||||||
CPUEntry* cpu = &gCPUEntries[thisCPU];
|
CPUEntry* cpu = CPUEntry::GetCPU(thisCPU);
|
||||||
CoreEntry* core = CoreEntry::GetCore(thisCPU);
|
CoreEntry* core = CoreEntry::GetCore(thisCPU);
|
||||||
|
|
||||||
TRACE("reschedule(): cpu %ld, current thread = %ld\n", thisCPU,
|
TRACE("reschedule(): cpu %ld, current thread = %ld\n", thisCPU,
|
||||||
|
|||||||
@@ -123,6 +123,14 @@ CPUEntry::Remove(ThreadData* thread)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline ThreadData*
|
||||||
|
CoreEntry::PeekThread() const
|
||||||
|
{
|
||||||
|
SCHEDULER_ENTER_FUNCTION();
|
||||||
|
return fRunQueue.PeekMaximum();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
inline ThreadData*
|
inline ThreadData*
|
||||||
CPUEntry::PeekThread() const
|
CPUEntry::PeekThread() const
|
||||||
{
|
{
|
||||||
@@ -152,6 +160,9 @@ CPUEntry::UpdatePriority(int32 priority)
|
|||||||
return;
|
return;
|
||||||
fCore->CPUHeap()->ModifyKey(this, priority);
|
fCore->CPUHeap()->ModifyKey(this, priority);
|
||||||
|
|
||||||
|
if (gSingleCore)
|
||||||
|
return;
|
||||||
|
|
||||||
if (oldPriority == B_IDLE_PRIORITY)
|
if (oldPriority == B_IDLE_PRIORITY)
|
||||||
fCore->CPUWakesUp(this);
|
fCore->CPUWakesUp(this);
|
||||||
else if (priority == B_IDLE_PRIORITY)
|
else if (priority == B_IDLE_PRIORITY)
|
||||||
@@ -164,6 +175,7 @@ CPUEntry::ComputeLoad()
|
|||||||
{
|
{
|
||||||
SCHEDULER_ENTER_FUNCTION();
|
SCHEDULER_ENTER_FUNCTION();
|
||||||
|
|
||||||
|
ASSERT(gTrackLoad);
|
||||||
ASSERT(fCPUNumber == smp_get_current_cpu());
|
ASSERT(fCPUNumber == smp_get_current_cpu());
|
||||||
|
|
||||||
int oldLoad = compute_load(fMeasureTime, fMeasureActiveTime, fLoad);
|
int oldLoad = compute_load(fMeasureTime, fMeasureActiveTime, fLoad);
|
||||||
@@ -244,10 +256,12 @@ CPUEntry::TrackActivity(ThreadData* oldThreadData, ThreadData* nextThreadData)
|
|||||||
oldThreadData->UpdateActivity(active);
|
oldThreadData->UpdateActivity(active);
|
||||||
}
|
}
|
||||||
|
|
||||||
oldThreadData->ComputeLoad();
|
if (gTrackLoad) {
|
||||||
nextThreadData->ComputeLoad();
|
oldThreadData->ComputeLoad();
|
||||||
if (gTrackLoad && !cpuEntry->disabled)
|
nextThreadData->ComputeLoad();
|
||||||
ComputeLoad();
|
if (!cpuEntry->disabled)
|
||||||
|
ComputeLoad();
|
||||||
|
}
|
||||||
|
|
||||||
Thread* nextThread = nextThreadData->GetThread();
|
Thread* nextThread = nextThreadData->GetThread();
|
||||||
if (!thread_is_idle_thread(nextThread)) {
|
if (!thread_is_idle_thread(nextThread)) {
|
||||||
@@ -256,19 +270,17 @@ CPUEntry::TrackActivity(ThreadData* oldThreadData, ThreadData* nextThreadData)
|
|||||||
|
|
||||||
nextThreadData->SetLastInterruptTime(cpuEntry->interrupt_time);
|
nextThreadData->SetLastInterruptTime(cpuEntry->interrupt_time);
|
||||||
|
|
||||||
|
if (gCPUFrequencyManagement)
|
||||||
_RequestPerformanceLevel(nextThreadData);
|
_RequestPerformanceLevel(nextThreadData);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
inline void
|
void
|
||||||
CPUEntry::_RequestPerformanceLevel(ThreadData* threadData)
|
CPUEntry::_RequestPerformanceLevel(ThreadData* threadData)
|
||||||
{
|
{
|
||||||
SCHEDULER_ENTER_FUNCTION();
|
SCHEDULER_ENTER_FUNCTION();
|
||||||
|
|
||||||
if (!gCPUFrequencyManagement)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (gCPU[fCPUNumber].disabled) {
|
if (gCPU[fCPUNumber].disabled) {
|
||||||
decrease_cpu_performance(kCPUPerformanceScaleMax);
|
decrease_cpu_performance(kCPUPerformanceScaleMax);
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -112,7 +112,6 @@ public:
|
|||||||
void Dump();
|
void Dump();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class CoreEntry : public MinMaxHeapLinkImpl<CoreEntry, int32>,
|
class CoreEntry : public MinMaxHeapLinkImpl<CoreEntry, int32>,
|
||||||
public DoublyLinkedListLinkImpl<CoreEntry> {
|
public DoublyLinkedListLinkImpl<CoreEntry> {
|
||||||
public:
|
public:
|
||||||
@@ -190,7 +189,6 @@ private:
|
|||||||
friend class DebugDumper;
|
friend class DebugDumper;
|
||||||
} CACHE_LINE_ALIGN;
|
} CACHE_LINE_ALIGN;
|
||||||
|
|
||||||
|
|
||||||
class CoreLoadHeap : public MinMaxHeap<CoreEntry, int32> {
|
class CoreLoadHeap : public MinMaxHeap<CoreEntry, int32> {
|
||||||
public:
|
public:
|
||||||
CoreLoadHeap() { }
|
CoreLoadHeap() { }
|
||||||
@@ -356,14 +354,6 @@ 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
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -12,6 +12,28 @@ using namespace Scheduler;
|
|||||||
static bigtime_t sQuantumLengths[THREAD_MAX_SET_PRIORITY + 1];
|
static bigtime_t sQuantumLengths[THREAD_MAX_SET_PRIORITY + 1];
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
ThreadData::_InitBase()
|
||||||
|
{
|
||||||
|
fPriorityPenalty = 0;
|
||||||
|
fAdditionalPenalty = 0;
|
||||||
|
fEffectivePriority = fThread->priority;
|
||||||
|
|
||||||
|
fTimeLeft = 0;
|
||||||
|
fStolenTime = 0;
|
||||||
|
|
||||||
|
fMeasureActiveTime = 0;
|
||||||
|
fMeasureTime = 0;
|
||||||
|
fLoad = 0;
|
||||||
|
|
||||||
|
fWentSleep = 0;
|
||||||
|
fWentSleepActive = 0;
|
||||||
|
fWentSleepCount = -1;
|
||||||
|
|
||||||
|
fEnqueued = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
inline CoreEntry*
|
inline CoreEntry*
|
||||||
ThreadData::_ChooseCore() const
|
ThreadData::_ChooseCore() const
|
||||||
{
|
{
|
||||||
@@ -30,7 +52,8 @@ ThreadData::_ChooseCPU(CoreEntry* core, bool& rescheduleNeeded) const
|
|||||||
int32 threadPriority = GetEffectivePriority();
|
int32 threadPriority = GetEffectivePriority();
|
||||||
|
|
||||||
if (fThread->previous_cpu != NULL) {
|
if (fThread->previous_cpu != NULL) {
|
||||||
CPUEntry* previousCPU = &gCPUEntries[fThread->previous_cpu->cpu_num];
|
CPUEntry* previousCPU
|
||||||
|
= CPUEntry::GetCPU(fThread->previous_cpu->cpu_num);
|
||||||
if (previousCPU->Core() == core && !fThread->previous_cpu->disabled) {
|
if (previousCPU->Core() == core && !fThread->previous_cpu->disabled) {
|
||||||
CoreCPUHeapLocker _(core);
|
CoreCPUHeapLocker _(core);
|
||||||
if (CPUPriorityHeap::GetKey(previousCPU) < threadPriority) {
|
if (CPUPriorityHeap::GetKey(previousCPU) < threadPriority) {
|
||||||
@@ -74,48 +97,18 @@ ThreadData::ThreadData(Thread* thread)
|
|||||||
void
|
void
|
||||||
ThreadData::Init()
|
ThreadData::Init()
|
||||||
{
|
{
|
||||||
fAdditionalPenalty = 0;
|
_InitBase();
|
||||||
fEffectivePriority = -1;
|
|
||||||
|
|
||||||
fTimeLeft = 0;
|
ThreadData* currentThreadData = thread_get_current_thread()->scheduler_data;
|
||||||
fStolenTime = 0;
|
fCore = currentThreadData->fCore;
|
||||||
|
|
||||||
fMeasureActiveTime = 0;
|
|
||||||
fMeasureTime = 0;
|
|
||||||
fLoad = 0;
|
|
||||||
|
|
||||||
fWentSleep = 0;
|
|
||||||
fWentSleepActive = 0;
|
|
||||||
fWentSleepCount = -1;
|
|
||||||
|
|
||||||
fEnqueued = false;
|
|
||||||
|
|
||||||
Thread* currentThread = thread_get_current_thread();
|
|
||||||
ASSERT(currentThread != NULL);
|
|
||||||
if (!thread_is_idle_thread(currentThread)) {
|
|
||||||
ThreadData* currentThreadData = currentThread->scheduler_data;
|
|
||||||
int32 penalty = currentThreadData->fPriorityPenalty;
|
|
||||||
|
|
||||||
int32 minimalPriority = _GetMinimalPriority();
|
|
||||||
if (fThread->priority - penalty >= minimalPriority)
|
|
||||||
fPriorityPenalty = penalty;
|
|
||||||
else
|
|
||||||
fPriorityPenalty = fThread->priority - minimalPriority;
|
|
||||||
|
|
||||||
fCore = currentThreadData->fCore;
|
|
||||||
} else {
|
|
||||||
fPriorityPenalty = 0;
|
|
||||||
fAdditionalPenalty = 0;
|
|
||||||
|
|
||||||
fCore = NULL;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
ThreadData::Init(CoreEntry* core)
|
ThreadData::Init(CoreEntry* core)
|
||||||
{
|
{
|
||||||
Init();
|
_InitBase();
|
||||||
|
|
||||||
fCore = core;
|
fCore = core;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -172,8 +165,7 @@ ThreadData::ComputeLoad()
|
|||||||
{
|
{
|
||||||
SCHEDULER_ENTER_FUNCTION();
|
SCHEDULER_ENTER_FUNCTION();
|
||||||
|
|
||||||
if (!gTrackLoad)
|
ASSERT(gTrackLoad);
|
||||||
return;
|
|
||||||
|
|
||||||
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;
|
||||||
|
|||||||
@@ -165,9 +165,6 @@ inline int32
|
|||||||
ThreadData::GetEffectivePriority() const
|
ThreadData::GetEffectivePriority() const
|
||||||
{
|
{
|
||||||
SCHEDULER_ENTER_FUNCTION();
|
SCHEDULER_ENTER_FUNCTION();
|
||||||
|
|
||||||
if (fEffectivePriority == -1)
|
|
||||||
_ComputeEffectivePriority();
|
|
||||||
return fEffectivePriority;
|
return fEffectivePriority;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -184,7 +181,6 @@ ThreadData::IncreasePenalty()
|
|||||||
|
|
||||||
TRACE("increasing thread %ld penalty\n", fThread->id);
|
TRACE("increasing thread %ld penalty\n", fThread->id);
|
||||||
|
|
||||||
fEffectivePriority = -1;
|
|
||||||
int32 oldPenalty = fPriorityPenalty++;
|
int32 oldPenalty = fPriorityPenalty++;
|
||||||
|
|
||||||
ASSERT(fThread->priority - oldPenalty >= B_LOWEST_ACTIVE_PRIORITY);
|
ASSERT(fThread->priority - oldPenalty >= B_LOWEST_ACTIVE_PRIORITY);
|
||||||
@@ -194,6 +190,8 @@ ThreadData::IncreasePenalty()
|
|||||||
fPriorityPenalty = oldPenalty;
|
fPriorityPenalty = oldPenalty;
|
||||||
fAdditionalPenalty++;
|
fAdditionalPenalty++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_ComputeEffectivePriority();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -202,13 +200,15 @@ ThreadData::CancelPenalty()
|
|||||||
{
|
{
|
||||||
SCHEDULER_ENTER_FUNCTION();
|
SCHEDULER_ENTER_FUNCTION();
|
||||||
|
|
||||||
if (fPriorityPenalty != 0) {
|
int32 oldPenalty = fPriorityPenalty;
|
||||||
TRACE("cancelling thread %ld penalty\n", fThread->id);
|
|
||||||
fEffectivePriority = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
fAdditionalPenalty = 0;
|
fAdditionalPenalty = 0;
|
||||||
fPriorityPenalty = 0;
|
fPriorityPenalty = 0;
|
||||||
|
|
||||||
|
if (oldPenalty != 0) {
|
||||||
|
TRACE("cancelling thread %ld penalty\n", fThread->id);
|
||||||
|
_ComputeEffectivePriority();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -217,7 +217,7 @@ ThreadData::ShouldCancelPenalty() const
|
|||||||
{
|
{
|
||||||
SCHEDULER_ENTER_FUNCTION();
|
SCHEDULER_ENTER_FUNCTION();
|
||||||
|
|
||||||
if (fCore == NULL || fWentSleep == 0)
|
if (fCore == NULL)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return fCore->StarvationCounter() != fWentSleepCount
|
return fCore->StarvationCounter() != fWentSleepCount
|
||||||
@@ -251,7 +251,8 @@ ThreadData::PutBack()
|
|||||||
{
|
{
|
||||||
SCHEDULER_ENTER_FUNCTION();
|
SCHEDULER_ENTER_FUNCTION();
|
||||||
|
|
||||||
ComputeLoad();
|
if (gTrackLoad)
|
||||||
|
ComputeLoad();
|
||||||
fWentSleepCount = -1;
|
fWentSleepCount = -1;
|
||||||
|
|
||||||
int32 priority = GetEffectivePriority();
|
int32 priority = GetEffectivePriority();
|
||||||
@@ -282,7 +283,8 @@ ThreadData::Enqueue()
|
|||||||
|
|
||||||
fThread->state = B_THREAD_READY;
|
fThread->state = B_THREAD_READY;
|
||||||
|
|
||||||
ComputeLoad();
|
if (gTrackLoad)
|
||||||
|
ComputeLoad();
|
||||||
fWentSleepCount = 0;
|
fWentSleepCount = 0;
|
||||||
|
|
||||||
int32 priority = GetEffectivePriority();
|
int32 priority = GetEffectivePriority();
|
||||||
|
|||||||
Reference in New Issue
Block a user