scheduler: Always protect gCore[High]LoadHeap with spinlock

Should fix #10628. If there is a race condition with a writer getting
minimum or maximum from double ended heap may incorrectly result NULL.
Which is not expected in the most of the thread migration logic. Apart
from that, because of the race condition heap state may be observed as
inconsistent thus failing assertions.
ended heap
This commit is contained in:
Pawel Dziepak 2014-03-06 01:13:31 +01:00
parent 198fd05030
commit 1700e825b1
2 changed files with 15 additions and 15 deletions

View File

@ -87,29 +87,26 @@ should_rebalance(const ThreadData* threadData)
int32 coreNewLoad = coreLoad - threadLoad;
// If there is high load on this core but this thread does not contribute
// significantly consider giving it to someone less busy.
if (coreLoad > kHighLoad) {
CoreEntry* other = gCoreLoadHeap.PeekMinimum();
if (other != NULL) {
int32 otherNewLoad = other->GetLoad() + threadLoad;
if (coreNewLoad - otherNewLoad >= kLoadDifference)
return true;
}
}
// No cpu bound threads - the situation is quite good. Make sure it
// won't get much worse...
ReadSpinLocker coreLocker(gCoreHeapsLock);
CoreEntry* other = gCoreLoadHeap.PeekMinimum();
if (other == NULL)
other = gCoreHighLoadHeap.PeekMinimum();
coreLocker.Unlock();
ASSERT(other != NULL);
int32 otherNewLoad = other->GetLoad() + threadLoad;
// If there is high load on this core but this thread does not contribute
// significantly consider giving it to someone less busy.
if (coreLoad > kHighLoad) {
if (coreNewLoad - otherNewLoad >= kLoadDifference)
return true;
}
// No cpu bound threads - the situation is quite good. Make sure it
// won't get much worse...
if (other->GetLoad() == 0 && coreNewLoad != 0)
return true;
int32 otherNewLoad = other->GetLoad() + threadLoad;
return coreNewLoad - otherNewLoad >= kLoadDifference * 2;
}

View File

@ -52,6 +52,7 @@ choose_small_task_core()
{
SCHEDULER_ENTER_FUNCTION();
ReadSpinLocker coreLocker(gCoreHeapsLock);
CoreEntry* core = gCoreLoadHeap.PeekMaximum();
if (core == NULL)
return sSmallTaskCore;
@ -137,9 +138,11 @@ should_rebalance(const ThreadData* threadData)
if (threadLoad >= coreLoad / 2)
return false;
ReadSpinLocker coreLocker(gCoreHeapsLock);
CoreEntry* other = gCoreLoadHeap.PeekMaximum();
if (other == NULL)
other = gCoreHighLoadHeap.PeekMinimum();
coreLocker.Unlock();
ASSERT(other != NULL);
int32 coreNewLoad = coreLoad - threadLoad;