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 #include "gtest/gtest.h"
     16 
     17 #include <string.h>
     18 
     19 namespace __sanitizer {
     20 
     21 template<typename MutexType>
     22 class TestData {
     23  public:
     24   explicit TestData(MutexType *mtx)
     25       : mtx_(mtx) {
     26     for (int i = 0; i < kSize; i++)
     27       data_[i] = 0;
     28   }
     29 
     30   void Write() {
     31     Lock l(mtx_);
     32     T v0 = data_[0];
     33     for (int i = 0; i < kSize; i++) {
     34       CHECK_EQ(data_[i], v0);
     35       data_[i]++;
     36     }
     37   }
     38 
     39   void TryWrite() {
     40     if (!mtx_->TryLock())
     41       return;
     42     T v0 = data_[0];
     43     for (int i = 0; i < kSize; i++) {
     44       CHECK_EQ(data_[i], v0);
     45       data_[i]++;
     46     }
     47     mtx_->Unlock();
     48   }
     49 
     50   void Backoff() {
     51     volatile T data[kSize] = {};
     52     for (int i = 0; i < kSize; i++) {
     53       data[i]++;
     54       CHECK_EQ(data[i], 1);
     55     }
     56   }
     57 
     58  private:
     59   typedef GenericScopedLock<MutexType> Lock;
     60   static const int kSize = 64;
     61   typedef u64 T;
     62   MutexType *mtx_;
     63   char pad_[kCacheLineSize];
     64   T data_[kSize];
     65 };
     66 
     67 const int kThreads = 8;
     68 const int kWriteRate = 1024;
     69 #if SANITIZER_DEBUG
     70 const int kIters = 16*1024;
     71 #else
     72 const int kIters = 64*1024;
     73 #endif
     74 
     75 template<typename MutexType>
     76 static void *lock_thread(void *param) {
     77   TestData<MutexType> *data = (TestData<MutexType>*)param;
     78   for (int i = 0; i < kIters; i++) {
     79     data->Write();
     80     data->Backoff();
     81   }
     82   return 0;
     83 }
     84 
     85 template<typename MutexType>
     86 static void *try_thread(void *param) {
     87   TestData<MutexType> *data = (TestData<MutexType>*)param;
     88   for (int i = 0; i < kIters; i++) {
     89     data->TryWrite();
     90     data->Backoff();
     91   }
     92   return 0;
     93 }
     94 
     95 template<typename MutexType>
     96 static void check_locked(MutexType *mtx) {
     97   GenericScopedLock<MutexType> l(mtx);
     98   mtx->CheckLocked();
     99 }
    100 
    101 TEST(SanitizerCommon, SpinMutex) {
    102   SpinMutex mtx;
    103   mtx.Init();
    104   TestData<SpinMutex> data(&mtx);
    105   pthread_t threads[kThreads];
    106   for (int i = 0; i < kThreads; i++)
    107     pthread_create(&threads[i], 0, lock_thread<SpinMutex>, &data);
    108   for (int i = 0; i < kThreads; i++)
    109     pthread_join(threads[i], 0);
    110 }
    111 
    112 TEST(SanitizerCommon, SpinMutexTry) {
    113   SpinMutex mtx;
    114   mtx.Init();
    115   TestData<SpinMutex> data(&mtx);
    116   pthread_t threads[kThreads];
    117   for (int i = 0; i < kThreads; i++)
    118     pthread_create(&threads[i], 0, try_thread<SpinMutex>, &data);
    119   for (int i = 0; i < kThreads; i++)
    120     pthread_join(threads[i], 0);
    121 }
    122 
    123 TEST(SanitizerCommon, BlockingMutex) {
    124   u64 mtxmem[1024] = {};
    125   BlockingMutex *mtx = new(mtxmem) BlockingMutex(LINKER_INITIALIZED);
    126   TestData<BlockingMutex> data(mtx);
    127   pthread_t threads[kThreads];
    128   for (int i = 0; i < kThreads; i++)
    129     pthread_create(&threads[i], 0, lock_thread<BlockingMutex>, &data);
    130   for (int i = 0; i < kThreads; i++)
    131     pthread_join(threads[i], 0);
    132   check_locked(mtx);
    133 }
    134 
    135 }  // namespace __sanitizer
    136