1603c4be006d8c53905d736bf1f19a49f5ce98276Alexey Samsonov//===-- tsan_mutex_test.cc ------------------------------------------------===// 2da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany// 3da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany// The LLVM Compiler Infrastructure 4da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany// 5da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany// This file is distributed under the University of Illinois Open Source 6da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany// License. See LICENSE.TXT for details. 7da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany// 8da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany//===----------------------------------------------------------------------===// 9da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany// 10da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany// This file is a part of ThreadSanitizer (TSan), a race detector. 11da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany// 12da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany//===----------------------------------------------------------------------===// 132ea978704a794e536d2801affcc7f301092d75daAlexey Samsonov#include "sanitizer_common/sanitizer_internal_defs.h" 14fce5bd4cc29fddb5e8f0cb9c12df7c10187a991dDmitry Vyukov#include "sanitizer_common/sanitizer_atomic.h" 15fce5bd4cc29fddb5e8f0cb9c12df7c10187a991dDmitry Vyukov#include "sanitizer_common/sanitizer_common.h" 16a3eca8192505f4796194dd24eb051019f402de99Dmitry Vyukov#include "sanitizer_common/sanitizer_mutex.h" 17da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany#include "tsan_mutex.h" 18da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany#include "gtest/gtest.h" 19da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany 20da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryanynamespace __tsan { 21da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany 22a3eca8192505f4796194dd24eb051019f402de99Dmitry Vyukovtemplate<typename MutexType> 23da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryanyclass TestData { 24da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany public: 25b6eb56f5a03b4dba8de79465274a73d1ecbca7f2Dmitry Vyukov explicit TestData(MutexType *mtx) 26a3eca8192505f4796194dd24eb051019f402de99Dmitry Vyukov : mtx_(mtx) { 27da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany for (int i = 0; i < kSize; i++) 28da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany data_[i] = 0; 29da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany } 30da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany 31da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany void Write() { 32a3eca8192505f4796194dd24eb051019f402de99Dmitry Vyukov Lock l(mtx_); 33da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany T v0 = data_[0]; 34da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany for (int i = 0; i < kSize; i++) { 35da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany CHECK_EQ(data_[i], v0); 36da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany data_[i]++; 37da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany } 38da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany } 39da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany 40da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany void Read() { 41a3eca8192505f4796194dd24eb051019f402de99Dmitry Vyukov ReadLock l(mtx_); 42da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany T v0 = data_[0]; 43da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany for (int i = 0; i < kSize; i++) { 44da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany CHECK_EQ(data_[i], v0); 45da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany } 46da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany } 47da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany 48a3eca8192505f4796194dd24eb051019f402de99Dmitry Vyukov void Backoff() { 49a3eca8192505f4796194dd24eb051019f402de99Dmitry Vyukov volatile T data[kSize] = {}; 50a3eca8192505f4796194dd24eb051019f402de99Dmitry Vyukov for (int i = 0; i < kSize; i++) { 51a3eca8192505f4796194dd24eb051019f402de99Dmitry Vyukov data[i]++; 52a3eca8192505f4796194dd24eb051019f402de99Dmitry Vyukov CHECK_EQ(data[i], 1); 53a3eca8192505f4796194dd24eb051019f402de99Dmitry Vyukov } 54a3eca8192505f4796194dd24eb051019f402de99Dmitry Vyukov } 55a3eca8192505f4796194dd24eb051019f402de99Dmitry Vyukov 56da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany private: 57a3eca8192505f4796194dd24eb051019f402de99Dmitry Vyukov typedef GenericScopedLock<MutexType> Lock; 58da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany static const int kSize = 64; 59da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany typedef u64 T; 60a3eca8192505f4796194dd24eb051019f402de99Dmitry Vyukov MutexType *mtx_; 61502d3831379094368e099ec70b1916d0ceda1bfeAlexey Samsonov char pad_[kCacheLineSize]; 62da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany T data_[kSize]; 63da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany}; 64da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany 65da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryanyconst int kThreads = 8; 66da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryanyconst int kWriteRate = 1024; 6786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#if SANITIZER_DEBUG 68da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryanyconst int kIters = 16*1024; 69da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany#else 70da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryanyconst int kIters = 64*1024; 71da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany#endif 72da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany 73a3eca8192505f4796194dd24eb051019f402de99Dmitry Vyukovtemplate<typename MutexType> 74da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryanystatic void *write_mutex_thread(void *param) { 75a3eca8192505f4796194dd24eb051019f402de99Dmitry Vyukov TestData<MutexType> *data = (TestData<MutexType>*)param; 76da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany for (int i = 0; i < kIters; i++) { 77da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany data->Write(); 78a3eca8192505f4796194dd24eb051019f402de99Dmitry Vyukov data->Backoff(); 79da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany } 80da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany return 0; 81da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany} 82da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany 83a3eca8192505f4796194dd24eb051019f402de99Dmitry Vyukovtemplate<typename MutexType> 84da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryanystatic void *read_mutex_thread(void *param) { 85a3eca8192505f4796194dd24eb051019f402de99Dmitry Vyukov TestData<MutexType> *data = (TestData<MutexType>*)param; 86da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany for (int i = 0; i < kIters; i++) { 87da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany if ((i % kWriteRate) == 0) 88da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany data->Write(); 89da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany else 90da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany data->Read(); 91a3eca8192505f4796194dd24eb051019f402de99Dmitry Vyukov data->Backoff(); 92da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany } 93da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany return 0; 94da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany} 95da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany 96da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya SerebryanyTEST(Mutex, Write) { 97a3eca8192505f4796194dd24eb051019f402de99Dmitry Vyukov Mutex mtx(MutexTypeAnnotations, StatMtxAnnotations); 98a3eca8192505f4796194dd24eb051019f402de99Dmitry Vyukov TestData<Mutex> data(&mtx); 99da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany pthread_t threads[kThreads]; 100da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany for (int i = 0; i < kThreads; i++) 101a3eca8192505f4796194dd24eb051019f402de99Dmitry Vyukov pthread_create(&threads[i], 0, write_mutex_thread<Mutex>, &data); 102da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany for (int i = 0; i < kThreads; i++) 103da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany pthread_join(threads[i], 0); 104da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany} 105da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany 106da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya SerebryanyTEST(Mutex, ReadWrite) { 107a3eca8192505f4796194dd24eb051019f402de99Dmitry Vyukov Mutex mtx(MutexTypeAnnotations, StatMtxAnnotations); 108a3eca8192505f4796194dd24eb051019f402de99Dmitry Vyukov TestData<Mutex> data(&mtx); 109a3eca8192505f4796194dd24eb051019f402de99Dmitry Vyukov pthread_t threads[kThreads]; 110a3eca8192505f4796194dd24eb051019f402de99Dmitry Vyukov for (int i = 0; i < kThreads; i++) 111a3eca8192505f4796194dd24eb051019f402de99Dmitry Vyukov pthread_create(&threads[i], 0, read_mutex_thread<Mutex>, &data); 112a3eca8192505f4796194dd24eb051019f402de99Dmitry Vyukov for (int i = 0; i < kThreads; i++) 113a3eca8192505f4796194dd24eb051019f402de99Dmitry Vyukov pthread_join(threads[i], 0); 114a3eca8192505f4796194dd24eb051019f402de99Dmitry Vyukov} 115a3eca8192505f4796194dd24eb051019f402de99Dmitry Vyukov 116a3eca8192505f4796194dd24eb051019f402de99Dmitry VyukovTEST(Mutex, SpinWrite) { 117a3eca8192505f4796194dd24eb051019f402de99Dmitry Vyukov SpinMutex mtx; 118a3eca8192505f4796194dd24eb051019f402de99Dmitry Vyukov TestData<SpinMutex> data(&mtx); 119da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany pthread_t threads[kThreads]; 120da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany for (int i = 0; i < kThreads; i++) 121a3eca8192505f4796194dd24eb051019f402de99Dmitry Vyukov pthread_create(&threads[i], 0, write_mutex_thread<SpinMutex>, &data); 122da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany for (int i = 0; i < kThreads; i++) 123da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany pthread_join(threads[i], 0); 124da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany} 125da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany 126da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany} // namespace __tsan 127