1//===-- mutex_test.cpp ------------------------------------------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include "gwp_asan/mutex.h"
10#include "gwp_asan/tests/harness.h"
11
12#include <atomic>
13#include <mutex>
14#include <thread>
15#include <vector>
16
17using gwp_asan::Mutex;
18using gwp_asan::ScopedLock;
19
20TEST(GwpAsanMutexTest, LockUnlockTest) {
21 Mutex Mu;
22
23 ASSERT_TRUE(Mu.tryLock());
24 ASSERT_FALSE(Mu.tryLock());
25 Mu.unlock();
26
27 Mu.lock();
28 Mu.unlock();
29
30 // Ensure that the mutex actually unlocked.
31 ASSERT_TRUE(Mu.tryLock());
32 Mu.unlock();
33}
34
35TEST(GwpAsanMutexTest, ScopedLockUnlockTest) {
36 Mutex Mu;
37 { ScopedLock L(Mu); }
38 // Locking will fail here if the scoped lock failed to unlock.
39 EXPECT_TRUE(Mu.tryLock());
40 Mu.unlock();
41
42 {
43 ScopedLock L(Mu);
44 EXPECT_FALSE(Mu.tryLock()); // Check that the c'tor did lock.
45
46 // Manually unlock and check that this succeeds.
47 Mu.unlock();
48 EXPECT_TRUE(Mu.tryLock()); // Manually lock.
49 }
50 EXPECT_TRUE(Mu.tryLock()); // Assert that the scoped destructor did unlock.
51 Mu.unlock();
52}
53
54static void synchronousIncrementTask(std::atomic<bool> *StartingGun, Mutex *Mu,
55 unsigned *Counter,
56 unsigned NumIterations) {
57 while (!StartingGun) {
58 // Wait for starting gun.
59 }
60 for (unsigned i = 0; i < NumIterations; ++i) {
61 ScopedLock L(*Mu);
62 (*Counter)++;
63 }
64}
65
66static void runSynchronisedTest(unsigned NumThreads, unsigned CounterMax) {
67 std::vector<std::thread> Threads;
68
69 ASSERT_TRUE(CounterMax % NumThreads == 0);
70
71 std::atomic<bool> StartingGun{false};
72 Mutex Mu;
73 unsigned Counter = 0;
74
75 for (unsigned i = 0; i < NumThreads; ++i)
76 Threads.emplace_back(synchronousIncrementTask, &StartingGun, &Mu, &Counter,
77 CounterMax / NumThreads);
78
79 StartingGun = true;
80 for (auto &T : Threads)
81 T.join();
82
83 EXPECT_EQ(CounterMax, Counter);
84}
85
86TEST(GwpAsanMutexTest, SynchronisedCounterTest) {
87 runSynchronisedTest(NumThreads: 4, CounterMax: 1000000);
88 runSynchronisedTest(NumThreads: 100, CounterMax: 1000000);
89}
90

source code of compiler-rt/lib/gwp_asan/tests/mutex_test.cpp