xref: /openbsd-src/gnu/llvm/compiler-rt/lib/gwp_asan/tests/mutex_test.cpp (revision d89ec533011f513df1010f142a111086a0785f09)
13cab2bb3Spatrick //===-- mutex_test.cpp ------------------------------------------*- C++ -*-===//
23cab2bb3Spatrick //
33cab2bb3Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
43cab2bb3Spatrick // See https://llvm.org/LICENSE.txt for license information.
53cab2bb3Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
63cab2bb3Spatrick //
73cab2bb3Spatrick //===----------------------------------------------------------------------===//
83cab2bb3Spatrick 
93cab2bb3Spatrick #include "gwp_asan/mutex.h"
10*d89ec533Spatrick #include "gwp_asan/tests/harness.h"
113cab2bb3Spatrick 
123cab2bb3Spatrick #include <atomic>
133cab2bb3Spatrick #include <mutex>
143cab2bb3Spatrick #include <thread>
153cab2bb3Spatrick #include <vector>
163cab2bb3Spatrick 
173cab2bb3Spatrick using gwp_asan::Mutex;
183cab2bb3Spatrick using gwp_asan::ScopedLock;
193cab2bb3Spatrick 
TEST(GwpAsanMutexTest,LockUnlockTest)203cab2bb3Spatrick TEST(GwpAsanMutexTest, LockUnlockTest) {
213cab2bb3Spatrick   Mutex Mu;
223cab2bb3Spatrick 
233cab2bb3Spatrick   ASSERT_TRUE(Mu.tryLock());
243cab2bb3Spatrick   ASSERT_FALSE(Mu.tryLock());
253cab2bb3Spatrick   Mu.unlock();
263cab2bb3Spatrick 
273cab2bb3Spatrick   Mu.lock();
283cab2bb3Spatrick   Mu.unlock();
293cab2bb3Spatrick 
303cab2bb3Spatrick   // Ensure that the mutex actually unlocked.
313cab2bb3Spatrick   ASSERT_TRUE(Mu.tryLock());
323cab2bb3Spatrick   Mu.unlock();
333cab2bb3Spatrick }
343cab2bb3Spatrick 
TEST(GwpAsanMutexTest,ScopedLockUnlockTest)353cab2bb3Spatrick TEST(GwpAsanMutexTest, ScopedLockUnlockTest) {
363cab2bb3Spatrick   Mutex Mu;
373cab2bb3Spatrick   { ScopedLock L(Mu); }
383cab2bb3Spatrick   // Locking will fail here if the scoped lock failed to unlock.
393cab2bb3Spatrick   EXPECT_TRUE(Mu.tryLock());
403cab2bb3Spatrick   Mu.unlock();
413cab2bb3Spatrick 
423cab2bb3Spatrick   {
433cab2bb3Spatrick     ScopedLock L(Mu);
443cab2bb3Spatrick     EXPECT_FALSE(Mu.tryLock()); // Check that the c'tor did lock.
453cab2bb3Spatrick 
463cab2bb3Spatrick     // Manually unlock and check that this succeeds.
473cab2bb3Spatrick     Mu.unlock();
483cab2bb3Spatrick     EXPECT_TRUE(Mu.tryLock()); // Manually lock.
493cab2bb3Spatrick   }
503cab2bb3Spatrick   EXPECT_TRUE(Mu.tryLock()); // Assert that the scoped destructor did unlock.
513cab2bb3Spatrick   Mu.unlock();
523cab2bb3Spatrick }
533cab2bb3Spatrick 
synchronousIncrementTask(std::atomic<bool> * StartingGun,Mutex * Mu,unsigned * Counter,unsigned NumIterations)543cab2bb3Spatrick static void synchronousIncrementTask(std::atomic<bool> *StartingGun, Mutex *Mu,
553cab2bb3Spatrick                                      unsigned *Counter,
563cab2bb3Spatrick                                      unsigned NumIterations) {
573cab2bb3Spatrick   while (!StartingGun) {
583cab2bb3Spatrick     // Wait for starting gun.
593cab2bb3Spatrick   }
603cab2bb3Spatrick   for (unsigned i = 0; i < NumIterations; ++i) {
613cab2bb3Spatrick     ScopedLock L(*Mu);
623cab2bb3Spatrick     (*Counter)++;
633cab2bb3Spatrick   }
643cab2bb3Spatrick }
653cab2bb3Spatrick 
runSynchronisedTest(unsigned NumThreads,unsigned CounterMax)663cab2bb3Spatrick static void runSynchronisedTest(unsigned NumThreads, unsigned CounterMax) {
673cab2bb3Spatrick   std::vector<std::thread> Threads;
683cab2bb3Spatrick 
693cab2bb3Spatrick   ASSERT_TRUE(CounterMax % NumThreads == 0);
703cab2bb3Spatrick 
713cab2bb3Spatrick   std::atomic<bool> StartingGun{false};
723cab2bb3Spatrick   Mutex Mu;
733cab2bb3Spatrick   unsigned Counter = 0;
743cab2bb3Spatrick 
753cab2bb3Spatrick   for (unsigned i = 0; i < NumThreads; ++i)
763cab2bb3Spatrick     Threads.emplace_back(synchronousIncrementTask, &StartingGun, &Mu, &Counter,
773cab2bb3Spatrick                          CounterMax / NumThreads);
783cab2bb3Spatrick 
793cab2bb3Spatrick   StartingGun = true;
803cab2bb3Spatrick   for (auto &T : Threads)
813cab2bb3Spatrick     T.join();
823cab2bb3Spatrick 
833cab2bb3Spatrick   EXPECT_EQ(CounterMax, Counter);
843cab2bb3Spatrick }
853cab2bb3Spatrick 
TEST(GwpAsanMutexTest,SynchronisedCounterTest)863cab2bb3Spatrick TEST(GwpAsanMutexTest, SynchronisedCounterTest) {
873cab2bb3Spatrick   runSynchronisedTest(4, 1000000);
883cab2bb3Spatrick   runSynchronisedTest(100, 1000000);
893cab2bb3Spatrick }
90