xref: /aosp_15_r20/external/angle/src/libANGLE/GlobalMutex_unittest.cpp (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
1*8975f5c5SAndroid Build Coastguard Worker //
2*8975f5c5SAndroid Build Coastguard Worker // Copyright 2023 The ANGLE Project Authors. All rights reserved.
3*8975f5c5SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
4*8975f5c5SAndroid Build Coastguard Worker // found in the LICENSE file.
5*8975f5c5SAndroid Build Coastguard Worker //
6*8975f5c5SAndroid Build Coastguard Worker // GlobalMutex_unittest:
7*8975f5c5SAndroid Build Coastguard Worker //   Tests of the Scoped<*>GlobalMutexLock classes
8*8975f5c5SAndroid Build Coastguard Worker //
9*8975f5c5SAndroid Build Coastguard Worker 
10*8975f5c5SAndroid Build Coastguard Worker #include <gtest/gtest.h>
11*8975f5c5SAndroid Build Coastguard Worker 
12*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/GlobalMutex.h"
13*8975f5c5SAndroid Build Coastguard Worker 
14*8975f5c5SAndroid Build Coastguard Worker namespace
15*8975f5c5SAndroid Build Coastguard Worker {
16*8975f5c5SAndroid Build Coastguard Worker template <class ScopedGlobalLockT, class... Args>
runBasicGlobalMutexTest(bool expectToPass,Args &&...args)17*8975f5c5SAndroid Build Coastguard Worker void runBasicGlobalMutexTest(bool expectToPass, Args &&...args)
18*8975f5c5SAndroid Build Coastguard Worker {
19*8975f5c5SAndroid Build Coastguard Worker     constexpr size_t kThreadCount    = 16;
20*8975f5c5SAndroid Build Coastguard Worker     constexpr size_t kIterationCount = 50'000;
21*8975f5c5SAndroid Build Coastguard Worker 
22*8975f5c5SAndroid Build Coastguard Worker     std::array<std::thread, kThreadCount> threads;
23*8975f5c5SAndroid Build Coastguard Worker 
24*8975f5c5SAndroid Build Coastguard Worker     std::mutex mutex;
25*8975f5c5SAndroid Build Coastguard Worker     std::condition_variable condVar;
26*8975f5c5SAndroid Build Coastguard Worker     size_t readyCount = 0;
27*8975f5c5SAndroid Build Coastguard Worker 
28*8975f5c5SAndroid Build Coastguard Worker     std::atomic<size_t> testVar;
29*8975f5c5SAndroid Build Coastguard Worker 
30*8975f5c5SAndroid Build Coastguard Worker     for (size_t i = 0; i < kThreadCount; ++i)
31*8975f5c5SAndroid Build Coastguard Worker     {
32*8975f5c5SAndroid Build Coastguard Worker         threads[i] = std::thread([&]() {
33*8975f5c5SAndroid Build Coastguard Worker             {
34*8975f5c5SAndroid Build Coastguard Worker                 std::unique_lock<std::mutex> lock(mutex);
35*8975f5c5SAndroid Build Coastguard Worker                 ++readyCount;
36*8975f5c5SAndroid Build Coastguard Worker                 if (readyCount < kThreadCount)
37*8975f5c5SAndroid Build Coastguard Worker                 {
38*8975f5c5SAndroid Build Coastguard Worker                     condVar.wait(lock, [&]() { return readyCount == kThreadCount; });
39*8975f5c5SAndroid Build Coastguard Worker                 }
40*8975f5c5SAndroid Build Coastguard Worker                 else
41*8975f5c5SAndroid Build Coastguard Worker                 {
42*8975f5c5SAndroid Build Coastguard Worker                     condVar.notify_all();
43*8975f5c5SAndroid Build Coastguard Worker                 }
44*8975f5c5SAndroid Build Coastguard Worker             }
45*8975f5c5SAndroid Build Coastguard Worker             for (size_t j = 0; j < kIterationCount; ++j)
46*8975f5c5SAndroid Build Coastguard Worker             {
47*8975f5c5SAndroid Build Coastguard Worker                 ScopedGlobalLockT lock(std::forward<Args>(args)...);
48*8975f5c5SAndroid Build Coastguard Worker                 const int local    = testVar.load(std::memory_order_relaxed);
49*8975f5c5SAndroid Build Coastguard Worker                 const int newValue = local + 1;
50*8975f5c5SAndroid Build Coastguard Worker                 testVar.store(newValue, std::memory_order_relaxed);
51*8975f5c5SAndroid Build Coastguard Worker             }
52*8975f5c5SAndroid Build Coastguard Worker         });
53*8975f5c5SAndroid Build Coastguard Worker     }
54*8975f5c5SAndroid Build Coastguard Worker 
55*8975f5c5SAndroid Build Coastguard Worker     for (size_t i = 0; i < kThreadCount; ++i)
56*8975f5c5SAndroid Build Coastguard Worker     {
57*8975f5c5SAndroid Build Coastguard Worker         threads[i].join();
58*8975f5c5SAndroid Build Coastguard Worker     }
59*8975f5c5SAndroid Build Coastguard Worker 
60*8975f5c5SAndroid Build Coastguard Worker     if (expectToPass)
61*8975f5c5SAndroid Build Coastguard Worker     {
62*8975f5c5SAndroid Build Coastguard Worker         EXPECT_EQ(testVar.load(), kThreadCount * kIterationCount);
63*8975f5c5SAndroid Build Coastguard Worker     }
64*8975f5c5SAndroid Build Coastguard Worker     else
65*8975f5c5SAndroid Build Coastguard Worker     {
66*8975f5c5SAndroid Build Coastguard Worker         EXPECT_LE(testVar.load(), kThreadCount * kIterationCount);
67*8975f5c5SAndroid Build Coastguard Worker     }
68*8975f5c5SAndroid Build Coastguard Worker }
69*8975f5c5SAndroid Build Coastguard Worker 
70*8975f5c5SAndroid Build Coastguard Worker // Tests basic usage of ScopedGlobalEGLMutexLock.
TEST(GlobalMutexTest,ScopedGlobalEGLMutexLock)71*8975f5c5SAndroid Build Coastguard Worker TEST(GlobalMutexTest, ScopedGlobalEGLMutexLock)
72*8975f5c5SAndroid Build Coastguard Worker {
73*8975f5c5SAndroid Build Coastguard Worker     runBasicGlobalMutexTest<egl::ScopedGlobalEGLMutexLock>(true);
74*8975f5c5SAndroid Build Coastguard Worker }
75*8975f5c5SAndroid Build Coastguard Worker 
76*8975f5c5SAndroid Build Coastguard Worker // Tests basic usage of ScopedOptionalGlobalMutexLock (Enabled).
TEST(GlobalMutexTest,ScopedOptionalGlobalMutexLockEnabled)77*8975f5c5SAndroid Build Coastguard Worker TEST(GlobalMutexTest, ScopedOptionalGlobalMutexLockEnabled)
78*8975f5c5SAndroid Build Coastguard Worker {
79*8975f5c5SAndroid Build Coastguard Worker     runBasicGlobalMutexTest<egl::ScopedOptionalGlobalMutexLock>(true, true);
80*8975f5c5SAndroid Build Coastguard Worker }
81*8975f5c5SAndroid Build Coastguard Worker 
82*8975f5c5SAndroid Build Coastguard Worker // Tests basic usage of ScopedOptionalGlobalMutexLock (Disabled).
TEST(GlobalMutexTest,ScopedOptionalGlobalMutexLockDisabled)83*8975f5c5SAndroid Build Coastguard Worker TEST(GlobalMutexTest, ScopedOptionalGlobalMutexLockDisabled)
84*8975f5c5SAndroid Build Coastguard Worker {
85*8975f5c5SAndroid Build Coastguard Worker     runBasicGlobalMutexTest<egl::ScopedOptionalGlobalMutexLock>(false, false);
86*8975f5c5SAndroid Build Coastguard Worker }
87*8975f5c5SAndroid Build Coastguard Worker 
88*8975f5c5SAndroid Build Coastguard Worker #if defined(ANGLE_ENABLE_GLOBAL_MUTEX_RECURSION)
89*8975f5c5SAndroid Build Coastguard Worker // Tests that ScopedGlobalEGLMutexLock can be recursively locked.
TEST(GlobalMutexTest,RecursiveScopedGlobalEGLMutexLock)90*8975f5c5SAndroid Build Coastguard Worker TEST(GlobalMutexTest, RecursiveScopedGlobalEGLMutexLock)
91*8975f5c5SAndroid Build Coastguard Worker {
92*8975f5c5SAndroid Build Coastguard Worker     egl::ScopedGlobalEGLMutexLock lock;
93*8975f5c5SAndroid Build Coastguard Worker     egl::ScopedGlobalEGLMutexLock lock2;
94*8975f5c5SAndroid Build Coastguard Worker }
95*8975f5c5SAndroid Build Coastguard Worker 
96*8975f5c5SAndroid Build Coastguard Worker // Tests that ScopedOptionalGlobalMutexLock can be recursively locked.
TEST(GlobalMutexTest,RecursiveScopedOptionalGlobalMutexLock)97*8975f5c5SAndroid Build Coastguard Worker TEST(GlobalMutexTest, RecursiveScopedOptionalGlobalMutexLock)
98*8975f5c5SAndroid Build Coastguard Worker {
99*8975f5c5SAndroid Build Coastguard Worker     egl::ScopedOptionalGlobalMutexLock lock(true);
100*8975f5c5SAndroid Build Coastguard Worker     egl::ScopedOptionalGlobalMutexLock lock2(true);
101*8975f5c5SAndroid Build Coastguard Worker }
102*8975f5c5SAndroid Build Coastguard Worker #endif
103*8975f5c5SAndroid Build Coastguard Worker 
104*8975f5c5SAndroid Build Coastguard Worker }  // anonymous namespace
105