summaryrefslogtreecommitdiffstats
path: root/compiler-rt/lib/gwp_asan/tests/mutex_test.cpp
diff options
context:
space:
mode:
authorMitch Phillips <mitchphillips@outlook.com>2019-05-30 19:45:32 +0000
committerMitch Phillips <mitchphillips@outlook.com>2019-05-30 19:45:32 +0000
commit5f0f4e3ae03afa84034c01ddaac559e0b5cb6532 (patch)
treea4d1f0c352380fb97a3eef96bf4537a179f0dac8 /compiler-rt/lib/gwp_asan/tests/mutex_test.cpp
parent04a38b924e7e37ad166b3f73f229411e3a2dfa25 (diff)
downloadbcm5719-llvm-5f0f4e3ae03afa84034c01ddaac559e0b5cb6532.tar.gz
bcm5719-llvm-5f0f4e3ae03afa84034c01ddaac559e0b5cb6532.zip
[GWP-ASan] Mutex implementation [2].
Summary: See D60593 for further information. This patch pulls out the mutex implementation and the required definitions file. We implement our own mutex for GWP-ASan currently, because: 1. We must be compatible with the sum of the most restrictive elements of the supporting allocator's build system. Current targets for GWP-ASan include Scudo (on Linux and Fuchsia), and bionic (on Android). 2. Scudo specifies `-nostdlib++ -nonodefaultlibs`, meaning we can't use `std::mutex` or `mtx_t`. 3. We can't use `sanitizer_common`'s mutex, as the supporting allocators cannot afford the extra maintenance (Android, Fuchsia) and code size (Fuchsia) overheads that this would incur. In future, we would like to implement a shared base mutex for GWP-ASan, Scudo and sanitizer_common. This will likely happen when both GWP-ASan and Scudo standalone are not in the development phase, at which point they will have stable requirements. Reviewers: vlad.tsyrklevich, morehouse, jfb Reviewed By: morehouse Subscribers: dexonsmith, srhines, cfe-commits, kubamracek, mgorny, cryptoad, jfb, #sanitizers, llvm-commits, vitalybuka, eugenis Tags: #sanitizers, #llvm, #clang Differential Revision: https://reviews.llvm.org/D61923 llvm-svn: 362138
Diffstat (limited to 'compiler-rt/lib/gwp_asan/tests/mutex_test.cpp')
-rw-r--r--compiler-rt/lib/gwp_asan/tests/mutex_test.cpp89
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);
+}
OpenPOWER on IntegriCloud