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