parent
f22982bf0a
commit
3d462f89de
|
@ -0,0 +1,128 @@
|
|||
//===-- sanitizer_mutex_test.cc -------------------------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file is a part of ThreadSanitizer/AddressSanitizer runtime.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
#include "sanitizer_common/sanitizer_mutex.h"
|
||||
#include "sanitizer_common/sanitizer_common.h"
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
namespace __sanitizer {
|
||||
|
||||
template<typename MutexType>
|
||||
class TestData {
|
||||
public:
|
||||
explicit TestData(MutexType *mtx)
|
||||
: mtx_(mtx) {
|
||||
for (int i = 0; i < kSize; i++)
|
||||
data_[i] = 0;
|
||||
}
|
||||
|
||||
void Write() {
|
||||
Lock l(mtx_);
|
||||
T v0 = data_[0];
|
||||
for (int i = 0; i < kSize; i++) {
|
||||
CHECK_EQ(data_[i], v0);
|
||||
data_[i]++;
|
||||
}
|
||||
}
|
||||
|
||||
void TryWrite() {
|
||||
if (!mtx_->TryLock())
|
||||
return;
|
||||
T v0 = data_[0];
|
||||
for (int i = 0; i < kSize; i++) {
|
||||
CHECK_EQ(data_[i], v0);
|
||||
data_[i]++;
|
||||
}
|
||||
mtx_->Unlock();
|
||||
}
|
||||
|
||||
void Backoff() {
|
||||
volatile T data[kSize] = {};
|
||||
for (int i = 0; i < kSize; i++) {
|
||||
data[i]++;
|
||||
CHECK_EQ(data[i], 1);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
typedef GenericScopedLock<MutexType> Lock;
|
||||
static const int kSize = 64;
|
||||
typedef u64 T;
|
||||
MutexType *mtx_;
|
||||
char pad_[kCacheLineSize];
|
||||
T data_[kSize];
|
||||
};
|
||||
|
||||
const int kThreads = 8;
|
||||
const int kWriteRate = 1024;
|
||||
#if SANITIZER_DEBUG
|
||||
const int kIters = 16*1024;
|
||||
#else
|
||||
const int kIters = 64*1024;
|
||||
#endif
|
||||
|
||||
template<typename MutexType>
|
||||
static void *lock_thread(void *param) {
|
||||
TestData<MutexType> *data = (TestData<MutexType>*)param;
|
||||
for (int i = 0; i < kIters; i++) {
|
||||
data->Write();
|
||||
data->Backoff();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
template<typename MutexType>
|
||||
static void *try_thread(void *param) {
|
||||
TestData<MutexType> *data = (TestData<MutexType>*)param;
|
||||
for (int i = 0; i < kIters; i++) {
|
||||
data->TryWrite();
|
||||
data->Backoff();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
TEST(SanitizerCommon, SpinMutex) {
|
||||
SpinMutex mtx;
|
||||
mtx.Init();
|
||||
TestData<SpinMutex> data(&mtx);
|
||||
pthread_t threads[kThreads];
|
||||
for (int i = 0; i < kThreads; i++)
|
||||
pthread_create(&threads[i], 0, lock_thread<SpinMutex>, &data);
|
||||
for (int i = 0; i < kThreads; i++)
|
||||
pthread_join(threads[i], 0);
|
||||
}
|
||||
|
||||
TEST(SanitizerCommon, SpinMutexTry) {
|
||||
SpinMutex mtx;
|
||||
mtx.Init();
|
||||
TestData<SpinMutex> data(&mtx);
|
||||
pthread_t threads[kThreads];
|
||||
for (int i = 0; i < kThreads; i++)
|
||||
pthread_create(&threads[i], 0, try_thread<SpinMutex>, &data);
|
||||
for (int i = 0; i < kThreads; i++)
|
||||
pthread_join(threads[i], 0);
|
||||
}
|
||||
|
||||
TEST(SanitizerCommon, BlockingMutex) {
|
||||
u64 mtxmem[1024] = {};
|
||||
BlockingMutex *mtx = new(mtxmem) BlockingMutex(LINKER_INITIALIZED);
|
||||
TestData<BlockingMutex> data(mtx);
|
||||
pthread_t threads[kThreads];
|
||||
for (int i = 0; i < kThreads; i++)
|
||||
pthread_create(&threads[i], 0, lock_thread<BlockingMutex>, &data);
|
||||
for (int i = 0; i < kThreads; i++)
|
||||
pthread_join(threads[i], 0);
|
||||
}
|
||||
|
||||
} // namespace __sanitizer
|
Loading…
Reference in New Issue