sanitizer_mutex_test.cc revision ce700979f644c790c2d9d80f5cc2a1ada0380284
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; 68const int kWriteRate = 1024; 69#if SANITIZER_DEBUG 70const int kIters = 16*1024; 71#else 72const int kIters = 64*1024; 73#endif 74 75template<typename MutexType> 76static 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 85template<typename MutexType> 86static 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 95template<typename MutexType> 96static void check_locked(MutexType *mtx) { 97 GenericScopedLock<MutexType> l(mtx); 98 mtx->CheckLocked(); 99} 100 101TEST(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 112TEST(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 123TEST(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