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;
|
2024-10-10 10:03:26 +00:00
|
|
|
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)
|
|
|
|
{
|
2023-12-01 10:55:24 +00:00
|
|
|
(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()
|
|
|
|
{
|
2024-10-10 10:03:26 +00:00
|
|
|
bool bRet = Threading::Primitives::DoTryIfAlderLake([&]
|
2023-10-21 03:31:00 +00:00
|
|
|
{
|
|
|
|
return this->TryTakeNoSpin();
|
2024-05-03 11:14:52 +00:00
|
|
|
}, &this->uAtomicWord);
|
2024-10-10 10:03:26 +00:00
|
|
|
|
|
|
|
#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
|
|
|
}
|
|
|
|
|
2024-09-07 21:45:34 +00:00
|
|
|
bool LSLocalMutex::TryTakeWaitNS(AuUInt64 uEndTime)
|
2023-10-21 03:31:00 +00:00
|
|
|
{
|
|
|
|
if (this->TryTakeSpin())
|
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
while (!this->TryTakeNoSpin())
|
|
|
|
{
|
2024-09-07 21:45:34 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2023-10-21 04:34:35 +00:00
|
|
|
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()
|
|
|
|
{
|
2024-10-10 10:03:26 +00:00
|
|
|
#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;
|
|
|
|
}
|
|
|
|
}
|