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 20namespace __tsan { 21 22template<typename MutexType> 23class 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 65const int kThreads = 8; 66const int kWriteRate = 1024; 67#if SANITIZER_DEBUG 68const int kIters = 16*1024; 69#else 70const int kIters = 64*1024; 71#endif 72 73template<typename MutexType> 74static 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 83template<typename MutexType> 84static 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 96TEST(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 106TEST(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 116TEST(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