sanitizer_mutex_test.cc revision a09507c38cf9dd9119e5aa9bd6d91383514f857b
1//===-- sanitizer_mutex_test.cc -------------------------------------------===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9// 10// This file is a part of ThreadSanitizer/AddressSanitizer runtime. 11// 12//===----------------------------------------------------------------------===// 13#include "sanitizer_common/sanitizer_mutex.h" 14#include "sanitizer_common/sanitizer_common.h" 15#include "gtest/gtest.h" 16 17#include <string.h> 18 19namespace __sanitizer { 20 21template<typename MutexType> 22class TestData { 23 public: 24 explicit TestData(MutexType *mtx) 25 : mtx_(mtx) { 26 for (int i = 0; i < kSize; i++) 27 data_[i] = 0; 28 } 29 30 void Write() { 31 Lock l(mtx_); 32 T v0 = data_[0]; 33 for (int i = 0; i < kSize; i++) { 34 CHECK_EQ(data_[i], v0); 35 data_[i]++; 36 } 37 } 38 39 void TryWrite() { 40 if (!mtx_->TryLock()) 41 return; 42 T v0 = data_[0]; 43 for (int i = 0; i < kSize; i++) { 44 CHECK_EQ(data_[i], v0); 45 data_[i]++; 46 } 47 mtx_->Unlock(); 48 } 49 50 void Backoff() { 51 volatile T data[kSize] = {}; 52 for (int i = 0; i < kSize; i++) { 53 data[i]++; 54 CHECK_EQ(data[i], 1); 55 } 56 } 57 58 private: 59 typedef GenericScopedLock<MutexType> Lock; 60 static const int kSize = 64; 61 typedef u64 T; 62 MutexType *mtx_; 63 char pad_[kCacheLineSize]; 64 T data_[kSize]; 65}; 66 67const int kThreads = 8; 68#if SANITIZER_DEBUG 69const int kIters = 16*1024; 70#else 71const int kIters = 64*1024; 72#endif 73 74template<typename MutexType> 75static void *lock_thread(void *param) { 76 TestData<MutexType> *data = (TestData<MutexType>*)param; 77 for (int i = 0; i < kIters; i++) { 78 data->Write(); 79 data->Backoff(); 80 } 81 return 0; 82} 83 84template<typename MutexType> 85static void *try_thread(void *param) { 86 TestData<MutexType> *data = (TestData<MutexType>*)param; 87 for (int i = 0; i < kIters; i++) { 88 data->TryWrite(); 89 data->Backoff(); 90 } 91 return 0; 92} 93 94template<typename MutexType> 95static void check_locked(MutexType *mtx) { 96 GenericScopedLock<MutexType> l(mtx); 97 mtx->CheckLocked(); 98} 99 100TEST(SanitizerCommon, SpinMutex) { 101 SpinMutex mtx; 102 mtx.Init(); 103 TestData<SpinMutex> data(&mtx); 104 pthread_t threads[kThreads]; 105 for (int i = 0; i < kThreads; i++) 106 pthread_create(&threads[i], 0, lock_thread<SpinMutex>, &data); 107 for (int i = 0; i < kThreads; i++) 108 pthread_join(threads[i], 0); 109} 110 111TEST(SanitizerCommon, SpinMutexTry) { 112 SpinMutex mtx; 113 mtx.Init(); 114 TestData<SpinMutex> data(&mtx); 115 pthread_t threads[kThreads]; 116 for (int i = 0; i < kThreads; i++) 117 pthread_create(&threads[i], 0, try_thread<SpinMutex>, &data); 118 for (int i = 0; i < kThreads; i++) 119 pthread_join(threads[i], 0); 120} 121 122TEST(SanitizerCommon, BlockingMutex) { 123 u64 mtxmem[1024] = {}; 124 BlockingMutex *mtx = new(mtxmem) BlockingMutex(LINKER_INITIALIZED); 125 TestData<BlockingMutex> data(mtx); 126 pthread_t threads[kThreads]; 127 for (int i = 0; i < kThreads; i++) 128 pthread_create(&threads[i], 0, lock_thread<BlockingMutex>, &data); 129 for (int i = 0; i < kThreads; i++) 130 pthread_join(threads[i], 0); 131 check_locked(mtx); 132} 133 134} // namespace __sanitizer 135