131dc66f6492773e974d32bde84d5d2df9c35a82bDmitry Vyukov//===-- sanitizer_mutex_test.cc -------------------------------------------===// 231dc66f6492773e974d32bde84d5d2df9c35a82bDmitry Vyukov// 331dc66f6492773e974d32bde84d5d2df9c35a82bDmitry Vyukov// The LLVM Compiler Infrastructure 431dc66f6492773e974d32bde84d5d2df9c35a82bDmitry Vyukov// 531dc66f6492773e974d32bde84d5d2df9c35a82bDmitry Vyukov// This file is distributed under the University of Illinois Open Source 631dc66f6492773e974d32bde84d5d2df9c35a82bDmitry Vyukov// License. See LICENSE.TXT for details. 731dc66f6492773e974d32bde84d5d2df9c35a82bDmitry Vyukov// 831dc66f6492773e974d32bde84d5d2df9c35a82bDmitry Vyukov//===----------------------------------------------------------------------===// 931dc66f6492773e974d32bde84d5d2df9c35a82bDmitry Vyukov// 1031dc66f6492773e974d32bde84d5d2df9c35a82bDmitry Vyukov// This file is a part of ThreadSanitizer/AddressSanitizer runtime. 1131dc66f6492773e974d32bde84d5d2df9c35a82bDmitry Vyukov// 1231dc66f6492773e974d32bde84d5d2df9c35a82bDmitry Vyukov//===----------------------------------------------------------------------===// 1331dc66f6492773e974d32bde84d5d2df9c35a82bDmitry Vyukov#include "sanitizer_common/sanitizer_mutex.h" 1431dc66f6492773e974d32bde84d5d2df9c35a82bDmitry Vyukov#include "sanitizer_common/sanitizer_common.h" 152d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 162d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#include "sanitizer_pthread_wrappers.h" 172d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 1831dc66f6492773e974d32bde84d5d2df9c35a82bDmitry Vyukov#include "gtest/gtest.h" 1931dc66f6492773e974d32bde84d5d2df9c35a82bDmitry Vyukov 2031dc66f6492773e974d32bde84d5d2df9c35a82bDmitry Vyukov#include <string.h> 2131dc66f6492773e974d32bde84d5d2df9c35a82bDmitry Vyukov 2231dc66f6492773e974d32bde84d5d2df9c35a82bDmitry Vyukovnamespace __sanitizer { 2331dc66f6492773e974d32bde84d5d2df9c35a82bDmitry Vyukov 2431dc66f6492773e974d32bde84d5d2df9c35a82bDmitry Vyukovtemplate<typename MutexType> 2531dc66f6492773e974d32bde84d5d2df9c35a82bDmitry Vyukovclass TestData { 2631dc66f6492773e974d32bde84d5d2df9c35a82bDmitry Vyukov public: 2731dc66f6492773e974d32bde84d5d2df9c35a82bDmitry Vyukov explicit TestData(MutexType *mtx) 2831dc66f6492773e974d32bde84d5d2df9c35a82bDmitry Vyukov : mtx_(mtx) { 2931dc66f6492773e974d32bde84d5d2df9c35a82bDmitry Vyukov for (int i = 0; i < kSize; i++) 3031dc66f6492773e974d32bde84d5d2df9c35a82bDmitry Vyukov data_[i] = 0; 3131dc66f6492773e974d32bde84d5d2df9c35a82bDmitry Vyukov } 3231dc66f6492773e974d32bde84d5d2df9c35a82bDmitry Vyukov 3331dc66f6492773e974d32bde84d5d2df9c35a82bDmitry Vyukov void Write() { 3431dc66f6492773e974d32bde84d5d2df9c35a82bDmitry Vyukov Lock l(mtx_); 3531dc66f6492773e974d32bde84d5d2df9c35a82bDmitry Vyukov T v0 = data_[0]; 3631dc66f6492773e974d32bde84d5d2df9c35a82bDmitry Vyukov for (int i = 0; i < kSize; i++) { 3731dc66f6492773e974d32bde84d5d2df9c35a82bDmitry Vyukov CHECK_EQ(data_[i], v0); 3831dc66f6492773e974d32bde84d5d2df9c35a82bDmitry Vyukov data_[i]++; 3931dc66f6492773e974d32bde84d5d2df9c35a82bDmitry Vyukov } 4031dc66f6492773e974d32bde84d5d2df9c35a82bDmitry Vyukov } 4131dc66f6492773e974d32bde84d5d2df9c35a82bDmitry Vyukov 4231dc66f6492773e974d32bde84d5d2df9c35a82bDmitry Vyukov void TryWrite() { 4331dc66f6492773e974d32bde84d5d2df9c35a82bDmitry Vyukov if (!mtx_->TryLock()) 4431dc66f6492773e974d32bde84d5d2df9c35a82bDmitry Vyukov return; 4531dc66f6492773e974d32bde84d5d2df9c35a82bDmitry Vyukov T v0 = data_[0]; 4631dc66f6492773e974d32bde84d5d2df9c35a82bDmitry Vyukov for (int i = 0; i < kSize; i++) { 4731dc66f6492773e974d32bde84d5d2df9c35a82bDmitry Vyukov CHECK_EQ(data_[i], v0); 4831dc66f6492773e974d32bde84d5d2df9c35a82bDmitry Vyukov data_[i]++; 4931dc66f6492773e974d32bde84d5d2df9c35a82bDmitry Vyukov } 5031dc66f6492773e974d32bde84d5d2df9c35a82bDmitry Vyukov mtx_->Unlock(); 5131dc66f6492773e974d32bde84d5d2df9c35a82bDmitry Vyukov } 5231dc66f6492773e974d32bde84d5d2df9c35a82bDmitry Vyukov 5331dc66f6492773e974d32bde84d5d2df9c35a82bDmitry Vyukov void Backoff() { 5431dc66f6492773e974d32bde84d5d2df9c35a82bDmitry Vyukov volatile T data[kSize] = {}; 5531dc66f6492773e974d32bde84d5d2df9c35a82bDmitry Vyukov for (int i = 0; i < kSize; i++) { 5631dc66f6492773e974d32bde84d5d2df9c35a82bDmitry Vyukov data[i]++; 5731dc66f6492773e974d32bde84d5d2df9c35a82bDmitry Vyukov CHECK_EQ(data[i], 1); 5831dc66f6492773e974d32bde84d5d2df9c35a82bDmitry Vyukov } 5931dc66f6492773e974d32bde84d5d2df9c35a82bDmitry Vyukov } 6031dc66f6492773e974d32bde84d5d2df9c35a82bDmitry Vyukov 6131dc66f6492773e974d32bde84d5d2df9c35a82bDmitry Vyukov private: 6231dc66f6492773e974d32bde84d5d2df9c35a82bDmitry Vyukov typedef GenericScopedLock<MutexType> Lock; 6331dc66f6492773e974d32bde84d5d2df9c35a82bDmitry Vyukov static const int kSize = 64; 6431dc66f6492773e974d32bde84d5d2df9c35a82bDmitry Vyukov typedef u64 T; 6531dc66f6492773e974d32bde84d5d2df9c35a82bDmitry Vyukov MutexType *mtx_; 6631dc66f6492773e974d32bde84d5d2df9c35a82bDmitry Vyukov char pad_[kCacheLineSize]; 6731dc66f6492773e974d32bde84d5d2df9c35a82bDmitry Vyukov T data_[kSize]; 6831dc66f6492773e974d32bde84d5d2df9c35a82bDmitry Vyukov}; 6931dc66f6492773e974d32bde84d5d2df9c35a82bDmitry Vyukov 7031dc66f6492773e974d32bde84d5d2df9c35a82bDmitry Vyukovconst int kThreads = 8; 7131dc66f6492773e974d32bde84d5d2df9c35a82bDmitry Vyukov#if SANITIZER_DEBUG 7231dc66f6492773e974d32bde84d5d2df9c35a82bDmitry Vyukovconst int kIters = 16*1024; 7331dc66f6492773e974d32bde84d5d2df9c35a82bDmitry Vyukov#else 7431dc66f6492773e974d32bde84d5d2df9c35a82bDmitry Vyukovconst int kIters = 64*1024; 7531dc66f6492773e974d32bde84d5d2df9c35a82bDmitry Vyukov#endif 7631dc66f6492773e974d32bde84d5d2df9c35a82bDmitry Vyukov 7731dc66f6492773e974d32bde84d5d2df9c35a82bDmitry Vyukovtemplate<typename MutexType> 7831dc66f6492773e974d32bde84d5d2df9c35a82bDmitry Vyukovstatic void *lock_thread(void *param) { 7931dc66f6492773e974d32bde84d5d2df9c35a82bDmitry Vyukov TestData<MutexType> *data = (TestData<MutexType>*)param; 8031dc66f6492773e974d32bde84d5d2df9c35a82bDmitry Vyukov for (int i = 0; i < kIters; i++) { 8131dc66f6492773e974d32bde84d5d2df9c35a82bDmitry Vyukov data->Write(); 8231dc66f6492773e974d32bde84d5d2df9c35a82bDmitry Vyukov data->Backoff(); 8331dc66f6492773e974d32bde84d5d2df9c35a82bDmitry Vyukov } 8431dc66f6492773e974d32bde84d5d2df9c35a82bDmitry Vyukov return 0; 8531dc66f6492773e974d32bde84d5d2df9c35a82bDmitry Vyukov} 8631dc66f6492773e974d32bde84d5d2df9c35a82bDmitry Vyukov 8731dc66f6492773e974d32bde84d5d2df9c35a82bDmitry Vyukovtemplate<typename MutexType> 8831dc66f6492773e974d32bde84d5d2df9c35a82bDmitry Vyukovstatic void *try_thread(void *param) { 8931dc66f6492773e974d32bde84d5d2df9c35a82bDmitry Vyukov TestData<MutexType> *data = (TestData<MutexType>*)param; 9031dc66f6492773e974d32bde84d5d2df9c35a82bDmitry Vyukov for (int i = 0; i < kIters; i++) { 9131dc66f6492773e974d32bde84d5d2df9c35a82bDmitry Vyukov data->TryWrite(); 9231dc66f6492773e974d32bde84d5d2df9c35a82bDmitry Vyukov data->Backoff(); 9331dc66f6492773e974d32bde84d5d2df9c35a82bDmitry Vyukov } 9431dc66f6492773e974d32bde84d5d2df9c35a82bDmitry Vyukov return 0; 9531dc66f6492773e974d32bde84d5d2df9c35a82bDmitry Vyukov} 9631dc66f6492773e974d32bde84d5d2df9c35a82bDmitry Vyukov 97ce700979f644c790c2d9d80f5cc2a1ada0380284Alexey Samsonovtemplate<typename MutexType> 98ce700979f644c790c2d9d80f5cc2a1ada0380284Alexey Samsonovstatic void check_locked(MutexType *mtx) { 99ce700979f644c790c2d9d80f5cc2a1ada0380284Alexey Samsonov GenericScopedLock<MutexType> l(mtx); 100ce700979f644c790c2d9d80f5cc2a1ada0380284Alexey Samsonov mtx->CheckLocked(); 101ce700979f644c790c2d9d80f5cc2a1ada0380284Alexey Samsonov} 102ce700979f644c790c2d9d80f5cc2a1ada0380284Alexey Samsonov 10331dc66f6492773e974d32bde84d5d2df9c35a82bDmitry VyukovTEST(SanitizerCommon, SpinMutex) { 10431dc66f6492773e974d32bde84d5d2df9c35a82bDmitry Vyukov SpinMutex mtx; 10531dc66f6492773e974d32bde84d5d2df9c35a82bDmitry Vyukov mtx.Init(); 10631dc66f6492773e974d32bde84d5d2df9c35a82bDmitry Vyukov TestData<SpinMutex> data(&mtx); 10731dc66f6492773e974d32bde84d5d2df9c35a82bDmitry Vyukov pthread_t threads[kThreads]; 10831dc66f6492773e974d32bde84d5d2df9c35a82bDmitry Vyukov for (int i = 0; i < kThreads; i++) 1092d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines PTHREAD_CREATE(&threads[i], 0, lock_thread<SpinMutex>, &data); 11031dc66f6492773e974d32bde84d5d2df9c35a82bDmitry Vyukov for (int i = 0; i < kThreads; i++) 1112d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines PTHREAD_JOIN(threads[i], 0); 11231dc66f6492773e974d32bde84d5d2df9c35a82bDmitry Vyukov} 11331dc66f6492773e974d32bde84d5d2df9c35a82bDmitry Vyukov 11431dc66f6492773e974d32bde84d5d2df9c35a82bDmitry VyukovTEST(SanitizerCommon, SpinMutexTry) { 11531dc66f6492773e974d32bde84d5d2df9c35a82bDmitry Vyukov SpinMutex mtx; 11631dc66f6492773e974d32bde84d5d2df9c35a82bDmitry Vyukov mtx.Init(); 11731dc66f6492773e974d32bde84d5d2df9c35a82bDmitry Vyukov TestData<SpinMutex> data(&mtx); 11831dc66f6492773e974d32bde84d5d2df9c35a82bDmitry Vyukov pthread_t threads[kThreads]; 11931dc66f6492773e974d32bde84d5d2df9c35a82bDmitry Vyukov for (int i = 0; i < kThreads; i++) 1202d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines PTHREAD_CREATE(&threads[i], 0, try_thread<SpinMutex>, &data); 12131dc66f6492773e974d32bde84d5d2df9c35a82bDmitry Vyukov for (int i = 0; i < kThreads; i++) 1222d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines PTHREAD_JOIN(threads[i], 0); 12331dc66f6492773e974d32bde84d5d2df9c35a82bDmitry Vyukov} 12431dc66f6492773e974d32bde84d5d2df9c35a82bDmitry Vyukov 12531dc66f6492773e974d32bde84d5d2df9c35a82bDmitry VyukovTEST(SanitizerCommon, BlockingMutex) { 12631dc66f6492773e974d32bde84d5d2df9c35a82bDmitry Vyukov u64 mtxmem[1024] = {}; 12731dc66f6492773e974d32bde84d5d2df9c35a82bDmitry Vyukov BlockingMutex *mtx = new(mtxmem) BlockingMutex(LINKER_INITIALIZED); 12831dc66f6492773e974d32bde84d5d2df9c35a82bDmitry Vyukov TestData<BlockingMutex> data(mtx); 12931dc66f6492773e974d32bde84d5d2df9c35a82bDmitry Vyukov pthread_t threads[kThreads]; 13031dc66f6492773e974d32bde84d5d2df9c35a82bDmitry Vyukov for (int i = 0; i < kThreads; i++) 1312d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines PTHREAD_CREATE(&threads[i], 0, lock_thread<BlockingMutex>, &data); 13231dc66f6492773e974d32bde84d5d2df9c35a82bDmitry Vyukov for (int i = 0; i < kThreads; i++) 1332d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines PTHREAD_JOIN(threads[i], 0); 134ce700979f644c790c2d9d80f5cc2a1ada0380284Alexey Samsonov check_locked(mtx); 13531dc66f6492773e974d32bde84d5d2df9c35a82bDmitry Vyukov} 13631dc66f6492773e974d32bde84d5d2df9c35a82bDmitry Vyukov 13731dc66f6492773e974d32bde84d5d2df9c35a82bDmitry Vyukov} // namespace __sanitizer 138