[*] Work on AuConditionVariable.NT some more

[*] Fix high cpu regression in 6af9940b
This commit is contained in:
Reece Wilson 2023-05-30 12:46:38 +01:00
parent b60b580d62
commit 53df1ee81d
2 changed files with 40 additions and 28 deletions

View File

@ -360,29 +360,29 @@ namespace Aurora::Async
{
if (this->sortedWork[i].size())
{
return true;
return false;
}
}
return false;
return true;
}
bool GroupWorkQueue::IsEmpty(AuWorkerId_t id)
{
AU_LOCK_GUARD(this->mutex);
for (AU_ITERATE_N(i, AuAsync::kEWorkPrioCount))
{
for (const auto &[srcId, pA] : this->sortedWork[i])
{
if (id == srcId)
{
return true;
return false;
}
}
}
return false;
return true;
}
void GroupWorkQueue::Dequeue(AuList<WorkEntry_t> &queue, int maxPopCount, AuAsync::ThreadId_t id)
@ -590,7 +590,6 @@ namespace Aurora::Async
state->pendingWorkItems.clear();
}
// Account for
// while (AuAsync.GetCurrentPool()->runForever());
// in the top most task

View File

@ -70,15 +70,12 @@ namespace Aurora::Threading::Primitives
LARGE_INTEGER word;
word.QuadPart = uTargetTimeNt;
// forced smp stall
// forced smt stall
// see the "hopefully nt is smart enough" comment
if (!bIOU)
{
bIOU = DoTryIf([=]()
{
bool b = true;
return CheckOut(b);
});
bool b = true;
bIOU = CheckOut(b);
}
if (bRet)
@ -87,14 +84,14 @@ namespace Aurora::Threading::Primitives
{
auto uNow = this->wlist;
auto waiting = uNow >> 2u;
auto uNext = ((waiting + 1) << 2u) | 1;
auto uNext = ((waiting + 1) << 2u) | (!bool(waiting)) | (uNow & 1);
if (AuAtomicCompareExchange(&this->wlist, uNext, uNow) == uNow)
{
break;
}
}
bRet = pNtWaitForKeyedEvent(gKeyedEventHandle, &this->wlist, 0, &word) != NTSTATUS_TIMEOUT;
}
else /* unblock NtReleaseKeyedEvent after an atomic this->wlist change <-> NtReleaseKeyedEvent race condition. */
@ -162,28 +159,29 @@ namespace Aurora::Threading::Primitives
}
else
{
bool bIOU {};
while (true)
{
while (true)
{
auto uNow = this->wlist;
auto waiting = uNow >> 2u;
auto uNext = ((waiting + 1) << 2u) | 1;
auto uNext = ((waiting + 1) << 2u) | (!bool(waiting)) | (uNow & 1);
if (AuAtomicCompareExchange(&this->wlist, uNext, uNow) == uNow)
{
break;
}
}
// forced smp stall
bool bIOU = DoTryIf([=]()
if (!bIOU)
{
bool b = true;
return CheckOut(b);
});
bIOU = CheckOut(b);
}
// then into the kernel no matter what (hopefully nt is smart enough to have a fast path)
// then into the kernel no matter what (hopefully nt is smart enough to have a fast path)
pNtWaitForKeyedEvent(gKeyedEventHandle, &this->wlist, 0, nullptr);
if (bIOU || CheckOut(bRet))
@ -246,7 +244,19 @@ namespace Aurora::Threading::Primitives
return false;
}
return AuAtomicCompareExchange(&this->signalCount, uSignalNow - 1, uSignalNow) == uSignalNow;
auto uSignalNext = uSignalNow - 1;
if (AuAtomicCompareExchange(&this->signalCount, uSignalNext, uSignalNow) != uSignalNow)
{
return false;
}
if (uSignalNext == 0)
{
InterlockedOr((volatile LONG*)&this->wlist, 1);
}
return true;
});
#endif
}
@ -290,17 +300,20 @@ namespace Aurora::Threading::Primitives
while (expected && uBroadcastIterations)
{
if (AuAtomicCompareExchange(&this->wlist, ((expected - 1) << 2) /*intentional clear*/, original) == original)
AuAtomicAdd(&this->signalCount, 1u);
while (expected && uBroadcastIterations)
{
AuAtomicAdd(&this->signalCount, 1u);
if (AuAtomicCompareExchange(&this->wlist, ((expected - 1) << 2) /*intentional clear*/, original) == original)
{
pNtReleaseKeyedEvent(gKeyedEventHandle, &this->wlist, FALSE, nullptr);
pNtReleaseKeyedEvent(gKeyedEventHandle, &this->wlist, FALSE, nullptr);
uBroadcastIterations--;
}
uBroadcastIterations--;
original = this->wlist;
expected = original >> 2;
}
original = this->wlist;
expected = original >> 2;
}
#else
::WakeAllConditionVariable(&this->winCond_);