[*] Move some platform specific code from AuWakeOnAddress to AuProcAddresses.*.*
This commit is contained in:
parent
9591fc9d30
commit
65c78ef182
@ -8,6 +8,7 @@
|
||||
#include <RuntimeInternal.hpp>
|
||||
#include <sys/syscall.h>
|
||||
#include <linux/futex.h>
|
||||
#include <Time/Time.hpp>
|
||||
|
||||
#define AURORA_IS_GLIBC
|
||||
|
||||
@ -288,4 +289,107 @@ namespace Aurora
|
||||
return -ENOSYS;
|
||||
}
|
||||
}
|
||||
|
||||
bool SysNativeWaitOnAddressFutexSupported()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SysWaitOnAddressNoTimed(const void *pTargetAddress,
|
||||
const void *pCompareAddress,
|
||||
AuUInt8 uWordSize)
|
||||
{
|
||||
int ret {};
|
||||
|
||||
#if defined(AU_CPU_ENDIAN_BIG)
|
||||
if (uWordSize == 8)
|
||||
{
|
||||
pTargetAddress = AuReinterpretCast<const char *>(pTargetAddress) + 4;
|
||||
pCompareAddress = AuReinterpretCast<const char *>(pCompareAddress) + 4;
|
||||
}
|
||||
#endif
|
||||
|
||||
auto uCurrent = *(AuUInt32 *)pCompareAddress;
|
||||
|
||||
do
|
||||
{
|
||||
ret = futex_wait((AuUInt32 *)pTargetAddress, uCurrent, nullptr);
|
||||
|
||||
if (ret == 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ret == -EAGAIN)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ret == -ETIMEDOUT)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
while (ret == -EINTR);
|
||||
|
||||
return AuMemcmp(pCompareAddress, pTargetAddress, uWordSize) != 0;
|
||||
}
|
||||
|
||||
bool SysWaitOnAddressTimed(const void *pTargetAddress,
|
||||
const void *pCompareAddress,
|
||||
AuUInt8 uWordSize,
|
||||
AuUInt64 uAbsTimeSteadyClock,
|
||||
AuUInt64 uRelativeNanoseconds,
|
||||
AuOptional<AuUInt64> uAbsTimeAltClock,
|
||||
bool bSpun)
|
||||
{
|
||||
int ret {};
|
||||
|
||||
#if defined(AU_CPU_ENDIAN_BIG)
|
||||
if (uWordSize == 8)
|
||||
{
|
||||
pTargetAddress = AuReinterpretCast<const char *>(pTargetAddress) + 4;
|
||||
pCompareAddress = AuReinterpretCast<const char *>(pCompareAddress) + 4;
|
||||
}
|
||||
#endif
|
||||
|
||||
auto uCurrent = *(AuUInt32 *)pCompareAddress;
|
||||
|
||||
struct timespec tspec;
|
||||
Time::monoabsns2ts(&tspec, uAbsTimeAltClock ? uAbsTimeAltClock.value() : uAbsTimeSteadyClock);
|
||||
|
||||
do
|
||||
{
|
||||
ret = futex_wait((AuUInt32 *)pTargetAddress, uCurrent, &tspec);
|
||||
|
||||
if (ret == 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ret == -EAGAIN)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ret == -ETIMEDOUT)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
while (ret == -EINTR);
|
||||
|
||||
return AuMemcmp(pCompareAddress, pTargetAddress, uWordSize) != 0;
|
||||
}
|
||||
|
||||
void SysWakeNOnAddress(const void *pAddress,
|
||||
AuUInt32 dwCount)
|
||||
{
|
||||
futex_wake((AuUInt32 *)pAddress, dwCount);
|
||||
}
|
||||
|
||||
void SysWakeAllOnAddress(const void *pAddress)
|
||||
{
|
||||
futex_wake((AuUInt32 *)pAddress, INT_MAX);
|
||||
}
|
||||
}
|
@ -680,4 +680,73 @@ namespace Aurora
|
||||
return nullptr;
|
||||
}
|
||||
#endif
|
||||
|
||||
bool SysNativeWaitOnAddressFutexSupported()
|
||||
{
|
||||
return bool(pWaitOnAddress) || bool(pRtlWaitOnAddress);
|
||||
}
|
||||
|
||||
bool SysWaitOnAddressNoTimed(const void *pTargetAddress,
|
||||
const void *pCompareAddress,
|
||||
AuUInt8 uWordSize)
|
||||
{
|
||||
if (pRtlWaitOnAddress)
|
||||
{
|
||||
return pRtlWaitOnAddress((void *)pTargetAddress, (void *)pCompareAddress, uWordSize, nullptr);
|
||||
}
|
||||
else
|
||||
{
|
||||
return pWaitOnAddress((void *)pTargetAddress, (void *)pCompareAddress, uWordSize, INFINITE);
|
||||
}
|
||||
}
|
||||
|
||||
bool SysWaitOnAddressTimed(const void *pTargetAddress,
|
||||
const void *pCompareAddress,
|
||||
AuUInt8 uWordSize,
|
||||
AuUInt64 uAbsTimeSteadyClock,
|
||||
AuUInt64 uRelativeNanoseconds,
|
||||
AuOptional<AuUInt64> uAbsTimeAltClock,
|
||||
bool bSpun)
|
||||
{
|
||||
// Wont move out of AuWakeOnAddress.cpp because it's so long and bloated in order to force nanosecond-scale yields on UWP.
|
||||
SysUnreachable();
|
||||
}
|
||||
|
||||
void SysWakeNOnAddress(const void *pAddress,
|
||||
AuUInt32 dwCount)
|
||||
{
|
||||
if (pRtlWakeAddressSingle)
|
||||
{
|
||||
if (dwCount < 6)
|
||||
{
|
||||
for (AuUInt i = 0; i < dwCount; i++)
|
||||
{
|
||||
pRtlWakeAddressSingle((void *)pAddress);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
pRtlWakeByAddressAll((void *)pAddress);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (AuUInt i = 0; i < dwCount; i++)
|
||||
{
|
||||
pWakeByAddressSingle((void *)pAddress);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SysWakeAllOnAddress(const void *pAddress)
|
||||
{
|
||||
if (pRtlWakeByAddressAll)
|
||||
{
|
||||
pRtlWakeByAddressAll((void *)pAddress);
|
||||
}
|
||||
else
|
||||
{
|
||||
pWakeByAddressAll((void *)pAddress);
|
||||
}
|
||||
}
|
||||
}
|
@ -18,4 +18,23 @@ namespace Aurora
|
||||
void InitProcAddresses();
|
||||
|
||||
inline bool gUseNativeWaitRWLock {};
|
||||
|
||||
bool SysNativeWaitOnAddressFutexSupported();
|
||||
|
||||
bool SysWaitOnAddressNoTimed(const void *pTargetAddress,
|
||||
const void *pCompareAddress,
|
||||
AuUInt8 uWordSize);
|
||||
|
||||
bool SysWaitOnAddressTimed(const void *pTargetAddress,
|
||||
const void *pCompareAddress,
|
||||
AuUInt8 uWordSize,
|
||||
AuUInt64 uAbsTimeSteadyClock,
|
||||
AuUInt64 uRelativeNanoseconds,
|
||||
AuOptional<AuUInt64> uAbsTimeAltClock /* hint */,
|
||||
bool bSpun = false);
|
||||
|
||||
void SysWakeNOnAddress(const void *pAddress,
|
||||
AuUInt32 dwCount);
|
||||
|
||||
void SysWakeAllOnAddress(const void *pAddress);
|
||||
}
|
@ -458,7 +458,7 @@ namespace Aurora::Threading
|
||||
#elif defined(AURORA_PLATFORM_LINUX)
|
||||
return true;
|
||||
#else
|
||||
return false;
|
||||
return SysNativeWaitOnAddressFutexSupported();
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -578,62 +578,6 @@ namespace Aurora::Threading
|
||||
}
|
||||
}
|
||||
|
||||
static bool RunOSWaitOnAddressNoTimed(const void *pTargetAddress,
|
||||
const void *pCompareAddress,
|
||||
AuUInt8 uWordSize)
|
||||
{
|
||||
#if defined(AURORA_IS_MODERNNT_DERIVED)
|
||||
if (pRtlWaitOnAddress)
|
||||
{
|
||||
return pRtlWaitOnAddress((void *)pTargetAddress, (void *)pCompareAddress, uWordSize, nullptr);
|
||||
}
|
||||
else
|
||||
{
|
||||
return pWaitOnAddress((void *)pTargetAddress, (void *)pCompareAddress, uWordSize, INFINITE);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(AURORA_IS_LINUX_DERIVED)
|
||||
int ret {};
|
||||
|
||||
#if defined(AU_CPU_ENDIAN_BIG)
|
||||
if (uWordSize == 8)
|
||||
{
|
||||
pTargetAddress = AuReinterpretCast<const char *>(pTargetAddress) + 4;
|
||||
pCompareAddress = AuReinterpretCast<const char *>(pCompareAddress) + 4;
|
||||
}
|
||||
#endif
|
||||
|
||||
auto uCurrent = *(AuUInt32 *)pCompareAddress;
|
||||
auto expect = WaitBuffer::From(pCompareAddress, uWordSize);
|
||||
|
||||
do
|
||||
{
|
||||
ret = futex_wait((AuUInt32 *)pTargetAddress, uCurrent, nullptr);
|
||||
|
||||
if (ret == 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ret == -EAGAIN)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ret == -ETIMEDOUT)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
while (ret == -EINTR);
|
||||
|
||||
return !expect.Compare(pTargetAddress);
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool RunOSWaitOnAddressTimed(const void *pTargetAddress,
|
||||
const void *pCompareAddress,
|
||||
AuUInt8 uWordSize,
|
||||
@ -803,48 +747,19 @@ namespace Aurora::Threading
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(AURORA_IS_LINUX_DERIVED)
|
||||
int ret {};
|
||||
|
||||
#if defined(AU_CPU_ENDIAN_BIG)
|
||||
if (uWordSize == 8)
|
||||
{
|
||||
pTargetAddress = AuReinterpretCast<const char *>(pTargetAddress) + 4;
|
||||
pCompareAddress = AuReinterpretCast<const char *>(pCompareAddress) + 4;
|
||||
}
|
||||
#endif
|
||||
|
||||
auto uCurrent = *(AuUInt32 *)pCompareAddress;
|
||||
|
||||
struct timespec tspec;
|
||||
Time::monoabsns2ts(&tspec, uAbsTimeAltClock ? uAbsTimeAltClock.value() : uAbsTimeSteadyClock);
|
||||
|
||||
do
|
||||
{
|
||||
ret = futex_wait((AuUInt32 *)pTargetAddress, uCurrent, &tspec);
|
||||
|
||||
if (ret == 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ret == -EAGAIN)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ret == -ETIMEDOUT)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
while (ret == -EINTR);
|
||||
|
||||
#endif
|
||||
|
||||
return !WaitBuffer::Compare(pCompareAddress, uWordSize, pTargetAddress);
|
||||
|
||||
#else
|
||||
|
||||
return SysWaitOnAddressTimed(pTargetAddress,
|
||||
pCompareAddress,
|
||||
uWordSize,
|
||||
uAbsTimeSteadyClock,
|
||||
uRelativeNanoseconds,
|
||||
uAbsTimeAltClock,
|
||||
bSpun);
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
static void RunOSWaitOnAddressNoTimedNoErrors(const void *pTargetAddress,
|
||||
@ -853,7 +768,7 @@ namespace Aurora::Threading
|
||||
{
|
||||
while (WaitBuffer::Compare(pTargetAddress, state.uWordSize, state))
|
||||
{
|
||||
if (!RunOSWaitOnAddressNoTimed(pTargetAddress, pCompareAddress, state.uWordSize))
|
||||
if (!SysWaitOnAddressNoTimed(pTargetAddress, pCompareAddress, state.uWordSize))
|
||||
{
|
||||
AuThreading::ContextYield();
|
||||
}
|
||||
@ -874,9 +789,6 @@ namespace Aurora::Threading
|
||||
return !WaitBuffer::Compare(pTargetAddress, state.uWordSize, state);
|
||||
}
|
||||
|
||||
static void RunOSWakeNOnAddress(const void *pAddress,
|
||||
AuUInt32 dwCount);
|
||||
|
||||
static void RunOSWaitOnAddressEQNoTimedNoErrors(const void *pTargetAddress,
|
||||
const void *pCompareAddress,
|
||||
WaitState &state)
|
||||
@ -890,11 +802,11 @@ namespace Aurora::Threading
|
||||
return;
|
||||
}
|
||||
|
||||
(void)RunOSWaitOnAddressNoTimed(pTargetAddress, wb.buffer, state.uWordSize);
|
||||
(void)SysWaitOnAddressNoTimed(pTargetAddress, wb.buffer, state.uWordSize);
|
||||
|
||||
if (WaitBuffer::Compare(pTargetAddress, state.uWordSize, state))
|
||||
{
|
||||
RunOSWakeNOnAddress(pTargetAddress, 1);
|
||||
SysWakeNOnAddress(pTargetAddress, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -921,7 +833,7 @@ namespace Aurora::Threading
|
||||
|
||||
if (WaitBuffer::Compare(pTargetAddress, state.uWordSize, state))
|
||||
{
|
||||
RunOSWakeNOnAddress(pTargetAddress, 1);
|
||||
SysWakeNOnAddress(pTargetAddress, 1);
|
||||
if (!bResult)
|
||||
{
|
||||
return false;
|
||||
@ -934,56 +846,6 @@ namespace Aurora::Threading
|
||||
}
|
||||
}
|
||||
|
||||
static void RunOSWakeNOnAddress(const void *pAddress,
|
||||
AuUInt32 dwCount)
|
||||
{
|
||||
#if defined(AURORA_IS_LINUX_DERIVED)
|
||||
futex_wake((AuUInt32 *)pAddress, dwCount);
|
||||
#endif
|
||||
|
||||
#if defined(AURORA_IS_MODERNNT_DERIVED)
|
||||
if (pRtlWakeAddressSingle)
|
||||
{
|
||||
if (dwCount < 6)
|
||||
{
|
||||
for (AuUInt i = 0; i < dwCount; i++)
|
||||
{
|
||||
pRtlWakeAddressSingle((void *)pAddress);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
pRtlWakeByAddressAll((void *)pAddress);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (AuUInt i = 0; i < dwCount; i++)
|
||||
{
|
||||
pWakeByAddressSingle((void *)pAddress);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static void RunOSWakeAllOnAddress(const void *pAddress)
|
||||
{
|
||||
#if defined(AURORA_IS_LINUX_DERIVED)
|
||||
futex_wake((AuUInt32 *)pAddress, INT_MAX);
|
||||
#endif
|
||||
|
||||
#if defined(AURORA_IS_MODERNNT_DERIVED)
|
||||
if (pRtlWakeByAddressAll)
|
||||
{
|
||||
pRtlWakeByAddressAll((void *)pAddress);
|
||||
}
|
||||
else
|
||||
{
|
||||
pWakeByAddressAll((void *)pAddress);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// Windows 8+ thread primitives might use me instead of the public API
|
||||
// it does work on Linux and Windows 8+
|
||||
// it does not, however, work on emulated platforms
|
||||
@ -1021,7 +883,7 @@ namespace Aurora::Threading
|
||||
WakeAllOnAddress(pTargetAddress);
|
||||
#else
|
||||
auto [pWakeAddress, uDelta, uMask] = DecodeAddress(pTargetAddress, 1);
|
||||
RunOSWakeAllOnAddress(pWakeAddress);
|
||||
SysWakeAllOnAddress(pWakeAddress);
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -1031,7 +893,14 @@ namespace Aurora::Threading
|
||||
WakeOnAddress(pTargetAddress);
|
||||
#else
|
||||
auto [pWakeAddress, uDelta, uMask] = DecodeAddress(pTargetAddress, 1);
|
||||
RunOSWakeNOnAddress(pWakeAddress, uDelta ? INT_MAX : 1);
|
||||
if (uDelta)
|
||||
{
|
||||
SysWakeAllOnAddress(pWakeAddress);
|
||||
}
|
||||
else
|
||||
{
|
||||
SysWakeNOnAddress(pWakeAddress, 1);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -1041,7 +910,14 @@ namespace Aurora::Threading
|
||||
WakeNOnAddress(pTargetAddress, uCount);
|
||||
#else
|
||||
auto [pWakeAddress, uDelta, uMask] = DecodeAddress(pTargetAddress, 1);
|
||||
RunOSWakeNOnAddress(pWakeAddress, uDelta ? INT_MAX : uCount);
|
||||
if (uDelta)
|
||||
{
|
||||
SysWakeAllOnAddress(pWakeAddress);
|
||||
}
|
||||
else
|
||||
{
|
||||
SysWakeNOnAddress(pWakeAddress, uCount);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -1151,7 +1027,14 @@ namespace Aurora::Threading
|
||||
if (IsWaitOnRecommended())
|
||||
{
|
||||
auto [pWakeAddress, uDelta, uMask] = DecodeAddress(pTargetAddress, 1);
|
||||
RunOSWakeNOnAddress(pWakeAddress, uDelta ? INT_MAX : uNMaximumThreads);
|
||||
if (uDelta)
|
||||
{
|
||||
SysWakeAllOnAddress(pWakeAddress);
|
||||
}
|
||||
else
|
||||
{
|
||||
SysWakeNOnAddress(pWakeAddress, uNMaximumThreads);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1185,7 +1068,7 @@ namespace Aurora::Threading
|
||||
if (IsWaitOnRecommended())
|
||||
{
|
||||
auto [pWakeAddress, uDelta, uMask] = DecodeAddress(pTargetAddress, 1);
|
||||
RunOSWakeAllOnAddress(pWakeAddress);
|
||||
SysWakeAllOnAddress(pWakeAddress);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user