[*] Win8+: Experimental primitive improvements by taking notes from Win7 cycle pinching
[*] +regression in condvar
This commit is contained in:
parent
355f7db711
commit
8c84ecf892
@ -67,15 +67,14 @@ namespace Aurora::Threading::Primitives
|
||||
{
|
||||
if (gUseNativeWaitCondvar)
|
||||
{
|
||||
auto uCurrentValue = uValue + kFutexBitWait; // TODO: 1 bit?
|
||||
auto uCurrentValue = uValue + kFutexBitWait;
|
||||
InternalLTSWaitOnAddressHighRes((void *)&uValueRef, &uCurrentValue, sizeof(uCurrentValue), 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
pNtWaitForKeyedEvent(gKeyedEventHandle, (void *)&uValueRef, 0, NULL);
|
||||
AuAtomicSub(&uValueRef, kFutexBitWake);
|
||||
}
|
||||
|
||||
AuAtomicSub(&uValueRef, kFutexBitWake);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@ -86,11 +85,38 @@ namespace Aurora::Threading::Primitives
|
||||
#if defined(AURORA_FORCE_SRW_LOCKS)
|
||||
::ReleaseSRWLockExclusive(&this->lock_);
|
||||
#else
|
||||
auto &uValueRef = this->lock_.uWaitCount;
|
||||
|
||||
// Mirrors: ./AuMutex.NT.cpp
|
||||
// keep this codeblock in parity
|
||||
// defer to the comments in that source file
|
||||
|
||||
if (gUseNativeWaitCondvar)
|
||||
{
|
||||
auto &uValueRef = this->lock_.uWaitCount;
|
||||
|
||||
*(AuUInt8 *)&uValueRef = 0;
|
||||
|
||||
while (true)
|
||||
{
|
||||
auto uValue = uValueRef;
|
||||
|
||||
if (uValue < kFutexBitWait)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (AuAtomicCompareExchange(&uValueRef, uValue - kFutexBitWait, uValue) == uValue)
|
||||
{
|
||||
pWakeByAddressSingle((void *)&this->lock_.uWaitCount);
|
||||
return;
|
||||
}
|
||||
|
||||
SMPPause();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
auto &uValueRef = this->lock_.uWaitCount;
|
||||
|
||||
#if defined(AURORA_ARCH_X86) || defined(AURORA_ARCH_X64)
|
||||
*(AuUInt8 *)&uValueRef = 0;
|
||||
#else
|
||||
@ -127,14 +153,7 @@ namespace Aurora::Threading::Primitives
|
||||
|
||||
if (AuAtomicCompareExchange(&uValueRef, uValue - kFutexBitWait + kFutexBitWake, uValue) == uValue)
|
||||
{
|
||||
if (gUseNativeWaitCondvar)
|
||||
{
|
||||
pWakeByAddressSingle((void *)&uValueRef);
|
||||
}
|
||||
else
|
||||
{
|
||||
pNtReleaseKeyedEvent(gKeyedEventHandle, (void *)&uValueRef, 0, NULL);
|
||||
}
|
||||
pNtReleaseKeyedEvent(gKeyedEventHandle, (void *)&uValueRef, 0, NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -18,8 +18,8 @@ namespace Aurora::Threading::Primitives
|
||||
// sub = and
|
||||
// assuming the bits are unset/set respectively
|
||||
|
||||
static auto const kFutexBitWake = 256u; // 1^8
|
||||
static auto const kFutexBitWait = 512u; // 1^9, next byte over
|
||||
static auto const kFutexBitWake = 256u; // 2^8
|
||||
static auto const kFutexBitWait = 512u; // 2^9, next byte over
|
||||
|
||||
|
||||
inline HANDLE gKeyedEventHandle { INVALID_HANDLE_VALUE };
|
||||
|
@ -151,6 +151,8 @@ namespace Aurora::Threading::Primitives
|
||||
}
|
||||
else
|
||||
{
|
||||
pMutex->Unlock();
|
||||
|
||||
// Obligatory Windows XP+ resched
|
||||
bRet = pNtWaitForKeyedEvent(gKeyedEventHandle, &this->wlist, 0, nullptr) != NTSTATUS_TIMEOUT;
|
||||
}
|
||||
|
@ -82,21 +82,24 @@ namespace Aurora::Threading::Primitives
|
||||
return true;
|
||||
}
|
||||
|
||||
AuUInt64 uStartTime = Time::SteadyClockNS();
|
||||
AuUInt64 uEndTime = uTimeout ? uStartTime + uTimeout : 0;
|
||||
AuUInt64 uEndTime = uTimeout ? Time::SteadyClockNS() + uTimeout : 0;
|
||||
int iYieldCounter {};
|
||||
|
||||
if (gUseNativeWaitMutex)
|
||||
{
|
||||
auto state = this->state_;
|
||||
while (::_interlockedbittestandset((volatile LONG *)&this->state_, 0) != 0)
|
||||
while (!TryLock())
|
||||
{
|
||||
if (!InternalLTSWaitOnAddressHighRes((void *)&this->state_, &state, sizeof(this->state_), uEndTime))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
auto &uValueRef = this->state_;
|
||||
auto uValue = uValueRef | 1;
|
||||
auto uNextValue = uValue + kFutexBitWait;
|
||||
|
||||
state = this->state_;
|
||||
if (AuAtomicCompareExchange(&uValueRef, uNextValue, uValue) == uValue)
|
||||
{
|
||||
if (!InternalLTSWaitOnAddressHighRes((void *)&uValueRef, &uNextValue, sizeof(uNextValue), uEndTime))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
@ -218,8 +221,29 @@ namespace Aurora::Threading::Primitives
|
||||
{
|
||||
if (gUseNativeWaitMutex)
|
||||
{
|
||||
this->state_ = 0;
|
||||
pWakeByAddressSingle((void *)&this->state_);
|
||||
auto &uValueRef = this->state_;
|
||||
|
||||
*(AuUInt8 *)&uValueRef = 0;
|
||||
|
||||
while (true)
|
||||
{
|
||||
auto uValue = uValueRef;
|
||||
|
||||
if (uValue < kFutexBitWait)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (AuAtomicCompareExchange(&uValueRef, uValue - kFutexBitWait, uValue) == uValue)
|
||||
{
|
||||
pWakeByAddressSingle((void *)&this->state_);
|
||||
return;
|
||||
}
|
||||
|
||||
SMPPause();
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user