Hash :
e5619a5c
Author :
Date :
2024-10-15T18:27:00
Use EGL sync global lock for all EGL*sync entrypoint calls To free EGL sync operations from waiting for other EGL calls to finish, we use a separate global lock for EGL*sync entrypoints. Below angle::SimpleMutex are added to protect resources that may have race condition due to being accessed by EGL*sync calls and non EGL*sync calls at the same time: 1. Display::mContextMapMutex that protects Display::mState.contextMap 2. static angle::base::NoDestructor<angle::SimpleMutex> anglePlatformDisplayMapMutex that protects static angle::base::NoDestructor<ANGLEPlatformDisplayMap> displays 3. static angle::base::NoDestructor<angle::SimpleMutex> devicePlatformDisplayMapMutex that protects static angle::base::NoDestructor<DevicePlatformDisplayMap> displays EGL_Terminate() entry point takes both global lock and global egl sync lock. This is to protect Display::mSyncMap, Display::mSyncPools, and Display::mSyncHandleAllocator being get cleared by thread 1 calling eglTerminate, while they are still accessed by thread 2 through a call such as eglCreateSync. So that we won't have thread 2 finish validating the sync object with syncID exists in Display::mSyncMap, but then find the mSyncMap.find(syncID) returns a nullptr due to the mSyncMap is cleared by thread 1. Same applies to EGL_LabelObjectKHR(), EGL_ReleaseThread(), ThreadCleanupCallback(). EGL_Initialize() writes to Display::mInitialized. This is read by EGL Sync API validation functions. EGL_Initialize() also takes both global lock and global sync lock to prevent race conditions between EGL_Initialize() and EGL Sync APIs. When ANGLE_CAPTURE_ENABLED is enabled, fall back to global lock, as the CaptureEGLCallToFrameCapture() touches many resources (e.g. mMaxAccessedResourceIDs, mFrameCalls) that could lead to race conditions without a global lock. Bug: b/362604439 Change-Id: Ic0d54a4cd66743bcd0f48f41f247dd223cff2f5e Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/5933570 Reviewed-by: Roman Lavrov <romanl@google.com> Reviewed-by: Shahbaz Youssefi <syoussefi@chromium.org> Reviewed-by: Igor Nazarov <i.nazarov@samsung.com> Commit-Queue: Yuxin Hu <yuxinhu@google.com>
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63
//
// 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.
//
// GlobalMutex.h: Defines Global Mutex and utilities.
#ifndef LIBANGLE_GLOBAL_MUTEX_H_
#define LIBANGLE_GLOBAL_MUTEX_H_
#include "common/angleutils.h"
namespace egl
{
namespace priv
{
class GlobalMutex;
enum class GlobalMutexChoice
{
// All EGL entry points except EGL Sync objects
EGL,
// Entry points relating to EGL Sync objects
Sync,
};
template <GlobalMutexChoice mutexChoice>
class [[nodiscard]] ScopedGlobalMutexLock final : angle::NonCopyable
{
public:
ScopedGlobalMutexLock();
~ScopedGlobalMutexLock();
#if !defined(ANGLE_ENABLE_GLOBAL_MUTEX_LOAD_TIME_ALLOCATE)
private:
GlobalMutex *mMutex;
#endif
};
} // namespace priv
using ScopedGlobalEGLMutexLock = priv::ScopedGlobalMutexLock<priv::GlobalMutexChoice::EGL>;
using ScopedGlobalEGLSyncObjectMutexLock =
priv::ScopedGlobalMutexLock<priv::GlobalMutexChoice::Sync>;
// For Context protection where lock is optional. Works slower than ScopedGlobalMutexLock.
class [[nodiscard]] ScopedOptionalGlobalMutexLock final : angle::NonCopyable
{
public:
explicit ScopedOptionalGlobalMutexLock(bool enabled);
~ScopedOptionalGlobalMutexLock();
private:
priv::GlobalMutex *mMutex;
};
#if defined(ANGLE_PLATFORM_WINDOWS) && !defined(ANGLE_STATIC)
void AllocateGlobalMutex();
void DeallocateGlobalMutex();
#endif
} // namespace egl
#endif // LIBANGLE_GLOBAL_MUTEX_H_