kernel/scheduler: Properly handle thread masks not being set.
There was a missing case in reschedule(). Also fix a copy/paste error in the power_saving logic. This also slightly optimizes things by having an unset CPU mask turn into a boolean and be processed separately, avoiding loops and masks entirely in that case. Have CPU masks be unset by default for new threads, while at it. Change-Id: Ic5d000a72839448a2d025cfc99de1ed49c841852 Reviewed-on: https://review.haiku-os.org/c/haiku/+/7900 Reviewed-by: waddlesplash <[email protected]>
This commit is contained in:
committed by
waddlesplash
parent
05c46731b8
commit
37df18e183
@@ -57,15 +57,13 @@ choose_core(const ThreadData* threadData)
|
||||
|
||||
int32 index = 0;
|
||||
CPUSet mask = threadData->GetCPUMask();
|
||||
if (mask.IsEmpty()) {
|
||||
// ignore when empty
|
||||
mask.SetAll();
|
||||
}
|
||||
const bool useMask = !mask.IsEmpty();
|
||||
|
||||
CoreEntry* core = NULL;
|
||||
if (package != NULL) {
|
||||
do {
|
||||
core = package->GetIdleCore(index++);
|
||||
} while (core != NULL && !core->CPUMask().Matches(mask));
|
||||
} while (useMask && core != NULL && !core->CPUMask().Matches(mask));
|
||||
}
|
||||
if (core == NULL) {
|
||||
ReadSpinLocker coreLocker(gCoreHeapsLock);
|
||||
@@ -73,12 +71,12 @@ choose_core(const ThreadData* threadData)
|
||||
// no idle cores, use least occupied core
|
||||
do {
|
||||
core = gCoreLoadHeap.PeekMinimum(index++);
|
||||
} while (core != NULL && !core->CPUMask().Matches(mask));
|
||||
} while (useMask && core != NULL && !core->CPUMask().Matches(mask));
|
||||
if (core == NULL) {
|
||||
index = 0;
|
||||
do {
|
||||
core = gCoreHighLoadHeap.PeekMinimum(index++);
|
||||
} while (core != NULL && !core->CPUMask().Matches(mask));
|
||||
} while (useMask && core != NULL && !core->CPUMask().Matches(mask));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -98,23 +96,21 @@ rebalance(const ThreadData* threadData)
|
||||
// Get the least loaded core.
|
||||
ReadSpinLocker coreLocker(gCoreHeapsLock);
|
||||
CPUSet mask = threadData->GetCPUMask();
|
||||
if (mask.IsEmpty()) {
|
||||
// ignore when empty
|
||||
mask.SetAll();
|
||||
}
|
||||
const bool useMask = !mask.IsEmpty();
|
||||
|
||||
int32 index = 0;
|
||||
CoreEntry* other;
|
||||
do {
|
||||
other = gCoreLoadHeap.PeekMinimum(index++);
|
||||
if (other != NULL && other->CPUMask().IsEmpty())
|
||||
if (other != NULL && (useMask && other->CPUMask().IsEmpty()))
|
||||
panic("other->CPUMask().IsEmpty()\n");
|
||||
} while (other != NULL && !other->CPUMask().Matches(mask));
|
||||
} while (useMask && other != NULL && !other->CPUMask().Matches(mask));
|
||||
|
||||
if (other == NULL) {
|
||||
index = 0;
|
||||
do {
|
||||
other = gCoreHighLoadHeap.PeekMinimum(index++);
|
||||
} while (other != NULL && !other->CPUMask().Matches(mask));
|
||||
} while (useMask && other != NULL && !other->CPUMask().Matches(mask));
|
||||
}
|
||||
coreLocker.Unlock();
|
||||
ASSERT(other != NULL);
|
||||
|
||||
@@ -89,14 +89,11 @@ choose_core(const ThreadData* threadData)
|
||||
CoreEntry* core = NULL;
|
||||
|
||||
CPUSet mask = threadData->GetCPUMask();
|
||||
if (mask.IsEmpty()) {
|
||||
// ignore when empty
|
||||
mask.SetAll();
|
||||
}
|
||||
const bool useMask = !mask.IsEmpty();
|
||||
|
||||
// try to pack all threads on one core
|
||||
core = choose_small_task_core();
|
||||
if (core != NULL && !core->CPUMask().Matches(mask))
|
||||
if (core != NULL && (useMask && !core->CPUMask().Matches(mask)))
|
||||
core = NULL;
|
||||
|
||||
if (core == NULL || core->GetLoad() + threadData->GetLoad() >= kHighLoad) {
|
||||
@@ -106,12 +103,12 @@ choose_core(const ThreadData* threadData)
|
||||
int32 index = 0;
|
||||
do {
|
||||
core = gCoreLoadHeap.PeekMinimum(index++);
|
||||
} while (core != NULL && !core->CPUMask().Matches(mask));
|
||||
} while (useMask && core != NULL && !core->CPUMask().Matches(mask));
|
||||
if (core == NULL) {
|
||||
coreLocker.Unlock();
|
||||
|
||||
core = choose_idle_core();
|
||||
if (!core->CPUMask().Matches(mask))
|
||||
if (useMask && !core->CPUMask().Matches(mask))
|
||||
core = NULL;
|
||||
|
||||
if (core == NULL) {
|
||||
@@ -119,7 +116,7 @@ choose_core(const ThreadData* threadData)
|
||||
index = 0;
|
||||
do {
|
||||
core = gCoreHighLoadHeap.PeekMinimum(index++);
|
||||
} while (core != NULL && !core->CPUMask().Matches(mask));
|
||||
} while (useMask && core != NULL && !core->CPUMask().Matches(mask));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -137,10 +134,8 @@ rebalance(const ThreadData* threadData)
|
||||
ASSERT(!gSingleCore);
|
||||
|
||||
CPUSet mask = threadData->GetCPUMask();
|
||||
if (mask.IsEmpty()) {
|
||||
// ignore when empty
|
||||
mask.SetAll();
|
||||
}
|
||||
const bool useMask = !mask.IsEmpty();
|
||||
|
||||
CoreEntry* core = threadData->Core();
|
||||
|
||||
int32 coreLoad = core->GetLoad();
|
||||
@@ -151,7 +146,7 @@ rebalance(const ThreadData* threadData)
|
||||
CoreEntry* smallTaskCore = choose_small_task_core();
|
||||
|
||||
if (threadLoad > coreLoad / 3 || smallTaskCore == NULL
|
||||
|| !smallTaskCore->CPUMask().Matches(mask)) {
|
||||
|| (useMask && !smallTaskCore->CPUMask().Matches(mask))) {
|
||||
return core;
|
||||
}
|
||||
return coreLoad > kVeryHighLoad ? smallTaskCore : core;
|
||||
@@ -165,12 +160,12 @@ rebalance(const ThreadData* threadData)
|
||||
int32 index = 0;
|
||||
do {
|
||||
other = gCoreLoadHeap.PeekMaximum(index++);
|
||||
} while (other != NULL && !core->CPUMask().Matches(mask));
|
||||
} while (useMask && other != NULL && !other->CPUMask().Matches(mask));
|
||||
if (other == NULL) {
|
||||
index = 0;
|
||||
do {
|
||||
other = gCoreHighLoadHeap.PeekMinimum(index++);
|
||||
} while (other != NULL && !core->CPUMask().Matches(mask));
|
||||
} while (useMask && other != NULL && !other->CPUMask().Matches(mask));
|
||||
}
|
||||
coreLocker.Unlock();
|
||||
ASSERT(other != NULL);
|
||||
@@ -184,7 +179,7 @@ rebalance(const ThreadData* threadData)
|
||||
return core;
|
||||
|
||||
CoreEntry* smallTaskCore = choose_small_task_core();
|
||||
if (smallTaskCore == NULL || !smallTaskCore->CPUMask().Matches(mask))
|
||||
if (smallTaskCore == NULL || (useMask && !smallTaskCore->CPUMask().Matches(mask)))
|
||||
return core;
|
||||
return smallTaskCore->GetLoad() + threadLoad < kHighLoad
|
||||
? smallTaskCore : core;
|
||||
|
||||
@@ -329,6 +329,9 @@ reschedule(int32 nextState)
|
||||
Thread* oldThread = thread_get_current_thread();
|
||||
ThreadData* oldThreadData = oldThread->scheduler_data;
|
||||
|
||||
CPUSet oldThreadMask;
|
||||
bool useOldThreadMask, fetchedOldThreadMask = false;
|
||||
|
||||
oldThreadData->StopCPUTime();
|
||||
|
||||
SchedulerModeLocker modeLocker;
|
||||
@@ -348,7 +351,11 @@ reschedule(int32 nextState)
|
||||
case B_THREAD_READY:
|
||||
enqueueOldThread = true;
|
||||
|
||||
if (!oldThreadData->IsIdle() && oldThreadData->GetCPUMask().GetBit(thisCPU)) {
|
||||
oldThreadMask = oldThreadData->GetCPUMask();
|
||||
useOldThreadMask = !oldThreadMask.IsEmpty();
|
||||
fetchedOldThreadMask = true;
|
||||
|
||||
if (!oldThreadData->IsIdle() && (!useOldThreadMask || oldThreadMask.GetBit(thisCPU))) {
|
||||
oldThreadData->Continues();
|
||||
if (oldThreadData->HasQuantumEnded(oldThread->cpu->preempted,
|
||||
oldThread->has_yielded)) {
|
||||
@@ -394,15 +401,19 @@ reschedule(int32 nextState)
|
||||
} else
|
||||
nextThreadData = oldThreadData;
|
||||
} else {
|
||||
CPUSet mask = oldThreadData->GetCPUMask();
|
||||
if (mask.IsEmpty())
|
||||
mask.SetAll();
|
||||
bool oldThreadShouldMigrate = !mask.GetBit(thisCPU);
|
||||
if (!fetchedOldThreadMask) {
|
||||
oldThreadMask = oldThreadData->GetCPUMask();
|
||||
useOldThreadMask = !oldThreadMask.IsEmpty();
|
||||
fetchedOldThreadMask = true;
|
||||
}
|
||||
bool oldThreadShouldMigrate = useOldThreadMask && !oldThreadMask.GetBit(thisCPU);
|
||||
if (oldThreadShouldMigrate)
|
||||
enqueueOldThread = false;
|
||||
|
||||
nextThreadData
|
||||
= cpu->ChooseNextThread(enqueueOldThread ? oldThreadData : NULL,
|
||||
putOldThreadAtBack);
|
||||
|
||||
if (oldThreadShouldMigrate) {
|
||||
enqueue(oldThread, true);
|
||||
// replace with the idle thread, if no other thread could be found
|
||||
|
||||
@@ -60,12 +60,11 @@ ThreadData::_ChooseCPU(CoreEntry* core, bool& rescheduleNeeded) const
|
||||
int32 threadPriority = GetEffectivePriority();
|
||||
|
||||
CPUSet mask = GetCPUMask();
|
||||
if (mask.IsEmpty())
|
||||
mask.SetAll();
|
||||
ASSERT(mask.Matches(core->CPUMask()));
|
||||
const bool useMask = !mask.IsEmpty();
|
||||
ASSERT(!useMask || mask.Matches(core->CPUMask()));
|
||||
|
||||
if (fThread->previous_cpu != NULL && !fThread->previous_cpu->disabled
|
||||
&& mask.GetBit(fThread->previous_cpu->cpu_num)) {
|
||||
&& (!useMask || mask.GetBit(fThread->previous_cpu->cpu_num))) {
|
||||
CPUEntry* previousCPU
|
||||
= CPUEntry::GetCPU(fThread->previous_cpu->cpu_num);
|
||||
if (previousCPU->Core() == core) {
|
||||
@@ -83,7 +82,7 @@ ThreadData::_ChooseCPU(CoreEntry* core, bool& rescheduleNeeded) const
|
||||
CPUEntry* cpu;
|
||||
do {
|
||||
cpu = core->CPUHeap()->PeekRoot(index++);
|
||||
} while (cpu != NULL && !mask.GetBit(cpu->ID()));
|
||||
} while (useMask && cpu != NULL && !mask.GetBit(cpu->ID()));
|
||||
ASSERT(cpu != NULL);
|
||||
|
||||
if (CPUPriorityHeap::GetKey(cpu) < threadPriority) {
|
||||
@@ -166,9 +165,12 @@ ThreadData::ChooseCoreAndCPU(CoreEntry*& targetCore, CPUEntry*& targetCPU)
|
||||
|
||||
bool rescheduleNeeded = false;
|
||||
|
||||
if (targetCore != NULL && !targetCore->CPUMask().Matches(GetCPUMask()))
|
||||
CPUSet mask = GetCPUMask();
|
||||
const bool useMask = !mask.IsEmpty();
|
||||
|
||||
if (targetCore != NULL && (useMask && !targetCore->CPUMask().Matches(mask)))
|
||||
targetCore = NULL;
|
||||
if (targetCPU != NULL && !GetCPUMask().GetBit(targetCPU->ID()))
|
||||
if (targetCPU != NULL && (useMask && !mask.GetBit(targetCPU->ID())))
|
||||
targetCPU = NULL;
|
||||
|
||||
if (targetCore == NULL && targetCPU != NULL)
|
||||
@@ -177,10 +179,7 @@ ThreadData::ChooseCoreAndCPU(CoreEntry*& targetCore, CPUEntry*& targetCPU)
|
||||
targetCPU = _ChooseCPU(targetCore, rescheduleNeeded);
|
||||
else if (targetCore == NULL && targetCPU == NULL) {
|
||||
targetCore = _ChooseCore();
|
||||
CPUSet mask = GetCPUMask();
|
||||
if (mask.IsEmpty())
|
||||
mask.SetAll();
|
||||
ASSERT(mask.Matches(targetCore->CPUMask()));
|
||||
ASSERT(!useMask || mask.Matches(targetCore->CPUMask()));
|
||||
targetCPU = _ChooseCPU(targetCore, rescheduleNeeded);
|
||||
}
|
||||
|
||||
|
||||
@@ -204,7 +204,6 @@ Thread::Thread(const char* name, thread_id threadID, struct cpu_ent* cpu)
|
||||
{
|
||||
id = threadID >= 0 ? threadID : allocate_thread_id();
|
||||
visible = false;
|
||||
cpumask.SetAll();
|
||||
|
||||
// init locks
|
||||
char lockName[32];
|
||||
@@ -2755,7 +2754,6 @@ thread_init(kernel_args *args)
|
||||
thread->team = team_get_kernel_team();
|
||||
thread->priority = B_IDLE_PRIORITY;
|
||||
thread->state = B_THREAD_RUNNING;
|
||||
thread->cpumask.SetAll();
|
||||
|
||||
sprintf(name, "idle thread %" B_PRIu32 " kstack", i + 1);
|
||||
thread->kernel_stack_area = find_area(name);
|
||||
|
||||
Reference in New Issue
Block a user