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 16 #include "sanitizer_pthread_wrappers.h" 17 18 #include "gtest/gtest.h" 19 20 #include <string.h> 21 22 namespace __sanitizer { 23 24 template<typename MutexType> 25 class TestData { 26 public: 27 explicit TestData(MutexType *mtx) 28 : mtx_(mtx) { 29 for (int i = 0; i < kSize; i++) 30 data_[i] = 0; 31 } 32 33 void Write() { 34 Lock l(mtx_); 35 T v0 = data_[0]; 36 for (int i = 0; i < kSize; i++) { 37 CHECK_EQ(data_[i], v0); 38 data_[i]++; 39 } 40 } 41 42 void TryWrite() { 43 if (!mtx_->TryLock()) 44 return; 45 T v0 = data_[0]; 46 for (int i = 0; i < kSize; i++) { 47 CHECK_EQ(data_[i], v0); 48 data_[i]++; 49 } 50 mtx_->Unlock(); 51 } 52 53 void Backoff() { 54 volatile T data[kSize] = {}; 55 for (int i = 0; i < kSize; i++) { 56 data[i]++; 57 CHECK_EQ(data[i], 1); 58 } 59 } 60 61 private: 62 typedef GenericScopedLock<MutexType> Lock; 63 static const int kSize = 64; 64 typedef u64 T; 65 MutexType *mtx_; 66 char pad_[kCacheLineSize]; 67 T data_[kSize]; 68 }; 69 70 const int kThreads = 8; 71 #if SANITIZER_DEBUG 72 const int kIters = 16*1024; 73 #else 74 const int kIters = 64*1024; 75 #endif 76 77 template<typename MutexType> 78 static void *lock_thread(void *param) { 79 TestData<MutexType> *data = (TestData<MutexType>*)param; 80 for (int i = 0; i < kIters; i++) { 81 data->Write(); 82 data->Backoff(); 83 } 84 return 0; 85 } 86 87 template<typename MutexType> 88 static void *try_thread(void *param) { 89 TestData<MutexType> *data = (TestData<MutexType>*)param; 90 for (int i = 0; i < kIters; i++) { 91 data->TryWrite(); 92 data->Backoff(); 93 } 94 return 0; 95 } 96 97 template<typename MutexType> 98 static void check_locked(MutexType *mtx) { 99 GenericScopedLock<MutexType> l(mtx); 100 mtx->CheckLocked(); 101 } 102 103 TEST(SanitizerCommon, SpinMutex) { 104 SpinMutex mtx; 105 mtx.Init(); 106 TestData<SpinMutex> data(&mtx); 107 pthread_t threads[kThreads]; 108 for (int i = 0; i < kThreads; i++) 109 PTHREAD_CREATE(&threads[i], 0, lock_thread<SpinMutex>, &data); 110 for (int i = 0; i < kThreads; i++) 111 PTHREAD_JOIN(threads[i], 0); 112 } 113 114 TEST(SanitizerCommon, SpinMutexTry) { 115 SpinMutex mtx; 116 mtx.Init(); 117 TestData<SpinMutex> data(&mtx); 118 pthread_t threads[kThreads]; 119 for (int i = 0; i < kThreads; i++) 120 PTHREAD_CREATE(&threads[i], 0, try_thread<SpinMutex>, &data); 121 for (int i = 0; i < kThreads; i++) 122 PTHREAD_JOIN(threads[i], 0); 123 } 124 125 TEST(SanitizerCommon, BlockingMutex) { 126 u64 mtxmem[1024] = {}; 127 BlockingMutex *mtx = new(mtxmem) BlockingMutex(LINKER_INITIALIZED); 128 TestData<BlockingMutex> data(mtx); 129 pthread_t threads[kThreads]; 130 for (int i = 0; i < kThreads; i++) 131 PTHREAD_CREATE(&threads[i], 0, lock_thread<BlockingMutex>, &data); 132 for (int i = 0; i < kThreads; i++) 133 PTHREAD_JOIN(threads[i], 0); 134 check_locked(mtx); 135 } 136 137 } // namespace __sanitizer 138