[+] Non-mutually exclusive binary semaphore / event wait path

[+] ThreadingConfig::gPreferFutexEvent
This commit is contained in:
Reece Wilson 2023-09-10 14:50:59 +01:00
parent 48dc2e790b
commit 74dc6772b0
5 changed files with 78 additions and 35 deletions

View File

@ -379,11 +379,12 @@ namespace Aurora
AuUInt64 uAdaptiveSpinCUCnt8 : 4 { 2 }; AuUInt64 uAdaptiveSpinCUCnt8 : 4 { 2 };
AuUInt64 uAdaptiveSpinCUCnt16 : 4 { 4 }; AuUInt64 uAdaptiveSpinCUCnt16 : 4 { 4 };
AuUInt64 bPreferFutexRWLock : 1 { true }; AuUInt64 bPreferFutexRWLock : 1 { true };
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 : 12 { 300 }; // 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 bAlwaysRWLockWriteBiasOnReadLock : 1 { false };
AuUInt64 bEnableRWLockWriteBiasOnReadLock : 1 { true }; AuUInt64 bEnableRWLockWriteBiasOnReadLock : 1 { true };
AuUInt64 bPreferFutexEvent : 1 { true };
}; };
struct DummyConfig struct DummyConfig

View File

@ -8,6 +8,7 @@
#include <Source/RuntimeInternal.hpp> #include <Source/RuntimeInternal.hpp>
#include "AuEvent.hpp" #include "AuEvent.hpp"
#include "SMTYield.hpp" #include "SMTYield.hpp"
#include "../AuWakeInternal.hpp"
namespace Aurora::Threading::Primitives namespace Aurora::Threading::Primitives
{ {
@ -45,26 +46,49 @@ namespace Aurora::Threading::Primitives
uEndTime = uStartTime + uTimeout; uEndTime = uStartTime + uTimeout;
} }
AU_LOCK_GUARD(this->mutex_); if (gPreferFutexEvent)
while (!AtomicIsEventSetLogicNoSpinNoLock())
{ {
AuUInt32 uTimeoutNS {}; while (!AtomicIsEventSetLogicNoSpinNoLock())
if (uTimeout)
{ {
uStartTime = Time::SteadyClockNS(); EventBits bits;
if (uStartTime >= uEndTime) bits.state = AuAtomicLoad(&this->state_);
if (bits.bTriggered)
{ {
return false; if (!InternalLTSWaitOnAddressHighRes(&this->state_, &bits.state, sizeof(bits.state), uEndTime))
{
return false;
}
}
else
{
SMPPause();
}
}
}
else
{
AU_LOCK_GUARD(this->mutex_);
while (!AtomicIsEventSetLogicNoSpinNoLock())
{
AuUInt32 uTimeoutNS {};
if (uTimeout)
{
uStartTime = Time::SteadyClockNS();
if (uStartTime >= uEndTime)
{
return false;
}
uTimeoutNS = uEndTime - uStartTime;
} }
uTimeoutNS = uEndTime - uStartTime; if (!this->condition_.WaitForSignalNsEx(&this->mutex_, uTimeoutNS))
} {
continue;
if (!this->condition_.WaitForSignalNsEx(&this->mutex_, uTimeoutNS)) }
{
continue;
} }
} }
@ -139,17 +163,7 @@ namespace Aurora::Threading::Primitives
} }
} }
this->mutex_.Lock(); this->DoSignal(bits);
this->mutex_.Unlock();
if (bits.bAtomicRelease)
{
this->condition_.Signal();
}
else
{
this->condition_.Broadcast();
}
} }
bool EventImpl::TrySet() bool EventImpl::TrySet()
@ -176,19 +190,38 @@ namespace Aurora::Threading::Primitives
} }
} }
this->mutex_.Lock(); this->DoSignal(bits);
this->mutex_.Unlock();
if (bits.bAtomicRelease) return true;
}
void EventImpl::DoSignal(const EventBits &bits)
{
if (gPreferFutexEvent)
{ {
this->condition_.Signal(); if (bits.bAtomicRelease)
{
InternalLTSWakeOne(&this->state_);
}
else
{
InternalLTSWakeAll(&this->state_);
}
} }
else else
{ {
this->condition_.Broadcast(); this->mutex_.Lock();
} this->mutex_.Unlock();
return true; if (bits.bAtomicRelease)
{
this->condition_.Signal();
}
else
{
this->condition_.Broadcast();
}
}
} }
bool EventImpl::HasOSHandle(AuMach &mach) bool EventImpl::HasOSHandle(AuMach &mach)

