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

View File

@ -70,15 +70,12 @@ namespace Aurora::Threading::Primitives
LARGE_INTEGER word; LARGE_INTEGER word;
word.QuadPart = uTargetTimeNt; word.QuadPart = uTargetTimeNt;
// forced smp stall // forced smt stall
// see the "hopefully nt is smart enough" comment // see the "hopefully nt is smart enough" comment
if (!bIOU) if (!bIOU)
{ {
bIOU = DoTryIf([=]() bool b = true;
{ bIOU = CheckOut(b);
bool b = true;
return CheckOut(b);
});
} }
if (bRet) if (bRet)
@ -87,14 +84,14 @@ namespace Aurora::Threading::Primitives
{ {
auto uNow = this->wlist; auto uNow = this->wlist;
auto waiting = uNow >> 2u; 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) if (AuAtomicCompareExchange(&this->wlist, uNext, uNow) == uNow)
{ {
break; break;
} }
} }
bRet = pNtWaitForKeyedEvent(gKeyedEventHandle, &this->wlist, 0, &word) != NTSTATUS_TIMEOUT; bRet = pNtWaitForKeyedEvent(gKeyedEventHandle, &this->wlist, 0, &word) != NTSTATUS_TIMEOUT;
} }
else /* unblock NtReleaseKeyedEvent after an atomic this->wlist change <-> NtReleaseKeyedEvent race condition. */ else /* unblock NtReleaseKeyedEvent after an atomic this->wlist change <-> NtReleaseKeyedEvent race condition. */
@ -162,28 +159,29 @@ namespace Aurora::Threading::Primitives
} }
else else
{ {
bool bIOU {};
while (true) while (true)
{ {
while (true) while (true)
{ {
auto uNow = this->wlist; auto uNow = this->wlist;
auto waiting = uNow >> 2u; 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) if (AuAtomicCompareExchange(&this->wlist, uNext, uNow) == uNow)
{ {
break; break;
} }
} }
// forced smp stall // forced smp stall
bool bIOU = DoTryIf([=]() if (!bIOU)
{ {
bool b = true; 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); pNtWaitForKeyedEvent(gKeyedEventHandle, &this->wlist, 0, nullptr);
if (bIOU || CheckOut(bRet)) if (bIOU || CheckOut(bRet))
@ -246,7 +244,19 @@ namespace Aurora::Threading::Primitives
return false; 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 #endif
} }
@ -290,17 +300,20 @@ namespace Aurora::Threading::Primitives
while (expected && uBroadcastIterations) 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 #else
::WakeAllConditionVariable(&this->winCond_); ::WakeAllConditionVariable(&this->winCond_);