chromium/third_party/angle/src/libANGLE/ContextMutex.cpp

//
// Copyright 2023 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// ContextMutex.cpp: Classes for protecting Context access and EGLImage siblings.

#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)
{}
}  // namespace

// ScopedContextMutexAddRefLock
void ScopedContextMutexAddRefLock::lock(ContextMutex *mutex)
{}

// ContextMutex
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))
    {
        // Unlock, so only the "stable root" mutex remains locked
        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))
    {
        // Unlock, so only the "stable root" mutex remains locked
        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

}  // namespace egl