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 19 namespace __sanitizer { 20 21 template<typename MutexType> 22 class 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 67 const int kThreads = 8; 68 const int kWriteRate = 1024; 69 #if SANITIZER_DEBUG 70 const int kIters = 16*1024; 71 #else 72 const int kIters = 64*1024; 73 #endif 74 75 template<typename MutexType> 76 static void *lock_thread(void *param) { 77 TestData<MutexType> *data = (TestData<MutexType>*)param; 78 for (int i = 0; i < kIters; i++) { 79 data->Write(); 80 data->Backoff(); 81 } 82 return 0; 83 } 84 85 template<typename MutexType> 86 static void *try_thread(void *param) { 87 TestData<MutexType> *data = (TestData<MutexType>*)param; 88 for (int i = 0; i < kIters; i++) { 89 data->TryWrite(); 90 data->Backoff(); 91 } 92 return 0; 93 } 94 95 template<typename MutexType> 96 static void check_locked(MutexType *mtx) { 97 GenericScopedLock<MutexType> l(mtx); 98 mtx->CheckLocked(); 99 } 100 101 TEST(SanitizerCommon, SpinMutex) { 102 SpinMutex mtx; 103 mtx.Init(); 104 TestData<SpinMutex> data(&mtx); 105 pthread_t threads[kThreads]; 106 for (int i = 0; i < kThreads; i++) 107 pthread_create(&threads[i], 0, lock_thread<SpinMutex>, &data); 108 for (int i = 0; i < kThreads; i++) 109 pthread_join(threads[i], 0); 110 } 111 112 TEST(SanitizerCommon, SpinMutexTry) { 113 SpinMutex mtx; 114 mtx.Init(); 115 TestData<SpinMutex> data(&mtx); 116 pthread_t threads[kThreads]; 117 for (int i = 0; i < kThreads; i++) 118 pthread_create(&threads[i], 0, try_thread<SpinMutex>, &data); 119 for (int i = 0; i < kThreads; i++) 120 pthread_join(threads[i], 0); 121 } 122 123 TEST(SanitizerCommon, BlockingMutex) { 124 u64 mtxmem[1024] = {}; 125 BlockingMutex *mtx = new(mtxmem) BlockingMutex(LINKER_INITIALIZED); 126 TestData<BlockingMutex> data(mtx); 127 pthread_t threads[kThreads]; 128 for (int i = 0; i < kThreads; i++) 129 pthread_create(&threads[i], 0, lock_thread<BlockingMutex>, &data); 130 for (int i = 0; i < kThreads; i++) 131 pthread_join(threads[i], 0); 132 check_locked(mtx); 133 } 134 135 } // namespace __sanitizer 136