diff options
Diffstat (limited to 'lib/sanitizer_common/tests/sanitizer_mutex_test.cc')
-rw-r--r-- | lib/sanitizer_common/tests/sanitizer_mutex_test.cc | 128 |
1 files changed, 128 insertions, 0 deletions
diff --git a/lib/sanitizer_common/tests/sanitizer_mutex_test.cc b/lib/sanitizer_common/tests/sanitizer_mutex_test.cc new file mode 100644 index 000000000000..6bb2ae29a188 --- /dev/null +++ b/lib/sanitizer_common/tests/sanitizer_mutex_test.cc @@ -0,0 +1,128 @@ +//===-- sanitizer_mutex_test.cc -------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file is a part of ThreadSanitizer/AddressSanitizer runtime. +// +//===----------------------------------------------------------------------===// +#include "sanitizer_common/sanitizer_mutex.h" +#include "sanitizer_common/sanitizer_common.h" +#include "gtest/gtest.h" + +#include <string.h> + +namespace __sanitizer { + +template<typename MutexType> +class TestData { + public: + explicit TestData(MutexType *mtx) + : mtx_(mtx) { + for (int i = 0; i < kSize; i++) + data_[i] = 0; + } + + void Write() { + Lock l(mtx_); + T v0 = data_[0]; + for (int i = 0; i < kSize; i++) { + CHECK_EQ(data_[i], v0); + data_[i]++; + } + } + + void TryWrite() { + if (!mtx_->TryLock()) + return; + T v0 = data_[0]; + for (int i = 0; i < kSize; i++) { + CHECK_EQ(data_[i], v0); + data_[i]++; + } + mtx_->Unlock(); + } + + 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; + MutexType *mtx_; + char pad_[kCacheLineSize]; + T data_[kSize]; +}; + +const int kThreads = 8; +const int kWriteRate = 1024; +#if SANITIZER_DEBUG +const int kIters = 16*1024; +#else +const int kIters = 64*1024; +#endif + +template<typename MutexType> +static void *lock_thread(void *param) { + TestData<MutexType> *data = (TestData<MutexType>*)param; + for (int i = 0; i < kIters; i++) { + data->Write(); + data->Backoff(); + } + return 0; +} + +template<typename MutexType> +static void *try_thread(void *param) { + TestData<MutexType> *data = (TestData<MutexType>*)param; + for (int i = 0; i < kIters; i++) { + data->TryWrite(); + data->Backoff(); + } + return 0; +} + +TEST(SanitizerCommon, SpinMutex) { + SpinMutex mtx; + mtx.Init(); + TestData<SpinMutex> data(&mtx); + pthread_t threads[kThreads]; + for (int i = 0; i < kThreads; i++) + pthread_create(&threads[i], 0, lock_thread<SpinMutex>, &data); + for (int i = 0; i < kThreads; i++) + pthread_join(threads[i], 0); +} + +TEST(SanitizerCommon, SpinMutexTry) { + SpinMutex mtx; + mtx.Init(); + TestData<SpinMutex> data(&mtx); + pthread_t threads[kThreads]; + for (int i = 0; i < kThreads; i++) + pthread_create(&threads[i], 0, try_thread<SpinMutex>, &data); + for (int i = 0; i < kThreads; i++) + pthread_join(threads[i], 0); +} + +TEST(SanitizerCommon, BlockingMutex) { + u64 mtxmem[1024] = {}; + BlockingMutex *mtx = new(mtxmem) BlockingMutex(LINKER_INITIALIZED); + TestData<BlockingMutex> data(mtx); + pthread_t threads[kThreads]; + for (int i = 0; i < kThreads; i++) + pthread_create(&threads[i], 0, lock_thread<BlockingMutex>, &data); + for (int i = 0; i < kThreads; i++) + pthread_join(threads[i], 0); +} + +} // namespace __sanitizer |