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)