184 lines
3.9 KiB
C++
184 lines
3.9 KiB
C++
/***
|
|
Copyright (C) 2021-2024 J Reece Wilson (a/k/a "Reece"). All rights reserved.
|
|
|
|
File: Mutex.Generic.cpp
|
|
Date: 2021-6-12
|
|
Author: Reece
|
|
***/
|
|
#include <Source/RuntimeInternal.hpp>
|
|
#include "AuMutex.Generic.hpp"
|
|
#include "../AuWakeInternal.hpp"
|
|
#include "SMTYield.hpp"
|
|
|
|
#if defined(_AURUNTIME_GENERIC_MUTEX)
|
|
|
|
namespace Aurora::Threading::Primitives
|
|
{
|
|
MutexGenericImpl::MutexGenericImpl()
|
|
{
|
|
this->state_ = 0;
|
|
}
|
|
|
|
MutexGenericImpl::~MutexGenericImpl()
|
|
{
|
|
|
|
}
|
|
|
|
bool MutexGenericImpl::HasOSHandle(AuMach &mach)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
bool MutexGenericImpl::HasLockImplementation()
|
|
{
|
|
return true;
|
|
}
|
|
|
|
bool MutexGenericImpl::TryLock()
|
|
{
|
|
if (ThrdCfg::gPreferUnixPrimitivesNoSpin)
|
|
{
|
|
return this->TryLockNoSpin();
|
|
}
|
|
else
|
|
{
|
|
return this->TryLockHeavy();
|
|
}
|
|
}
|
|
|
|
bool MutexGenericImpl::TryLockNoSpin()
|
|
{
|
|
return AuAtomicTestAndSet(&this->state_, 0) == 0;
|
|
}
|
|
|
|
bool MutexGenericImpl::TryLockHeavy()
|
|
{
|
|
return DoTryIfAlderLake([=]()
|
|
{
|
|
return this->TryLockNoSpin();
|
|
}, &this->state_);
|
|
}
|
|
|
|
bool MutexGenericImpl::LockMS(AuUInt64 uTimeout)
|
|
{
|
|
return this->LockNS(AuMSToNS<AuUInt64>(uTimeout));
|
|
}
|
|
|
|
bool MutexGenericImpl::LockNS(AuUInt64 uTimeout)
|
|
{
|
|
AuUInt64 uStart {};
|
|
AuUInt64 uEnd {};
|
|
bool bStatus { true };
|
|
|
|
if (this->TryLockNoSpin())
|
|
{
|
|
return true;
|
|
}
|
|
|
|
if (uTimeout != 0)
|
|
{
|
|
uStart = AuTime::SteadyClockNS();
|
|
uEnd = uStart + uTimeout;
|
|
}
|
|
|
|
if (this->TryLock())
|
|
{
|
|
return true;
|
|
}
|
|
|
|
AuAtomicAdd(&this->dwSleeping_, 1u);
|
|
|
|
while (!this->TryLockNoSpin())
|
|
{
|
|
static const AuUInt32 kRef { 1 };
|
|
|
|
if (uTimeout != 0)
|
|
{
|
|
if (!InternalLTSWaitOnAddressHighRes((void *)&this->state_, &kRef, 4, uEnd))
|
|
{
|
|
bStatus = false;
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
(void)InternalLTSWaitOnAddressHighRes((void *)&this->state_, &kRef, 4, uEnd);
|
|
}
|
|
}
|
|
|
|
AuAtomicSub(&this->dwSleeping_, 1u);
|
|
return bStatus;
|
|
}
|
|
|
|
bool MutexGenericImpl::LockAbsNS(AuUInt64 uEndTime)
|
|
{
|
|
bool bStatus { true };
|
|
|
|
if (ThrdCfg::gPreferUnixPrimitivesNoSpin)
|
|
{
|
|
if (this->TryLockNoSpin())
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (this->TryLockHeavy())
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
|
|
AuAtomicAdd(&this->dwSleeping_, 1u);
|
|
|
|
while (!this->TryLockNoSpin())
|
|
{
|
|
static const AuUInt32 kRef { 1 };
|
|
|
|
if (uEndTime != 0)
|
|
{
|
|
if (!InternalLTSWaitOnAddressHighRes((void *)&this->state_, &kRef, 4, uEndTime))
|
|
{
|
|
bStatus = false;
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
(void)InternalLTSWaitOnAddressHighRes((void *)&this->state_, &kRef, 4, uEndTime);
|
|
}
|
|
}
|
|
|
|
AuAtomicSub(&this->dwSleeping_, 1u);
|
|
return bStatus;
|
|
}
|
|
|
|
void MutexGenericImpl::SlowLock()
|
|
{
|
|
(void)this->LockAbsNS(0);
|
|
}
|
|
|
|
void MutexGenericImpl::Unlock()
|
|
{
|
|
AuAtomicClearU8Lock(&this->state_);
|
|
|
|
if (AuAtomicLoad(&this->dwSleeping_))
|
|
{
|
|
InternalLTSWakeOne((void *)&this->state_);
|
|
}
|
|
}
|
|
|
|
AUKN_SYM IHyperWaitable *MutexNew()
|
|
{
|
|
return _new MutexGenericImpl();
|
|
}
|
|
|
|
AUKN_SYM void MutexRelease(IHyperWaitable *pMutex)
|
|
{
|
|
AuSafeDelete<MutexGenericImpl *>(pMutex);
|
|
}
|
|
|
|
AUROXTL_INTERFACE_SOO_SRC_EX(AURORA_SYMBOL_EXPORT, Mutex, MutexGenericImpl)
|
|
|
|
}
|
|
#endif |