AuroraRuntime/Source/Threading/Primitives/AuConditionMutex.Linux.cpp

125 lines
2.7 KiB
C++

/***
Copyright (C) 2023 J Reece Wilson (a/k/a "Reece"). All rights reserved.
File: AuConditionMutex.Linux.cpp
Date: 2023-8-11
Author: Reece
***/
#include <Source/RuntimeInternal.hpp>
#include "AuConditionMutex.Generic.hpp"
#include "SMTYield.hpp"
#if !defined(_AURUNTIME_GENERICCV)
#include <Source/Time/Time.hpp>
namespace Aurora::Threading::Primitives
{
#define barrier() __asm__ __volatile__("sfence": : :"memory")
#define compilerReorderBarrier() __asm__ __volatile__("": : :"memory")
LinuxConditionMutex::LinuxConditionMutex()
{
}
LinuxConditionMutex::~LinuxConditionMutex()
{
}
bool LinuxConditionMutex::TryLock()
{
if (gRuntimeConfig.threadingConfig.bPreferLinuxCondMutexSpinTryLock)
{
return TryLockHeavy();
}
else
{
return TryLockNoSpin();
}
}
bool LinuxConditionMutex::TryLockNoSpin()
{
return AuAtomicTestAndSet(&this->uState_, 0) == 0;
}
bool LinuxConditionMutex::TryLockHeavy()
{
return DoTryIf([=]()
{
return TryLockNoSpin();
});
}
void LinuxConditionMutex::Lock()
{
if (TryLockHeavy())
{
return;
}
AuAtomicAdd(&this->uSleeping_, 1u);
auto state = this->uState_;
while (!(state == 0 &&
AuAtomicCompareExchange<AuUInt32>(&this->uState_, 1, state) == state))
{
int ret {};
bool bStatus {};
do
{
if ((ret = futex_wait(&this->uState_, state)) == 0)
{
bStatus = true;
break;
}
if (ret == EAGAIN || errno == EAGAIN)
{
bStatus = true;
break;
}
}
while (ret == EINTR);
RUNTIME_ASSERT_SHUTDOWN_SAFE(bStatus, "Mutex wait failed: {}", ret)
state = this->uState_;
}
AuAtomicSub(&this->uSleeping_, 1u);
}
void LinuxConditionMutex::Unlock()
{
__sync_lock_release(&this->uState_);
compilerReorderBarrier();
if (this->uSleeping_)
{
futex_wake(&this->uState_, 1);
}
}
AuUInt LinuxConditionMutex::GetOSHandle()
{
return AuMach(&this->uState_);
}
AUKN_SYM IConditionMutex *ConditionMutexNew()
{
return _new LinuxConditionMutex();
}
AUKN_SYM void ConditionMutexRelease(IConditionMutex *mutex)
{
AuSafeDelete<LinuxConditionMutex *>(mutex);
}
AUROXTL_INTERFACE_SOO_SRC_EX(AURORA_SYMBOL_EXPORT, ConditionMutex, LinuxConditionMutex)
}
#endif