diff options
author | Dmitry Vyukov <dvyukov@google.com> | 2012-06-29 17:32:18 +0000 |
---|---|---|
committer | Dmitry Vyukov <dvyukov@google.com> | 2012-06-29 17:32:18 +0000 |
commit | a3eca8192505f4796194dd24eb051019f402de99 (patch) | |
tree | 9d4fa9ef6ec6981cee878572d5a80c1040252aa0 | |
parent | c04d8b39795b8faab2c172da59462f4e54823533 (diff) |
tsan/asan: add SpinMutex to sanitizer_common
git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@159439 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | lib/sanitizer_common/sanitizer_atomic.h | 4 | ||||
-rw-r--r-- | lib/sanitizer_common/sanitizer_mutex.h | 26 | ||||
-rw-r--r-- | lib/sanitizer_common/tests/sanitizer_allocator64_test.cc | 1 | ||||
-rw-r--r-- | lib/sanitizer_common/tests/sanitizer_allocator_test.cc | 6 | ||||
-rw-r--r-- | lib/tsan/Makefile.old | 4 | ||||
-rw-r--r-- | lib/tsan/unit_tests/tsan_mutex_test.cc | 53 |
6 files changed, 74 insertions, 20 deletions
diff --git a/lib/sanitizer_common/sanitizer_atomic.h b/lib/sanitizer_common/sanitizer_atomic.h index df3344ec8..135be1822 100644 --- a/lib/sanitizer_common/sanitizer_atomic.h +++ b/lib/sanitizer_common/sanitizer_atomic.h @@ -6,6 +6,10 @@ // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// +// +// This file is a part of ThreadSanitizer/AddressSanitizer runtime. +// +//===----------------------------------------------------------------------===// #ifndef SANITIZER_ATOMIC_H #define SANITIZER_ATOMIC_H diff --git a/lib/sanitizer_common/sanitizer_mutex.h b/lib/sanitizer_common/sanitizer_mutex.h index c4e4f7f71..8bb9d3648 100644 --- a/lib/sanitizer_common/sanitizer_mutex.h +++ b/lib/sanitizer_common/sanitizer_mutex.h @@ -6,6 +6,10 @@ // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// +// +// This file is a part of ThreadSanitizer/AddressSanitizer runtime. +// +//===----------------------------------------------------------------------===// #ifndef SANITIZER_MUTEX_H #define SANITIZER_MUTEX_H @@ -15,6 +19,28 @@ namespace __sanitizer { +class SpinMutex { + public: + SpinMutex() { + atomic_store(&state_, 0, memory_order_relaxed); + } + + void Lock() { + while (atomic_exchange(&state_, 1, memory_order_acquire)) + proc_yield(10); + } + + void Unlock() { + atomic_store(&state_, 0, memory_order_release); + } + + private: + atomic_uint8_t state_; + + SpinMutex(const SpinMutex&); + void operator=(const SpinMutex&); +}; + template<typename MutexType> class GenericScopedLock { public: diff --git a/lib/sanitizer_common/tests/sanitizer_allocator64_test.cc b/lib/sanitizer_common/tests/sanitizer_allocator64_test.cc index ba636439f..e8da03eb9 100644 --- a/lib/sanitizer_common/tests/sanitizer_allocator64_test.cc +++ b/lib/sanitizer_common/tests/sanitizer_allocator64_test.cc @@ -124,6 +124,7 @@ TEST(SanitizerCommon, SizeClassAllocator64MetadataStress) { } a.TestOnlyUnmap(); + (void)sink; } void FailInAssertionOnOOM() { diff --git a/lib/sanitizer_common/tests/sanitizer_allocator_test.cc b/lib/sanitizer_common/tests/sanitizer_allocator_test.cc index 2a739471f..d6c7f56dc 100644 --- a/lib/sanitizer_common/tests/sanitizer_allocator_test.cc +++ b/lib/sanitizer_common/tests/sanitizer_allocator_test.cc @@ -7,14 +7,14 @@ // //===----------------------------------------------------------------------===// // -// This file is a part of ThreadSanitizer (TSan), a race detector. +// This file is a part of ThreadSanitizer/AddressSanitizer runtime. // //===----------------------------------------------------------------------===// #include "sanitizer_common/sanitizer_common.h" #include "gtest/gtest.h" #include <stdlib.h> -namespace __tsan { +namespace __sanitizer { TEST(Allocator, Basic) { char *p = (char*)InternalAlloc(10); @@ -53,4 +53,4 @@ TEST(Allocator, Stress) { } } -} // namespace __tsan +} // namespace __sanitizer diff --git a/lib/tsan/Makefile.old b/lib/tsan/Makefile.old index 1db2efc96..a0e83b6f2 100644 --- a/lib/tsan/Makefile.old +++ b/lib/tsan/Makefile.old @@ -3,12 +3,12 @@ LDFLAGS=-ldl -lpthread -pie CXXFLAGS = -fPIE -g -Wall -Werror -DTSAN_DEBUG=$(DEBUG) # Silence warnings that Clang produces for gtest code. # Use -Wno-attributes so that gcc doesn't complain about unknown warning types. -CXXFLAGS += -Wno-static-in-inline -Wno-attributes +CXXFLAGS += -Wno-attributes ifeq ($(DEBUG), 0) CXXFLAGS += -O3 endif ifeq ($(CXX), clang++) - CXXFLAGS+= -Wno-unused-private-field + CXXFLAGS+= -Wno-unused-private-field -Wno-static-in-inline endif LIBTSAN=rtl/libtsan.a diff --git a/lib/tsan/unit_tests/tsan_mutex_test.cc b/lib/tsan/unit_tests/tsan_mutex_test.cc index e26dd486f..9af3d8d3a 100644 --- a/lib/tsan/unit_tests/tsan_mutex_test.cc +++ b/lib/tsan/unit_tests/tsan_mutex_test.cc @@ -13,21 +13,23 @@ #include "sanitizer_common/sanitizer_internal_defs.h" #include "sanitizer_common/sanitizer_atomic.h" #include "sanitizer_common/sanitizer_common.h" +#include "sanitizer_common/sanitizer_mutex.h" #include "tsan_mutex.h" #include "gtest/gtest.h" namespace __tsan { +template<typename MutexType> class TestData { public: - TestData() - : mtx_(MutexTypeAnnotations, StatMtxAnnotations) { + TestData(MutexType *mtx) + : mtx_(mtx) { for (int i = 0; i < kSize; i++) data_[i] = 0; } void Write() { - Lock l(&mtx_); + Lock l(mtx_); T v0 = data_[0]; for (int i = 0; i < kSize; i++) { CHECK_EQ(data_[i], v0); @@ -36,17 +38,26 @@ class TestData { } void Read() { - ReadLock l(&mtx_); + ReadLock l(mtx_); T v0 = data_[0]; for (int i = 0; i < kSize; i++) { CHECK_EQ(data_[i], v0); } } + void Backoff() { + volatile T data[kSize] = {}; + for (int i = 0; i < kSize; i++) { + data[i]++; + CHECK_EQ(data[i], 1); + } + } + private: + typedef GenericScopedLock<MutexType> Lock; static const int kSize = 64; typedef u64 T; - Mutex mtx_; + MutexType *mtx_; char pad_[kCacheLineSize]; T data_[kSize]; }; @@ -59,43 +70,55 @@ const int kIters = 16*1024; const int kIters = 64*1024; #endif +template<typename MutexType> static void *write_mutex_thread(void *param) { - TestData *data = (TestData *)param; - TestData local; + TestData<MutexType> *data = (TestData<MutexType>*)param; for (int i = 0; i < kIters; i++) { data->Write(); - local.Write(); + data->Backoff(); } return 0; } +template<typename MutexType> static void *read_mutex_thread(void *param) { - TestData *data = (TestData *)param; - TestData local; + TestData<MutexType> *data = (TestData<MutexType>*)param; for (int i = 0; i < kIters; i++) { if ((i % kWriteRate) == 0) data->Write(); else data->Read(); - local.Write(); + data->Backoff(); } return 0; } TEST(Mutex, Write) { - TestData data; + Mutex mtx(MutexTypeAnnotations, StatMtxAnnotations); + TestData<Mutex> data(&mtx); pthread_t threads[kThreads]; for (int i = 0; i < kThreads; i++) - pthread_create(&threads[i], 0, write_mutex_thread, &data); + pthread_create(&threads[i], 0, write_mutex_thread<Mutex>, &data); for (int i = 0; i < kThreads; i++) pthread_join(threads[i], 0); } TEST(Mutex, ReadWrite) { - TestData data; + Mutex mtx(MutexTypeAnnotations, StatMtxAnnotations); + TestData<Mutex> data(&mtx); + pthread_t threads[kThreads]; + for (int i = 0; i < kThreads; i++) + pthread_create(&threads[i], 0, read_mutex_thread<Mutex>, &data); + for (int i = 0; i < kThreads; i++) + pthread_join(threads[i], 0); +} + +TEST(Mutex, SpinWrite) { + SpinMutex mtx; + TestData<SpinMutex> data(&mtx); pthread_t threads[kThreads]; for (int i = 0; i < kThreads; i++) - pthread_create(&threads[i], 0, read_mutex_thread, &data); + pthread_create(&threads[i], 0, write_mutex_thread<SpinMutex>, &data); for (int i = 0; i < kThreads; i++) pthread_join(threads[i], 0); } |