Home | History | Annotate | Download | only in tests
      1 //===-- sanitizer_mutex_test.cc -------------------------------------------===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 //
     10 // This file is a part of ThreadSanitizer/AddressSanitizer runtime.
     11 //
     12 //===----------------------------------------------------------------------===//
     13 #include "sanitizer_common/sanitizer_mutex.h"
     14 #include "sanitizer_common/sanitizer_common.h"
     15 
     16 #include "sanitizer_pthread_wrappers.h"
     17 
     18 #include "gtest/gtest.h"
     19 
     20 #include <string.h>
     21 
     22 namespace __sanitizer {
     23 
     24 template<typename MutexType>
     25 class TestData {
     26  public:
     27   explicit TestData(MutexType *mtx)
     28       : mtx_(mtx) {
     29     for (int i = 0; i < kSize; i++)
     30       data_[i] = 0;
     31   }
     32 
     33   void Write() {
     34     Lock l(mtx_);
     35     T v0 = data_[0];
     36     for (int i = 0; i < kSize; i++) {
     37       CHECK_EQ(data_[i], v0);
     38       data_[i]++;
     39     }
     40   }
     41 
     42   void TryWrite() {
     43     if (!mtx_->TryLock())
     44       return;
     45     T v0 = data_[0];
     46     for (int i = 0; i < kSize; i++) {
     47       CHECK_EQ(data_[i], v0);
     48       data_[i]++;
     49     }
     50     mtx_->Unlock();
     51   }
     52 
     53   void Backoff() {
     54     volatile T data[kSize] = {};
     55     for (int i = 0; i < kSize; i++) {
     56       data[i]++;
     57       CHECK_EQ(data[i], 1);
     58     }
     59   }
     60 
     61  private:
     62   typedef GenericScopedLock<MutexType> Lock;
     63   static const int kSize = 64;
     64   typedef u64 T;
     65   MutexType *mtx_;
     66   char pad_[kCacheLineSize];
     67   T data_[kSize];
     68 };
     69 
     70 const int kThreads = 8;
     71 #if SANITIZER_DEBUG
     72 const int kIters = 16*1024;
     73 #else
     74 const int kIters = 64*1024;
     75 #endif
     76 
     77 template<typename MutexType>
     78 static void *lock_thread(void *param) {
     79   TestData<MutexType> *data = (TestData<MutexType>*)param;
     80   for (int i = 0; i < kIters; i++) {
     81     data->Write();
     82     data->Backoff();
     83   }
     84   return 0;
     85 }
     86 
     87 template<typename MutexType>
     88 static void *try_thread(void *param) {
     89   TestData<MutexType> *data = (TestData<MutexType>*)param;
     90   for (int i = 0; i < kIters; i++) {
     91     data->TryWrite();
     92     data->Backoff();
     93   }
     94   return 0;
     95 }
     96 
     97 template<typename MutexType>
     98 static void check_locked(MutexType *mtx) {
     99   GenericScopedLock<MutexType> l(mtx);
    100   mtx->CheckLocked();
    101 }
    102 
    103 TEST(SanitizerCommon, SpinMutex) {
    104   SpinMutex mtx;
    105   mtx.Init();
    106   TestData<SpinMutex> data(&mtx);
    107   pthread_t threads[kThreads];
    108   for (int i = 0; i < kThreads; i++)
    109     PTHREAD_CREATE(&threads[i], 0, lock_thread<SpinMutex>, &data);
    110   for (int i = 0; i < kThreads; i++)
    111     PTHREAD_JOIN(threads[i], 0);
    112 }
    113 
    114 TEST(SanitizerCommon, SpinMutexTry) {
    115   SpinMutex mtx;
    116   mtx.Init();
    117   TestData<SpinMutex> data(&mtx);
    118   pthread_t threads[kThreads];
    119   for (int i = 0; i < kThreads; i++)
    120     PTHREAD_CREATE(&threads[i], 0, try_thread<SpinMutex>, &data);
    121   for (int i = 0; i < kThreads; i++)
    122     PTHREAD_JOIN(threads[i], 0);
    123 }
    124 
    125 TEST(SanitizerCommon, BlockingMutex) {
    126   u64 mtxmem[1024] = {};
    127   BlockingMutex *mtx = new(mtxmem) BlockingMutex(LINKER_INITIALIZED);
    128   TestData<BlockingMutex> data(mtx);
    129   pthread_t threads[kThreads];
    130   for (int i = 0; i < kThreads; i++)
    131     PTHREAD_CREATE(&threads[i], 0, lock_thread<BlockingMutex>, &data);
    132   for (int i = 0; i < kThreads; i++)
    133     PTHREAD_JOIN(threads[i], 0);
    134   check_locked(mtx);
    135 }
    136 
    137 }  // namespace __sanitizer
    138