[*] Finally fixed an old regression: RWLock is back to being write-biased to prevent forever-read conditions

This commit is contained in:
Reece Wilson 2023-09-09 13:03:02 +01:00
parent 109b0cff3f
commit cea3362186
3 changed files with 24 additions and 10 deletions

View File

@ -382,6 +382,8 @@ namespace Aurora
AuUInt64 bWinXpThrough7BlazeOptimizerPower : 7 { 6 }; // dont worry about it. we dont care about old portables. lets try to make older win32 targets tweak the scheduling in our favor a bit.
AuUInt64 bPreferLinuxPrimitivesFutexNoSpin : 1 { false };
AuUInt64 bPreferUnixPrimitivesNoSpin : 1 { false };
AuUInt64 bAlwaysRWLockWriteBiasOnReadLock : 1 { false };
AuUInt64 bEnableRWLockWriteBiasOnReadLock : 1 { true };
};
struct DummyConfig

View File

@ -208,11 +208,11 @@ namespace Aurora::Threading::Primitives
return true;
}
template<bool bIsWriteRecursionAllowed>
bool RWLockImpl<bIsWriteRecursionAllowed>::LockReadNS(AuUInt64 uTimeout)
{
if (this->TryLockReadNoSpin())
if (this->TryLockReadNoSpin<true>())
{
return true;
}
@ -435,7 +435,7 @@ namespace Aurora::Threading::Primitives
if (AuAtomicLoad(&this->state_) == 1 &&
AuAtomicLoad(&this->writersPending_) > 1)
{
this->SignalManyWriter();
this->SignalManyWriter(-1);
}
}
@ -479,7 +479,7 @@ namespace Aurora::Threading::Primitives
if (AuAtomicLoad(&this->state_) == 1 &&
AuAtomicLoad(&this->writersPending_) > 1)
{
this->SignalManyWriter();
this->SignalManyWriter(-1);
}
}
@ -541,12 +541,12 @@ namespace Aurora::Threading::Primitives
}
template<bool bIsWriteRecursionAllowed>
void RWLockImpl<bIsWriteRecursionAllowed>::SignalManyWriter()
void RWLockImpl<bIsWriteRecursionAllowed>::SignalManyWriter(int iBias)
{
if (gUseFutexRWLock)
{
auto pThat = this->GetFutexConditionWriter();
AuUInt32 uCount = AuAtomicLoad(&this->writersPending_);
AuUInt32 uCount = AuAtomicLoad(&this->writersPending_) + iBias;
AuAtomicAdd(pThat, uCount);
InternalLTSWakeCount(pThat, uCount);
}
@ -563,16 +563,17 @@ namespace Aurora::Threading::Primitives
{
return DoTryIf([=]()
{
return TryLockReadNoSpin();
return TryLockReadNoSpin<true>();
});
}
else
{
return TryLockReadNoSpin();
return TryLockReadNoSpin<true>();
}
}
template<bool bIsWriteRecursionAllowed>
template<bool CheckWrite>
bool RWLockImpl<bIsWriteRecursionAllowed>::TryLockReadNoSpin()
{
auto iCurState = this->state_;
@ -582,6 +583,16 @@ namespace Aurora::Threading::Primitives
return this->reentrantWriteLockHandle_ == GetThreadCookie();
}
if constexpr (CheckWrite)
{
if ((AuAtomicLoad(&this->writersPending_)) &&
(iCurState > 0 || gRuntimeConfig.threadingConfig.bAlwaysRWLockWriteBiasOnReadLock) &&
(gRuntimeConfig.threadingConfig.bEnableRWLockWriteBiasOnReadLock))
{
return false;
}
}
return AuAtomicCompareExchange(&this->state_, iCurState + 1, iCurState) == iCurState;
}

View File

@ -69,7 +69,8 @@ namespace Aurora::Threading::Primitives
auline bool LockWriteNS(AuUInt64 timeout);// override;
auline bool LockWriteNSAbs(AuUInt64 timeout);// override;
auline bool TryLockRead();// override;
auline bool TryLockReadNoSpin();// override;
template<bool CheckWrite>
auline bool TryLockReadNoSpin();
auline bool TryLockWrite();// override;
auline void UnlockRead();// override;
auline void UnlockWrite();// override;
@ -94,7 +95,7 @@ namespace Aurora::Threading::Primitives
auline void SignalOneReader();
auline void SignalOneWriter();
auline void SignalManyReader();
auline void SignalManyWriter();
auline void SignalManyWriter(int iBias = 0);
private: