sanitizer_mutex_test.cc revision 31dc66f6492773e974d32bde84d5d2df9c35a82b
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//===-- sanitizer_mutex_test.cc -------------------------------------------===// 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The LLVM Compiler Infrastructure 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 5effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch// This file is distributed under the University of Illinois Open Source 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// License. See LICENSE.TXT for details. 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//===----------------------------------------------------------------------===// 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This file is a part of ThreadSanitizer/AddressSanitizer runtime. 11cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//===----------------------------------------------------------------------===// 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sanitizer_common/sanitizer_mutex.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sanitizer_common/sanitizer_common.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "gtest/gtest.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string.h> 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 193551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)namespace __sanitizer { 203551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 21c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochtemplate<typename MutexType> 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class TestData { 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) explicit TestData(MutexType *mtx) 252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) : mtx_(mtx) { 262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (int i = 0; i < kSize; i++) 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) data_[i] = 0; 282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void Write() { 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Lock l(mtx_); 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) T v0 = data_[0]; 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int i = 0; i < kSize; i++) { 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK_EQ(data_[i], v0); 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) data_[i]++; 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void TryWrite() { 40868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (!mtx_->TryLock()) 41868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return; 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) T v0 = data_[0]; 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int i = 0; i < kSize; i++) { 444e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) CHECK_EQ(data_[i], v0); 450529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch data_[i]++; 460529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 470529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch mtx_->Unlock(); 480529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 490529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 500529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch void Backoff() { 510529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch volatile T data[kSize] = {}; 520529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch for (int i = 0; i < kSize; i++) { 530529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch data[i]++; 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK_EQ(data[i], 1); 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) typedef GenericScopedLock<MutexType> Lock; 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static const int kSize = 64; 612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) typedef u64 T; 622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) MutexType *mtx_; 632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) char pad_[kCacheLineSize]; 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) T data_[kSize]; 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kThreads = 8; 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kWriteRate = 1024; 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if SANITIZER_DEBUG 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kIters = 16*1024; 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kIters = 64*1024; 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template<typename MutexType> 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void *lock_thread(void *param) { 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TestData<MutexType> *data = (TestData<MutexType>*)param; 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int i = 0; i < kIters; i++) { 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) data->Write(); 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) data->Backoff(); 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template<typename MutexType> 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void *try_thread(void *param) { 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TestData<MutexType> *data = (TestData<MutexType>*)param; 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int i = 0; i < kIters; i++) { 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) data->TryWrite(); 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) data->Backoff(); 91868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 95cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)TEST(SanitizerCommon, SpinMutex) { 96cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) SpinMutex mtx; 97cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) mtx.Init(); 98cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) TestData<SpinMutex> data(&mtx); 99cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) pthread_t threads[kThreads]; 100cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) for (int i = 0; i < kThreads; i++) 101cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) pthread_create(&threads[i], 0, lock_thread<SpinMutex>, &data); 102cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) for (int i = 0; i < kThreads; i++) 103cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) pthread_join(threads[i], 0); 104cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 105cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 106cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)TEST(SanitizerCommon, SpinMutexTry) { 107cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) SpinMutex mtx; 108cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) mtx.Init(); 109cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) TestData<SpinMutex> data(&mtx); 110cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) pthread_t threads[kThreads]; 111cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) for (int i = 0; i < kThreads; i++) 112cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) pthread_create(&threads[i], 0, try_thread<SpinMutex>, &data); 113cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) for (int i = 0; i < kThreads; i++) 114cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) pthread_join(threads[i], 0); 115cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 116cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 117cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)TEST(SanitizerCommon, BlockingMutex) { 118cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) u64 mtxmem[1024] = {}; 119cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) BlockingMutex *mtx = new(mtxmem) BlockingMutex(LINKER_INITIALIZED); 120cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) TestData<BlockingMutex> data(mtx); 121cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) pthread_t threads[kThreads]; 122cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) for (int i = 0; i < kThreads; i++) 123cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) pthread_create(&threads[i], 0, lock_thread<BlockingMutex>, &data); 124cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) for (int i = 0; i < kThreads; i++) 125cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) pthread_join(threads[i], 0); 126cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 127cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 128cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} // namespace __sanitizer 129cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)