diff options
Diffstat (limited to 'compiler-rt/lib/gwp_asan/tests/mutex_test.cpp')
| -rw-r--r-- | compiler-rt/lib/gwp_asan/tests/mutex_test.cpp | 89 |
1 files changed, 89 insertions, 0 deletions
diff --git a/compiler-rt/lib/gwp_asan/tests/mutex_test.cpp b/compiler-rt/lib/gwp_asan/tests/mutex_test.cpp new file mode 100644 index 00000000000..36f7e1d2323 --- /dev/null +++ b/compiler-rt/lib/gwp_asan/tests/mutex_test.cpp @@ -0,0 +1,89 @@ +//===-- mutex_test.cpp ------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "gwp_asan/mutex.h" +#include "gtest/gtest.h" + +#include <atomic> +#include <mutex> +#include <thread> +#include <vector> + +using gwp_asan::Mutex; +using gwp_asan::ScopedLock; + +TEST(GwpAsanMutexTest, LockUnlockTest) { + Mutex Mu; + + ASSERT_TRUE(Mu.tryLock()); + ASSERT_FALSE(Mu.tryLock()); + Mu.unlock(); + + Mu.lock(); + Mu.unlock(); + + // Ensure that the mutex actually unlocked. + ASSERT_TRUE(Mu.tryLock()); + Mu.unlock(); +} + +TEST(GwpAsanMutexTest, ScopedLockUnlockTest) { + Mutex Mu; + { ScopedLock L(Mu); } + // Locking will fail here if the scoped lock failed to unlock. + EXPECT_TRUE(Mu.tryLock()); + Mu.unlock(); + + { + ScopedLock L(Mu); + EXPECT_FALSE(Mu.tryLock()); // Check that the c'tor did lock. + + // Manually unlock and check that this succeeds. + Mu.unlock(); + EXPECT_TRUE(Mu.tryLock()); // Manually lock. + } + EXPECT_TRUE(Mu.tryLock()); // Assert that the scoped destructor did unlock. + Mu.unlock(); +} + +static void synchronousIncrementTask(std::atomic<bool> *StartingGun, Mutex *Mu, + unsigned *Counter, + unsigned NumIterations) { + while (!StartingGun) { + // Wait for starting gun. + } + for (unsigned i = 0; i < NumIterations; ++i) { + ScopedLock L(*Mu); + (*Counter)++; + } +} + +static void runSynchronisedTest(unsigned NumThreads, unsigned CounterMax) { + std::vector<std::thread> Threads; + + ASSERT_TRUE(CounterMax % NumThreads == 0); + + std::atomic<bool> StartingGun{false}; + Mutex Mu; + unsigned Counter = 0; + + for (unsigned i = 0; i < NumThreads; ++i) + Threads.emplace_back(synchronousIncrementTask, &StartingGun, &Mu, &Counter, + CounterMax / NumThreads); + + StartingGun = true; + for (auto &T : Threads) + T.join(); + + EXPECT_EQ(CounterMax, Counter); +} + +TEST(GwpAsanMutexTest, SynchronisedCounterTest) { + runSynchronisedTest(4, 100000); + runSynchronisedTest(1000, 1000000); +} |