View File

@ -64,6 +64,8 @@ namespace Aurora::Threading::Primitives
AuUInt8 state_; AuUInt8 state_;
}; };
void DoSignal(const EventBits &bits);
#endif #endif
}; };
} }

View File

@ -78,8 +78,12 @@ namespace Aurora::Threading::Primitives
{ {
auto uCores = AuHwInfo::GetCPUInfo().uThreads; auto uCores = AuHwInfo::GetCPUInfo().uThreads;
bool bPermitWOAInternal = IsWaitOnRecommended();
gUseFutexRWLock = ThrdCfg::gPreferFutexRWLock && gUseFutexRWLock = ThrdCfg::gPreferFutexRWLock &&
IsWaitOnRecommended(); bPermitWOAInternal;
gPreferFutexEvent = ThrdCfg::gPreferFutexEvent &&
bPermitWOAInternal;
gSpinAdaptiveThreadCount = uCores; gSpinAdaptiveThreadCount = uCores;
@ -176,5 +180,6 @@ namespace Aurora::Threading::Primitives
ThrdCfg::gPreferUnixPrimitivesNoSpin = gRuntimeConfig.threadingConfig.bPreferUnixPrimitivesNoSpin; ThrdCfg::gPreferUnixPrimitivesNoSpin = gRuntimeConfig.threadingConfig.bPreferUnixPrimitivesNoSpin;
ThrdCfg::gAlwaysRWLockWriteBiasOnReadLock = gRuntimeConfig.threadingConfig.bAlwaysRWLockWriteBiasOnReadLock; ThrdCfg::gAlwaysRWLockWriteBiasOnReadLock = gRuntimeConfig.threadingConfig.bAlwaysRWLockWriteBiasOnReadLock;
ThrdCfg::gEnableRWLockWriteBiasOnReadLock = gRuntimeConfig.threadingConfig.bEnableRWLockWriteBiasOnReadLock; ThrdCfg::gEnableRWLockWriteBiasOnReadLock = gRuntimeConfig.threadingConfig.bEnableRWLockWriteBiasOnReadLock;
ThrdCfg::gPreferFutexEvent = gRuntimeConfig.threadingConfig.bPreferFutexEvent;
} }
} }

View File

@ -45,6 +45,7 @@ namespace Aurora::Threading::Primitives
inline AuUInt32 gAdaptiveSpinCUCnt8 {}; inline AuUInt32 gAdaptiveSpinCUCnt8 {};
inline AuUInt32 gAdaptiveSpinCUCnt16 {}; inline AuUInt32 gAdaptiveSpinCUCnt16 {};
inline bool gPreferFutexRWLock {}; inline bool gPreferFutexRWLock {};
inline bool gPreferFutexEvent {};
inline bool gWinXpThrough7BlazeOptimizerPower {}; inline bool gWinXpThrough7BlazeOptimizerPower {};
inline bool gPreferLinuxPrimitivesFutexNoSpin {}; inline bool gPreferLinuxPrimitivesFutexNoSpin {};
inline bool gPreferUnixPrimitivesNoSpin {}; inline bool gPreferUnixPrimitivesNoSpin {};
@ -57,6 +58,7 @@ namespace Aurora::Threading::Primitives
inline AuUInt32 gSpinAdaptiveThreadCount {}; inline AuUInt32 gSpinAdaptiveThreadCount {};
inline AuUInt32 gUseFutexRWLock {}; inline AuUInt32 gUseFutexRWLock {};
inline AuUInt32 gPreferFutexEvent {};
void InitAdaptiveThreshold(); void InitAdaptiveThreshold();
void InitAdaptiveThresholdFirstTime(); void InitAdaptiveThresholdFirstTime();