#include "libANGLE/ContextMutex.h"
#include "common/system_utils.h"
#include "libANGLE/Context.h"
namespace egl
{
namespace
{
[[maybe_unused]] bool CheckThreadIdCurrent(const std::atomic<angle::ThreadId> &threadId,
angle::ThreadId *currentThreadIdOut)
{ … }
[[maybe_unused]] bool TryUpdateThreadId(std::atomic<angle::ThreadId> *threadId,
angle::ThreadId oldThreadId,
angle::ThreadId newThreadId)
{ … }
}
void ScopedContextMutexAddRefLock::lock(ContextMutex *mutex)
{ … }
ContextMutex::ContextMutex(ContextMutex *root)
: … { … }
ContextMutex::~ContextMutex()
{ … }
void ContextMutex::Merge(ContextMutex *lockedMutex, ContextMutex *otherMutex)
{ … }
void ContextMutex::setNewRoot(ContextMutex *newRoot)
{ … }
void ContextMutex::addLeaf(ContextMutex *leaf)
{ … }
void ContextMutex::removeLeaf(ContextMutex *leaf)
{ … }
void ContextMutex::release(UnlockBehaviour unlockBehaviour)
{ … }
bool ContextMutex::try_lock()
{ … }
void ContextMutex::lock()
{ … }
void ContextMutex::unlock()
{ … }
#if defined(ANGLE_ENABLE_CONTEXT_MUTEX_RECURSION)
bool ContextMutex::tryLockImpl()
{
const angle::ThreadId threadId = angle::GetCurrentThreadId();
if (ANGLE_UNLIKELY(!mMutex.try_lock()))
{
if (ANGLE_UNLIKELY(mOwnerThreadId.load(std::memory_order_relaxed) == threadId))
{
ASSERT(this == getRoot());
ASSERT(mLockLevel > 0);
++mLockLevel;
return true;
}
return false;
}
ASSERT(mOwnerThreadId.load(std::memory_order_relaxed) == angle::InvalidThreadId());
ASSERT(mLockLevel == 0);
ContextMutex *const root = getRoot();
if (ANGLE_UNLIKELY(this != root))
{
mMutex.unlock();
return root->tryLockImpl();
}
mOwnerThreadId.store(threadId, std::memory_order_relaxed);
mLockLevel = 1;
return true;
}
void ContextMutex::lockImpl()
{
const angle::ThreadId threadId = angle::GetCurrentThreadId();
if (ANGLE_UNLIKELY(!mMutex.try_lock()))
{
if (ANGLE_UNLIKELY(mOwnerThreadId.load(std::memory_order_relaxed) == threadId))
{
ASSERT(this == getRoot());
ASSERT(mLockLevel > 0);
++mLockLevel;
return;
}
mMutex.lock();
}
ASSERT(mOwnerThreadId.load(std::memory_order_relaxed) == angle::InvalidThreadId());
ASSERT(mLockLevel == 0);
ContextMutex *const root = getRoot();
if (ANGLE_UNLIKELY(this != root))
{
mMutex.unlock();
root->lockImpl();
}
else
{
mOwnerThreadId.store(threadId, std::memory_order_relaxed);
mLockLevel = 1;
}
}
void ContextMutex::unlockImpl()
{
ASSERT(mOwnerThreadId.load(std::memory_order_relaxed) == angle::GetCurrentThreadId());
ASSERT(mLockLevel > 0);
if (ANGLE_LIKELY(--mLockLevel == 0))
{
mOwnerThreadId.store(angle::InvalidThreadId(), std::memory_order_relaxed);
mMutex.unlock();
}
}
#else
bool ContextMutex::tryLockImpl()
{ … }
void ContextMutex::lockImpl()
{ … }
void ContextMutex::unlockImpl()
{ … }
#endif
}