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 17 using gwp_asan::Mutex; 18 using gwp_asan::ScopedLock; 19 20 TEST(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 35 TEST(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 54 static 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 66 static 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 86 TEST(GwpAsanMutexTest, SynchronisedCounterTest) { 87 runSynchronisedTest(4, 1000000); 88 runSynchronisedTest(100, 1000000); 89 } 90