]> git.proxmox.com Git - rustc.git/blame - src/compiler-rt/lib/tsan/tests/unit/tsan_mutex_test.cc
Imported Upstream version 1.6.0+dfsg1
[rustc.git] / src / compiler-rt / lib / tsan / tests / unit / tsan_mutex_test.cc
CommitLineData
1a4d82fc
JJ
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;
92a42be0 67#if SANITIZER_DEBUG
1a4d82fc
JJ
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