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