[*] Fix abnormal ::UnlockWrite performance under heavyweight native WaitOnAddress platforms (Linux, BSD-like, etc)

This commit is contained in:
Reece Wilson 2023-09-18 18:21:46 +01:00
parent 5d12f1a203
commit 7357764cfc
2 changed files with 48 additions and 29 deletions

View File

@ -150,15 +150,25 @@ namespace Aurora::Threading::Primitives
return (AuUInt32 *)this->conditionVariableWriter_;
}
template<bool bIsWriteRecursionAllowed>
AuUInt32 *RWLockImpl<bIsWriteRecursionAllowed>::GetReadSleepCounter()
{
return (AuUInt32 *)this->conditionVariable_;
}
template<bool bIsWriteRecursionAllowed>
bool RWLockImpl<bIsWriteRecursionAllowed>::LockReadNSAbs(AuUInt64 uTimeout)
{
AuInt32 iCurState {};
bool bRet {};
if (this->TryLockRead())
{
return true;
}
AuInt32 iCurState {};
auto pCounter = this->GetReadSleepCounter();
do
{
iCurState = this->state_;
@ -167,7 +177,11 @@ namespace Aurora::Threading::Primitives
{
if (gUseFutexRWLock)
{
if (!InternalLTSWaitOnAddressHighRes((const void *)&this->state_, &iCurState, sizeof(iCurState), uTimeout))
AuAtomicAdd(pCounter, 1u);
bRet = InternalLTSWaitOnAddressHighRes((const void *)&this->state_, &iCurState, sizeof(iCurState), uTimeout);
AuAtomicSub(pCounter, 1u);
if (!bRet)
{
return false;
}
@ -212,6 +226,9 @@ namespace Aurora::Threading::Primitives
template<bool bIsWriteRecursionAllowed>
bool RWLockImpl<bIsWriteRecursionAllowed>::LockReadNS(AuUInt64 uTimeout)
{
AuInt32 iCurState {};
bool bRet {};
if (this->TryLockReadNoSpin<true>())
{
return true;
@ -224,7 +241,8 @@ namespace Aurora::Threading::Primitives
return true;
}
AuInt32 iCurState {};
auto pCounter = this->GetReadSleepCounter();
do
{
iCurState = this->state_;
@ -233,7 +251,11 @@ namespace Aurora::Threading::Primitives
{
if (gUseFutexRWLock)
{
if (!InternalLTSWaitOnAddressHighRes((const void *)&this->state_, &iCurState, sizeof(iCurState), uEndTime))
AuAtomicAdd(pCounter, 1u);
bRet = InternalLTSWaitOnAddressHighRes((const void *)&this->state_, &iCurState, sizeof(iCurState), uEndTime);
AuAtomicSub(pCounter, 1u);
if (!bRet)
{
return false;
}
@ -331,6 +353,9 @@ namespace Aurora::Threading::Primitives
bool RWLockImpl<bIsWriteRecursionAllowed>::LockWriteNSAbsSecondPath()
{
auto uOld = this->state_;
if constexpr (bIsWriteRecursionAllowed)
{
if (uOld < 0)
{
if (this->reentrantWriteLockHandle_ == GetThreadCookie())
@ -339,7 +364,9 @@ namespace Aurora::Threading::Primitives
return true;
}
}
else if (uOld == 0)
}
if (uOld == 0)
{
if (AuAtomicCompareExchange(&this->state_, -1, uOld) == uOld)
{
@ -354,6 +381,9 @@ namespace Aurora::Threading::Primitives
template<bool bIsWriteRecursionAllowed>
bool RWLockImpl<bIsWriteRecursionAllowed>::LockWriteNS(AuUInt64 uTimeout)
{
bool bRet {};
AuInt64 uEndTime {};
if constexpr (!bIsWriteRecursionAllowed)
{
if (this->TryLockWrite())
@ -363,27 +393,12 @@ namespace Aurora::Threading::Primitives
}
else
{
auto uOld = AuAtomicLoad(&this->state_);
if (uOld < 0)
if (this->LockWriteNSAbsSecondPath())
{
if (this->reentrantWriteLockHandle_ == GetThreadCookie())
{
AuAtomicSub(&this->state_, 1);
return true;
}
}
else if (uOld == 0)
{
if (AuAtomicCompareExchange(&this->state_, -1, uOld) == uOld)
{
this->reentrantWriteLockHandle_ = GetThreadCookie();
return true;
}
}
}
bool bRet {};
AuInt64 uEndTime {};
AuAtomicAdd(&this->writersPending_, 1);
if (gUseFutexRWLock)
@ -411,17 +426,17 @@ namespace Aurora::Threading::Primitives
{
while (true)
{
bool bStatus {};
AuInt32 iCurState;
while ((iCurState = AuAtomicLoad(&this->state_)) != 0)
{
AuInt64 uSecondTimeout = 0;
bool bStatus {};
if (gUseFutexRWLock)
{
auto pSemaphore = this->GetFutexConditionWriter();
AuInt32 iCurState;
while ((iCurState = AuAtomicLoad(&this->state_)) != 0)
{
static const AuUInt32 kExpect { 0 };
@ -531,9 +546,12 @@ namespace Aurora::Threading::Primitives
void RWLockImpl<bIsWriteRecursionAllowed>::SignalManyReader()
{
if (gUseFutexRWLock)
{
if (AuAtomicLoad(this->GetReadSleepCounter()))
{
InternalLTSWakeAll((const void *)&this->state_);
}
}
else
{
this->GetCondition().Broadcast();

View File

@ -97,6 +97,7 @@ namespace Aurora::Threading::Primitives
auline void SignalManyReader();
auline void SignalManyWriter(int iBias = 0);
auline AuUInt32 *GetReadSleepCounter();
private:
RWLockAccessView<true, RWLockImpl> read_;