[*] Move some platform specific code from AuWakeOnAddress to AuProcAddresses.*.*

This commit is contained in:
Reece Wilson 2024-03-03 00:25:10 +00:00
parent 9591fc9d30
commit 65c78ef182
4 changed files with 235 additions and 160 deletions

View File

@ -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);
}
}

View File

@ -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);
}
}
}

View File

@ -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);
}

View File

@ -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
{