1 //===-- sanitizer_mutex_test.cpp ------------------------------------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 // This file is a part of ThreadSanitizer/AddressSanitizer runtime.
11 //===----------------------------------------------------------------------===//
12 #include "sanitizer_common/sanitizer_mutex.h"
13 #include "sanitizer_common/sanitizer_common.h"
15 #include "sanitizer_pthread_wrappers.h"
17 #include "gtest/gtest.h"
21 namespace __sanitizer
{
23 template<typename MutexType
>
26 explicit TestData(MutexType
*mtx
)
28 for (int i
= 0; i
< kSize
; i
++)
35 for (int i
= 0; i
< kSize
; i
++) {
37 CHECK_EQ(data_
[i
], v0
);
46 for (int i
= 0; i
< kSize
; i
++) {
48 CHECK_EQ(data_
[i
], v0
);
57 for (int i
= 0; i
< kSize
; i
++) {
58 mtx_
->CheckReadLocked();
59 CHECK_EQ(data_
[i
], v0
);
64 volatile T data
[kSize
] = {};
65 for (int i
= 0; i
< kSize
; i
++) {
72 typedef GenericScopedLock
<MutexType
> Lock
;
73 typedef GenericScopedReadLock
<MutexType
> ReadLock
;
74 static const int kSize
= 64;
77 char pad_
[kCacheLineSize
];
81 const int kThreads
= 8;
83 const int kIters
= 16*1024;
85 const int kIters
= 64*1024;
88 template<typename MutexType
>
89 static void *lock_thread(void *param
) {
90 TestData
<MutexType
> *data
= (TestData
<MutexType
>*)param
;
91 for (int i
= 0; i
< kIters
; i
++) {
98 template<typename MutexType
>
99 static void *try_thread(void *param
) {
100 TestData
<MutexType
> *data
= (TestData
<MutexType
>*)param
;
101 for (int i
= 0; i
< kIters
; i
++) {
108 template <typename MutexType
>
109 static void *read_write_thread(void *param
) {
110 TestData
<MutexType
> *data
= (TestData
<MutexType
> *)param
;
111 for (int i
= 0; i
< kIters
; i
++) {
121 template<typename MutexType
>
122 static void check_locked(MutexType
*mtx
) {
123 GenericScopedLock
<MutexType
> l(mtx
);
127 TEST(SanitizerCommon
, SpinMutex
) {
130 TestData
<SpinMutex
> data(&mtx
);
131 pthread_t threads
[kThreads
];
132 for (int i
= 0; i
< kThreads
; i
++)
133 PTHREAD_CREATE(&threads
[i
], 0, lock_thread
<SpinMutex
>, &data
);
134 for (int i
= 0; i
< kThreads
; i
++)
135 PTHREAD_JOIN(threads
[i
], 0);
138 TEST(SanitizerCommon
, SpinMutexTry
) {
141 TestData
<SpinMutex
> data(&mtx
);
142 pthread_t threads
[kThreads
];
143 for (int i
= 0; i
< kThreads
; i
++)
144 PTHREAD_CREATE(&threads
[i
], 0, try_thread
<SpinMutex
>, &data
);
145 for (int i
= 0; i
< kThreads
; i
++)
146 PTHREAD_JOIN(threads
[i
], 0);
149 TEST(SanitizerCommon
, Mutex
) {
151 TestData
<Mutex
> data(&mtx
);
152 pthread_t threads
[kThreads
];
153 for (int i
= 0; i
< kThreads
; i
++)
154 PTHREAD_CREATE(&threads
[i
], 0, read_write_thread
<Mutex
>, &data
);
155 for (int i
= 0; i
< kThreads
; i
++) PTHREAD_JOIN(threads
[i
], 0);
158 TEST(SanitizerCommon
, MutexTry
) {
160 TestData
<Mutex
> data(&mtx
);
161 pthread_t threads
[kThreads
];
162 for (int i
= 0; i
< kThreads
; i
++)
163 PTHREAD_CREATE(&threads
[i
], 0, try_thread
<Mutex
>, &data
);
164 for (int i
= 0; i
< kThreads
; i
++) PTHREAD_JOIN(threads
[i
], 0);
167 struct SemaphoreData
{
172 void *SemaphoreThread(void *arg
) {
173 auto data
= static_cast<SemaphoreData
*>(arg
);
179 TEST(SanitizerCommon
, Semaphore
) {
188 SemaphoreData data
= {&sem
, false};
190 PTHREAD_CREATE(&thread
, nullptr, SemaphoreThread
, &data
);
194 PTHREAD_JOIN(thread
, nullptr);
197 } // namespace __sanitizer