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;
67da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany#if TSAN_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