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