AuroraRuntime/Source/IO/Loop/LSLocalMutex.cpp

195 lines
4.2 KiB
C++
Raw Normal View History

2023-10-21 03:31:00 +00:00
/***
Copyright (C) 2023 J Reece Wilson (a/k/a "Reece"). All rights reserved.
File: LSLocalMutex.cpp
Date: 2023-10-21
Author: Reece
***/
#include <RuntimeInternal.hpp>
#include "LSLocalMutex.hpp"
#include <Source/Threading/Primitives/SMTYield.hpp>
namespace Aurora::IO::Loop
{
static auto const kFutexBitWake = 256u;
extern AuRWRenterableLock gWaitForMultipleALLLock;
2023-10-21 03:31:00 +00:00
LSLocalMutex::LSLocalMutex()
{
}
LSLocalMutex::~LSLocalMutex()
{
}
bool LSLocalMutex::TryInit()
{
if (!LSSemaphore::TryInit(1))
{
return false;
}
return true;
}
bool LSLocalMutex::OnTrigger(AuUInt handle)
{
if (AuAtomicLoad(&this->uAtomicWord) & kFutexBitWake)
{
(void)LSSemaphore::OnTrigger(0);
2023-10-21 03:31:00 +00:00
AuAtomicSub(&this->uAtomicWord, kFutexBitWake);
}
return this->TryTakeNoSpin();
}
bool LSLocalMutex::Unlock()
{
if (!(AuAtomicLoad(&this->uAtomicWord) & 1))
{
return false;
}
AuAtomicClearU8Lock(&this->uAtomicWord);
while (true)
{
auto uState = AuAtomicLoad(&this->uAtomicWord);
if (uState & 1)
{
return true;
}
if (uState & kFutexBitWake)
{
if (AuAtomicCompareExchange(&this->uAtomicWord, uState, uState) == uState)
{
return true;
}
else
{
continue;
}
}
if (AuAtomicCompareExchange(&this->uAtomicWord, uState + kFutexBitWake, uState) == uState)
{
LSSemaphore::AddOne();
return true;
}
}
}
bool LSLocalMutex::IsSignaled()
{
return this->TryTake();
}
2023-12-01 10:33:55 +00:00
bool LSLocalMutex::IsSignaledNoSpinIfUserland()
{
return this->TryTakeNoSpin();
}
2023-10-21 03:31:00 +00:00
ELoopSource LSLocalMutex::GetType()
{
2023-12-18 07:37:48 +00:00
return ELoopSource::eSourceFastMutex;
2023-10-21 03:31:00 +00:00
}
bool LSLocalMutex::TryTakeNoSpin()
{
return AuAtomicTestAndSet(&this->uAtomicWord, 0) == 0;
}
bool LSLocalMutex::TryTakeSpin()
{
bool bRet = Threading::Primitives::DoTryIfAlderLake([&]
2023-10-21 03:31:00 +00:00
{
return this->TryTakeNoSpin();
}, &this->uAtomicWord);
#if !defined(AU_NO_WAITMULTIPLELS_ALL_MS_PARITY)
if (!bRet && gRuntimeConfig.ioConfig.bAimCloserForNTParityWaitALL)
{
AU_LOCK_GLOBAL_GUARD(gWaitForMultipleALLLock->AsReadable());
bRet = this->TryTakeNoSpin();
}
#endif
return bRet;
2023-10-21 03:31:00 +00:00
}
bool LSLocalMutex::TryTake()
{
2023-12-01 10:33:55 +00:00
return this->TryTakeSpin();
2023-10-21 03:31:00 +00:00
}
bool LSLocalMutex::TryTakeWaitNS(AuUInt64 uEndTime)
2023-10-21 03:31:00 +00:00
{
if (this->TryTakeSpin())
{
return true;
}
while (!this->TryTakeNoSpin())
{
if (!uEndTime)
2023-10-21 03:31:00 +00:00
{
if (LSSemaphore::WaitOn(0))
{
return true;
}
}
else
{
auto uStartTime = Time::SteadyClockNS();
if (uStartTime >= uEndTime)
{
return false;
}
auto uDeltaMs = AuNSToMS<AuInt64>(uEndTime - uStartTime);
if (uDeltaMs &&
LSSemaphore::WaitOn(uDeltaMs))
2023-10-21 03:31:00 +00:00
{
return true;
}
2023-10-26 16:25:40 +00:00
else if (!uDeltaMs)
{
if (this->TryTakeSpin())
{
return true;
}
}
2023-10-21 03:31:00 +00:00
}
}
return true;
}
AUKN_SYM AuSPtr<ILSMutex> NewLSMutex()
{
#if defined(AURORA_IS_MODERNNT_DERIVED)
if (gRuntimeConfig.ioConfig.bINeedPerfectAnds)
{
return NewLSMutexSlow();
}
#endif
2023-10-21 03:31:00 +00:00
auto pMutex = AuMakeShared<LSLocalMutex>();
if (!pMutex)
{
SysPushErrorGeneric();
return {};
}
if (!pMutex->TryInit())
{
SysPushErrorNested();
return {};
}
return pMutex;
}
}