diff options
| author | Mitch Phillips <mitchphillips@outlook.com> | 2019-05-30 19:45:32 +0000 |
|---|---|---|
| committer | Mitch Phillips <mitchphillips@outlook.com> | 2019-05-30 19:45:32 +0000 |
| commit | 5f0f4e3ae03afa84034c01ddaac559e0b5cb6532 (patch) | |
| tree | a4d1f0c352380fb97a3eef96bf4537a179f0dac8 /compiler-rt/lib/gwp_asan/tests/mutex_test.cpp | |
| parent | 04a38b924e7e37ad166b3f73f229411e3a2dfa25 (diff) | |
| download | bcm5719-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.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); +} |

