1 //===-- tsan_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 (TSan), a race detector. 11 // 12 //===----------------------------------------------------------------------===// 13 #include "sanitizer_common/sanitizer_internal_defs.h" 14 #include "sanitizer_common/sanitizer_atomic.h" 15 #include "sanitizer_common/sanitizer_common.h" 16 #include "sanitizer_common/sanitizer_mutex.h" 17 #include "tsan_mutex.h" 18 #include "gtest/gtest.h" 19 20 namespace __tsan { 21 22 template<typename MutexType> 23 class TestData { 24 public: 25 explicit TestData(MutexType *mtx) 26 : mtx_(mtx) { 27 for (int i = 0; i < kSize; i++) 28 data_[i] = 0; 29 } 30 31 void Write() { 32 Lock l(mtx_); 33 T v0 = data_[0]; 34 for (int i = 0; i < kSize; i++) { 35 CHECK_EQ(data_[i], v0); 36 data_[i]++; 37 } 38 } 39 40 void Read() { 41 ReadLock l(mtx_); 42 T v0 = data_[0]; 43 for (int i = 0; i < kSize; i++) { 44 CHECK_EQ(data_[i], v0); 45 } 46 } 47 48 void Backoff() { 49 volatile T data[kSize] = {}; 50 for (int i = 0; i < kSize; i++) { 51 data[i]++; 52 CHECK_EQ(data[i], 1); 53 } 54 } 55 56 private: 57 typedef GenericScopedLock<MutexType> Lock; 58 static const int kSize = 64; 59 typedef u64 T; 60 MutexType *mtx_; 61 char pad_[kCacheLineSize]; 62 T data_[kSize]; 63 }; 64 65 const int kThreads = 8; 66 const int kWriteRate = 1024; 67 #if TSAN_DEBUG 68 const int kIters = 16*1024; 69 #else 70 const int kIters = 64*1024; 71 #endif 72 73 template<typename MutexType> 74 static void *write_mutex_thread(void *param) { 75 TestData<MutexType> *data = (TestData<MutexType>*)param; 76 for (int i = 0; i < kIters; i++) { 77 data->Write(); 78 data->Backoff(); 79 } 80 return 0; 81 } 82 83 template<typename MutexType> 84 static void *read_mutex_thread(void *param) { 85 TestData<MutexType> *data = (TestData<MutexType>*)param; 86 for (int i = 0; i < kIters; i++) { 87 if ((i % kWriteRate) == 0) 88 data->Write(); 89 else 90 data->Read(); 91 data->Backoff(); 92 } 93 return 0; 94 } 95 96 TEST(Mutex, Write) { 97 Mutex mtx(MutexTypeAnnotations, StatMtxAnnotations); 98 TestData<Mutex> data(&mtx); 99 pthread_t threads[kThreads]; 100 for (int i = 0; i < kThreads; i++) 101 pthread_create(&threads[i], 0, write_mutex_thread<Mutex>, &data); 102 for (int i = 0; i < kThreads; i++) 103 pthread_join(threads[i], 0); 104 } 105 106 TEST(Mutex, ReadWrite) { 107 Mutex mtx(MutexTypeAnnotations, StatMtxAnnotations); 108 TestData<Mutex> data(&mtx); 109 pthread_t threads[kThreads]; 110 for (int i = 0; i < kThreads; i++) 111 pthread_create(&threads[i], 0, read_mutex_thread<Mutex>, &data); 112 for (int i = 0; i < kThreads; i++) 113 pthread_join(threads[i], 0); 114 } 115 116 TEST(Mutex, SpinWrite) { 117 SpinMutex mtx; 118 TestData<SpinMutex> data(&mtx); 119 pthread_t threads[kThreads]; 120 for (int i = 0; i < kThreads; i++) 121 pthread_create(&threads[i], 0, write_mutex_thread<SpinMutex>, &data); 122 for (int i = 0; i < kThreads; i++) 123 pthread_join(threads[i], 0); 124 } 125 126 } // namespace __tsan 127