[*] 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 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 bPreferLinuxPrimitivesFutexNoSpin : 1 { false };
AuUInt64 bPreferUnixPrimitivesNoSpin : 1 { false }; AuUInt64 bPreferUnixPrimitivesNoSpin : 1 { false };
AuUInt64 bAlwaysRWLockWriteBiasOnReadLock : 1 { false };
AuUInt64 bEnableRWLockWriteBiasOnReadLock : 1 { true };
}; };
struct DummyConfig struct DummyConfig

View File

@ -212,7 +212,7 @@ namespace Aurora::Threading::Primitives
template<bool bIsWriteRecursionAllowed> template<bool bIsWriteRecursionAllowed>
bool RWLockImpl<bIsWriteRecursionAllowed>::LockReadNS(AuUInt64 uTimeout) bool RWLockImpl<bIsWriteRecursionAllowed>::LockReadNS(AuUInt64 uTimeout)
{ {
if (this->TryLockReadNoSpin()) if (this->TryLockReadNoSpin<true>())
{ {
return true; return true;
} }
@ -435,7 +435,7 @@ namespace Aurora::Threading::Primitives
if (AuAtomicLoad(&this->state_) == 1 && if (AuAtomicLoad(&this->state_) == 1 &&
AuAtomicLoad(&this->writersPending_) > 1) AuAtomicLoad(&this->writersPending_) > 1)
{ {
this->SignalManyWriter(); this->SignalManyWriter(-1);
} }
} }
@ -479,7 +479,7 @@ namespace Aurora::Threading::Primitives
if (AuAtomicLoad(&this->state_) == 1 && if (AuAtomicLoad(&this->state_) == 1 &&
AuAtomicLoad(&this->writersPending_) > 1) AuAtomicLoad(&this->writersPending_) > 1)
{ {
this->SignalManyWriter(); this->SignalManyWriter(-1);
} }
} }
@ -541,12 +541,12 @@ namespace Aurora::Threading::Primitives
} }
template<bool bIsWriteRecursionAllowed> template<bool bIsWriteRecursionAllowed>
void RWLockImpl<bIsWriteRecursionAllowed>::SignalManyWriter() void RWLockImpl<bIsWriteRecursionAllowed>::SignalManyWriter(int iBias)
{ {
if (gUseFutexRWLock) if (gUseFutexRWLock)
{ {
auto pThat = this->GetFutexConditionWriter(); auto pThat = this->GetFutexConditionWriter();
AuUInt32 uCount = AuAtomicLoad(&this->writersPending_); AuUInt32 uCount = AuAtomicLoad(&this->writersPending_) + iBias;
AuAtomicAdd(pThat, uCount); AuAtomicAdd(pThat, uCount);
InternalLTSWakeCount(pThat, uCount); InternalLTSWakeCount(pThat, uCount);
} }
@ -563,16 +563,17 @@ namespace Aurora::Threading::Primitives
{ {
return DoTryIf([=]() return DoTryIf([=]()
{ {
return TryLockReadNoSpin(); return TryLockReadNoSpin<true>();
}); });
} }
else else
{ {
return TryLockReadNoSpin(); return TryLockReadNoSpin<true>();
} }
} }
template<bool bIsWriteRecursionAllowed> template<bool bIsWriteRecursionAllowed>
template<bool CheckWrite>
bool RWLockImpl<bIsWriteRecursionAllowed>::TryLockReadNoSpin() bool RWLockImpl<bIsWriteRecursionAllowed>::TryLockReadNoSpin()
{ {
auto iCurState = this->state_; auto iCurState = this->state_;
@ -582,6 +583,16 @@ namespace Aurora::Threading::Primitives
return this->reentrantWriteLockHandle_ == GetThreadCookie(); 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; 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 LockWriteNS(AuUInt64 timeout);// override;
auline bool LockWriteNSAbs(AuUInt64 timeout);// override; auline bool LockWriteNSAbs(AuUInt64 timeout);// override;
auline bool TryLockRead();// override; auline bool TryLockRead();// override;
auline bool TryLockReadNoSpin();// override; template<bool CheckWrite>
auline bool TryLockReadNoSpin();
auline bool TryLockWrite();// override; auline bool TryLockWrite();// override;
auline void UnlockRead();// override; auline void UnlockRead();// override;
auline void UnlockWrite();// override; auline void UnlockWrite();// override;
@ -94,7 +95,7 @@ namespace Aurora::Threading::Primitives
auline void SignalOneReader(); auline void SignalOneReader();
auline void SignalOneWriter(); auline void SignalOneWriter();
auline void SignalManyReader(); auline void SignalManyReader();
auline void SignalManyWriter(); auline void SignalManyWriter(int iBias = 0);
private: private: