[compiler-rt] r362138 - [GWP-ASan] Mutex implementation [2].
Mitch Phillips via llvm-commits
llvm-commits at lists.llvm.org
Thu May 30 12:45:32 PDT 2019
Author: hctim
Date: Thu May 30 12:45:32 2019
New Revision: 362138
URL: http://llvm.org/viewvc/llvm-project?rev=362138&view=rev
Log:
[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
Added:
compiler-rt/trunk/lib/gwp_asan/mutex.h
compiler-rt/trunk/lib/gwp_asan/platform_specific/
compiler-rt/trunk/lib/gwp_asan/platform_specific/mutex_posix.cpp
compiler-rt/trunk/lib/gwp_asan/tests/
compiler-rt/trunk/lib/gwp_asan/tests/CMakeLists.txt
compiler-rt/trunk/lib/gwp_asan/tests/driver.cpp
compiler-rt/trunk/lib/gwp_asan/tests/mutex_test.cpp
compiler-rt/trunk/test/gwp_asan/dummy_test.cc
compiler-rt/trunk/test/gwp_asan/lit.cfg
compiler-rt/trunk/test/gwp_asan/lit.site.cfg.in
compiler-rt/trunk/test/gwp_asan/unit/
compiler-rt/trunk/test/gwp_asan/unit/lit.site.cfg.in
Modified:
compiler-rt/trunk/lib/gwp_asan/CMakeLists.txt
compiler-rt/trunk/test/gwp_asan/CMakeLists.txt
Modified: compiler-rt/trunk/lib/gwp_asan/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/gwp_asan/CMakeLists.txt?rev=362138&r1=362137&r2=362138&view=diff
==============================================================================
--- compiler-rt/trunk/lib/gwp_asan/CMakeLists.txt (original)
+++ compiler-rt/trunk/lib/gwp_asan/CMakeLists.txt Thu May 30 12:45:32 2019
@@ -3,17 +3,19 @@ add_compiler_rt_component(gwp_asan)
include_directories(..)
set(GWP_ASAN_SOURCES
+ platform_specific/mutex_posix.cpp
random.cpp
)
set(GWP_ASAN_HEADERS
+ mutex.h
random.h
)
# Ensure that GWP-ASan meets the delegated requirements of some supporting
# allocators. Some supporting allocators (e.g. scudo standalone) cannot use any
# parts of the C++ standard library.
-set(GWP_ASAN_CFLAGS -fno-rtti -fno-exceptions -nostdinc++)
+set(GWP_ASAN_CFLAGS -fno-rtti -fno-exceptions -nostdinc++ -pthread)
# Remove -stdlib= which is unused when passing -nostdinc++.
string(REGEX REPLACE "-stdlib=[a-zA-Z+]*" "" CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS})
@@ -37,3 +39,7 @@ if (COMPILER_RT_HAS_GWP_ASAN)
ADDITIONAL_HEADERS ${GWP_ASAN_HEADERS}
CFLAGS ${GWP_ASAN_CFLAGS})
endif()
+
+if(COMPILER_RT_INCLUDE_TESTS)
+ add_subdirectory(tests)
+endif()
Added: compiler-rt/trunk/lib/gwp_asan/mutex.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/gwp_asan/mutex.h?rev=362138&view=auto
==============================================================================
--- compiler-rt/trunk/lib/gwp_asan/mutex.h (added)
+++ compiler-rt/trunk/lib/gwp_asan/mutex.h Thu May 30 12:45:32 2019
@@ -0,0 +1,50 @@
+//===-- mutex.h -------------------------------------------------*- 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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef GWP_ASAN_MUTEX_H_
+#define GWP_ASAN_MUTEX_H_
+
+#ifdef __unix__
+#include <pthread.h>
+#else
+#error "GWP-ASan is not supported on this platform."
+#endif
+
+namespace gwp_asan {
+class Mutex {
+public:
+ constexpr Mutex() = default;
+ ~Mutex() = default;
+ Mutex(const Mutex &) = delete;
+ Mutex &operator=(const Mutex &) = delete;
+ // Lock the mutex.
+ void lock();
+ // Nonblocking trylock of the mutex. Returns true if the lock was acquired.
+ bool tryLock();
+ // Unlock the mutex.
+ void unlock();
+
+private:
+#ifdef __unix__
+ pthread_mutex_t Mu = PTHREAD_MUTEX_INITIALIZER;
+#endif // defined(__unix__)
+};
+
+class ScopedLock {
+public:
+ explicit ScopedLock(Mutex &Mx) : Mu(Mx) { Mu.lock(); }
+ ~ScopedLock() { Mu.unlock(); }
+ ScopedLock(const ScopedLock &) = delete;
+ ScopedLock &operator=(const ScopedLock &) = delete;
+
+private:
+ Mutex Μ
+};
+} // namespace gwp_asan
+
+#endif // GWP_ASAN_MUTEX_H_
Added: compiler-rt/trunk/lib/gwp_asan/platform_specific/mutex_posix.cpp
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/gwp_asan/platform_specific/mutex_posix.cpp?rev=362138&view=auto
==============================================================================
--- compiler-rt/trunk/lib/gwp_asan/platform_specific/mutex_posix.cpp (added)
+++ compiler-rt/trunk/lib/gwp_asan/platform_specific/mutex_posix.cpp Thu May 30 12:45:32 2019
@@ -0,0 +1,30 @@
+//===-- mutex_posix.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 "mutex.h"
+
+#include <assert.h>
+#include <pthread.h>
+
+namespace gwp_asan {
+void Mutex::lock() {
+ int Status = pthread_mutex_lock(&Mu);
+ assert(Status == 0);
+ // Remove warning for non-debug builds.
+ (void)Status;
+}
+
+bool Mutex::tryLock() { return pthread_mutex_trylock(&Mu) == 0; }
+
+void Mutex::unlock() {
+ int Status = pthread_mutex_unlock(&Mu);
+ assert(Status == 0);
+ // Remove warning for non-debug builds.
+ (void)Status;
+}
+} // namespace gwp_asan
Added: compiler-rt/trunk/lib/gwp_asan/tests/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/gwp_asan/tests/CMakeLists.txt?rev=362138&view=auto
==============================================================================
--- compiler-rt/trunk/lib/gwp_asan/tests/CMakeLists.txt (added)
+++ compiler-rt/trunk/lib/gwp_asan/tests/CMakeLists.txt Thu May 30 12:45:32 2019
@@ -0,0 +1,49 @@
+include(CompilerRTCompile)
+
+set(GWP_ASAN_UNITTEST_CFLAGS
+ ${COMPILER_RT_UNITTEST_CFLAGS}
+ ${COMPILER_RT_GTEST_CFLAGS}
+ -I${COMPILER_RT_SOURCE_DIR}/lib/
+ -O2)
+
+file(GLOB GWP_ASAN_HEADERS ../*.h)
+file(GLOB GWP_ASAN_UNITTESTS *.cpp)
+set(GWP_ASAN_UNIT_TEST_HEADERS
+ ${GWP_ASAN_HEADERS})
+
+add_custom_target(GwpAsanUnitTests)
+set_target_properties(GwpAsanUnitTests PROPERTIES FOLDER "Compiler-RT Tests")
+
+set(GWP_ASAN_UNITTEST_LINK_FLAGS ${COMPILER_RT_UNITTEST_LINK_FLAGS})
+list(APPEND GWP_ASAN_UNITTEST_LINK_FLAGS --driver-mode=g++)
+if(NOT WIN32)
+ list(APPEND GWP_ASAN_UNITTEST_LINK_FLAGS -lpthread)
+endif()
+
+if(COMPILER_RT_DEFAULT_TARGET_ARCH IN_LIST GWP_ASAN_SUPPORTED_ARCH)
+ # GWP-ASan unit tests are only run on the host machine.
+ set(arch ${COMPILER_RT_DEFAULT_TARGET_ARCH})
+
+ set(GWP_ASAN_TEST_RUNTIME RTGwpAsanTest.${arch})
+
+ set(GWP_ASAN_TEST_RUNTIME_OBJECTS
+ $<TARGET_OBJECTS:RTGwpAsan.${arch}>)
+
+ add_library(${GWP_ASAN_TEST_RUNTIME} STATIC
+ ${GWP_ASAN_TEST_RUNTIME_OBJECTS})
+
+ set_target_properties(${GWP_ASAN_TEST_RUNTIME} PROPERTIES
+ ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
+ FOLDER "Compiler-RT Runtime tests")
+
+ set(GwpAsanTestObjects)
+ generate_compiler_rt_tests(GwpAsanTestObjects
+ GwpAsanUnitTests "GwpAsan-${arch}-Test" ${arch}
+ SOURCES ${GWP_ASAN_UNITTESTS} ${COMPILER_RT_GTEST_SOURCE}
+ RUNTIME ${GWP_ASAN_TEST_RUNTIME}
+ DEPS gtest ${GWP_ASAN_UNIT_TEST_HEADERS}
+ CFLAGS ${GWP_ASAN_UNITTEST_CFLAGS}
+ LINK_FLAGS ${GWP_ASAN_UNITTEST_LINK_FLAGS})
+ set_target_properties(GwpAsanUnitTests PROPERTIES
+ RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
+endif()
Added: compiler-rt/trunk/lib/gwp_asan/tests/driver.cpp
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/gwp_asan/tests/driver.cpp?rev=362138&view=auto
==============================================================================
--- compiler-rt/trunk/lib/gwp_asan/tests/driver.cpp (added)
+++ compiler-rt/trunk/lib/gwp_asan/tests/driver.cpp Thu May 30 12:45:32 2019
@@ -0,0 +1,14 @@
+//===-- driver.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 "gtest/gtest.h"
+
+int main(int argc, char **argv) {
+ testing::InitGoogleTest(&argc, argv);
+ return RUN_ALL_TESTS();
+}
Added: compiler-rt/trunk/lib/gwp_asan/tests/mutex_test.cpp
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/gwp_asan/tests/mutex_test.cpp?rev=362138&view=auto
==============================================================================
--- compiler-rt/trunk/lib/gwp_asan/tests/mutex_test.cpp (added)
+++ compiler-rt/trunk/lib/gwp_asan/tests/mutex_test.cpp Thu May 30 12:45:32 2019
@@ -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);
+}
Modified: compiler-rt/trunk/test/gwp_asan/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/gwp_asan/CMakeLists.txt?rev=362138&r1=362137&r2=362138&view=diff
==============================================================================
--- compiler-rt/trunk/test/gwp_asan/CMakeLists.txt (original)
+++ compiler-rt/trunk/test/gwp_asan/CMakeLists.txt Thu May 30 12:45:32 2019
@@ -0,0 +1,45 @@
+set(GWP_ASAN_LIT_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR})
+set(GWP_ASAN_LIT_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR})
+
+set(GWP_ASAN_TESTSUITES)
+
+set(GWP_ASAN_UNITTEST_DEPS)
+set(GWP_ASAN_TEST_DEPS
+ ${SANITIZER_COMMON_LIT_TEST_DEPS}
+ gwp_asan)
+
+if (COMPILER_RT_INCLUDE_TESTS)
+ list(APPEND GWP_ASAN_TEST_DEPS GwpAsanUnitTests)
+ configure_lit_site_cfg(
+ ${CMAKE_CURRENT_SOURCE_DIR}/unit/lit.site.cfg.in
+ ${CMAKE_CURRENT_BINARY_DIR}/unit/lit.site.cfg)
+ add_lit_testsuite(check-gwp_asan-unit "Running GWP-ASan unit tests"
+ ${CMAKE_CURRENT_BINARY_DIR}/unit
+ DEPENDS ${GWP_ASAN_TEST_DEPS})
+ set_target_properties(check-gwp_asan-unit PROPERTIES FOLDER
+ "Compiler-RT Tests")
+ list(APPEND GWP_ASAN_TEST_DEPS check-gwp_asan-unit)
+endif()
+
+configure_lit_site_cfg(
+ ${CMAKE_CURRENT_SOURCE_DIR}/lit.site.cfg.in
+ ${CMAKE_CURRENT_BINARY_DIR}/lit.site.cfg
+ )
+
+foreach(arch ${GWP_ASAN_SUPPORTED_ARCH})
+ set(GWP_ASAN_TEST_TARGET_ARCH ${arch})
+ string(TOLOWER "-${arch}" GWP_ASAN_TEST_CONFIG_SUFFIX)
+ get_test_cc_for_arch(${arch} GWP_ASAN_TEST_TARGET_CC GWP_ASAN_TEST_TARGET_CFLAGS)
+ string(TOUPPER ${arch} ARCH_UPPER_CASE)
+ set(CONFIG_NAME ${ARCH_UPPER_CASE}${OS_NAME}Config)
+
+ configure_lit_site_cfg(
+ ${CMAKE_CURRENT_SOURCE_DIR}/lit.site.cfg.in
+ ${CMAKE_CURRENT_BINARY_DIR}/${CONFIG_NAME}/lit.site.cfg)
+ list(APPEND GWP_ASAN_TESTSUITES ${CMAKE_CURRENT_BINARY_DIR}/${CONFIG_NAME})
+endforeach()
+
+add_lit_testsuite(check-gwp_asan "Running the GWP-ASan tests"
+ ${GWP_ASAN_TESTSUITES}
+ DEPENDS ${GWP_ASAN_TEST_DEPS})
+set_target_properties(check-gwp_asan PROPERTIES FOLDER "Compiler-RT Misc")
Added: compiler-rt/trunk/test/gwp_asan/dummy_test.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/gwp_asan/dummy_test.cc?rev=362138&view=auto
==============================================================================
--- compiler-rt/trunk/test/gwp_asan/dummy_test.cc (added)
+++ compiler-rt/trunk/test/gwp_asan/dummy_test.cc Thu May 30 12:45:32 2019
@@ -0,0 +1,4 @@
+// Exists to simply stop warnings about lit not discovering any tests here.
+// RUN: %clang %s
+
+int main() { return 0; }
Added: compiler-rt/trunk/test/gwp_asan/lit.cfg
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/gwp_asan/lit.cfg?rev=362138&view=auto
==============================================================================
--- compiler-rt/trunk/test/gwp_asan/lit.cfg (added)
+++ compiler-rt/trunk/test/gwp_asan/lit.cfg Thu May 30 12:45:32 2019
@@ -0,0 +1,31 @@
+# -*- Python -*-
+
+import os
+
+# Setup config name.
+config.name = 'GWP-ASan' + config.name_suffix
+
+# Setup source root.
+config.test_source_root = os.path.dirname(__file__)
+
+# Test suffixes.
+config.suffixes = ['.c', '.cc', '.cpp', '.test']
+
+# C & CXX flags.
+c_flags = ([config.target_cflags])
+
+# Android doesn't want -lrt.
+if not config.android:
+ c_flags += ["-lrt"]
+
+cxx_flags = (c_flags + config.cxx_mode_flags + ["-std=c++11"])
+
+def build_invocation(compile_flags):
+ return " " + " ".join([config.clang] + compile_flags) + " "
+
+# Add substitutions.
+config.substitutions.append(("%clang ", build_invocation(c_flags)))
+
+# GWP-ASan tests are currently supported on Linux only.
+if config.host_os not in ['Linux']:
+ config.unsupported = True
Added: compiler-rt/trunk/test/gwp_asan/lit.site.cfg.in
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/gwp_asan/lit.site.cfg.in?rev=362138&view=auto
==============================================================================
--- compiler-rt/trunk/test/gwp_asan/lit.site.cfg.in (added)
+++ compiler-rt/trunk/test/gwp_asan/lit.site.cfg.in Thu May 30 12:45:32 2019
@@ -0,0 +1,11 @@
+ at LIT_SITE_CFG_IN_HEADER@
+
+config.name_suffix = "@GWP_ASAN_TEST_CONFIG_SUFFIX@"
+config.target_arch = "@GWP_ASAN_TEST_TARGET_ARCH@"
+config.target_cflags = "@GWP_ASAN_TEST_TARGET_CFLAGS@"
+
+# Load common config for all compiler-rt lit tests.
+lit_config.load_config(config, "@COMPILER_RT_BINARY_DIR@/test/lit.common.configured")
+
+# Load tool-specific config that would do the real work.
+lit_config.load_config(config, "@GWP_ASAN_LIT_SOURCE_DIR@/lit.cfg")
Added: compiler-rt/trunk/test/gwp_asan/unit/lit.site.cfg.in
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/gwp_asan/unit/lit.site.cfg.in?rev=362138&view=auto
==============================================================================
--- compiler-rt/trunk/test/gwp_asan/unit/lit.site.cfg.in (added)
+++ compiler-rt/trunk/test/gwp_asan/unit/lit.site.cfg.in Thu May 30 12:45:32 2019
@@ -0,0 +1,9 @@
+ at LIT_SITE_CFG_IN_HEADER@
+
+config.name = "GwpAsan-Unittest"
+# Load common config for all compiler-rt unit tests.
+lit_config.load_config(config, "@COMPILER_RT_BINARY_DIR@/unittests/lit.common.unit.configured")
+
+config.test_exec_root = os.path.join("@COMPILER_RT_BINARY_DIR@",
+ "lib", "gwp_asan", "tests")
+config.test_source_root = config.test_exec_root
More information about the llvm-commits
mailing list