Home | History | Annotate | Download | only in tsan
      1 // RUN: %clangxx_tsan %s -o %t -DLockType=PthreadMutex
      2 // RUN: TSAN_OPTIONS=detect_deadlocks=1 %deflake %run %t | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-NOT-SECOND
      3 // RUN: TSAN_OPTIONS="detect_deadlocks=1 second_deadlock_stack=1" %deflake %run %t | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-SECOND
      4 // RUN: %clangxx_tsan %s -o %t -DLockType=PthreadSpinLock
      5 // RUN: TSAN_OPTIONS=detect_deadlocks=1 %deflake %run %t | FileCheck %s
      6 // RUN: %clangxx_tsan %s -o %t -DLockType=PthreadRWLock
      7 // RUN: TSAN_OPTIONS=detect_deadlocks=1 %deflake %run %t | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-RD
      8 // RUN: %clangxx_tsan %s -o %t -DLockType=PthreadRecursiveMutex
      9 // RUN: TSAN_OPTIONS=detect_deadlocks=1 %deflake %run %t | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-REC
     10 #include "test.h"
     11 #undef NDEBUG
     12 #include <assert.h>
     13 #include <new>
     14 
     15 #ifndef LockType
     16 #define LockType PthreadMutex
     17 #endif
     18 
     19 // You can optionally pass [test_number [iter_count]] on command line.
     20 static int test_number = -1;
     21 static int iter_count = 100000;
     22 
     23 class PthreadMutex {
     24  public:
     25   explicit PthreadMutex(bool recursive = false) {
     26     if (recursive) {
     27       pthread_mutexattr_t attr;
     28       pthread_mutexattr_init(&attr);
     29       pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
     30       assert(0 == pthread_mutex_init(&mu_, &attr));
     31     } else {
     32       assert(0 == pthread_mutex_init(&mu_, 0));
     33     }
     34   }
     35   ~PthreadMutex() {
     36     assert(0 == pthread_mutex_destroy(&mu_));
     37     (void)padding_;
     38   }
     39   static bool supports_read_lock() { return false; }
     40   static bool supports_recursive_lock() { return false; }
     41   void lock() { assert(0 == pthread_mutex_lock(&mu_)); }
     42   void unlock() { assert(0 == pthread_mutex_unlock(&mu_)); }
     43   bool try_lock() { return 0 == pthread_mutex_trylock(&mu_); }
     44   void rdlock() { assert(0); }
     45   void rdunlock() { assert(0); }
     46   bool try_rdlock() { assert(0); }
     47 
     48  private:
     49   pthread_mutex_t mu_;
     50   char padding_[64 - sizeof(pthread_mutex_t)];
     51 };
     52 
     53 class PthreadRecursiveMutex : public PthreadMutex {
     54  public:
     55   PthreadRecursiveMutex() : PthreadMutex(true) { }
     56   static bool supports_recursive_lock() { return true; }
     57 };
     58 
     59 class PthreadSpinLock {
     60  public:
     61   PthreadSpinLock() { assert(0 == pthread_spin_init(&mu_, 0)); }
     62   ~PthreadSpinLock() {
     63     assert(0 == pthread_spin_destroy(&mu_));
     64     (void)padding_;
     65   }
     66   static bool supports_read_lock() { return false; }
     67   static bool supports_recursive_lock() { return false; }
     68   void lock() { assert(0 == pthread_spin_lock(&mu_)); }
     69   void unlock() { assert(0 == pthread_spin_unlock(&mu_)); }
     70   bool try_lock() { return 0 == pthread_spin_trylock(&mu_); }
     71   void rdlock() { assert(0); }
     72   void rdunlock() { assert(0); }
     73   bool try_rdlock() { assert(0); }
     74 
     75  private:
     76   pthread_spinlock_t mu_;
     77   char padding_[64 - sizeof(pthread_spinlock_t)];
     78 };
     79 
     80 class PthreadRWLock {
     81  public:
     82   PthreadRWLock() { assert(0 == pthread_rwlock_init(&mu_, 0)); }
     83   ~PthreadRWLock() {
     84     assert(0 == pthread_rwlock_destroy(&mu_));
     85     (void)padding_;
     86   }
     87   static bool supports_read_lock() { return true; }
     88   static bool supports_recursive_lock() { return false; }
     89   void lock() { assert(0 == pthread_rwlock_wrlock(&mu_)); }
     90   void unlock() { assert(0 == pthread_rwlock_unlock(&mu_)); }
     91   bool try_lock() { return 0 == pthread_rwlock_trywrlock(&mu_); }
     92   void rdlock() { assert(0 == pthread_rwlock_rdlock(&mu_)); }
     93   void rdunlock() { assert(0 == pthread_rwlock_unlock(&mu_)); }
     94   bool try_rdlock() { return 0 == pthread_rwlock_tryrdlock(&mu_); }
     95 
     96  private:
     97   pthread_rwlock_t mu_;
     98   char padding_[64 - sizeof(pthread_rwlock_t)];
     99 };
    100 
    101 class LockTest {
    102  public:
    103   LockTest() : n_(), locks_() {}
    104   void Init(size_t n) {
    105     n_ = n;
    106     locks_ = new LockType*[n_];
    107     for (size_t i = 0; i < n_; i++)
    108       locks_[i] = new LockType;
    109   }
    110   ~LockTest() {
    111     for (size_t i = 0; i < n_; i++)
    112       delete locks_[i];
    113     delete [] locks_;
    114   }
    115   void L(size_t i) {
    116     assert(i < n_);
    117     locks_[i]->lock();
    118   }
    119 
    120   void U(size_t i) {
    121     assert(i < n_);
    122     locks_[i]->unlock();
    123   }
    124 
    125   void RL(size_t i) {
    126     assert(i < n_);
    127     locks_[i]->rdlock();
    128   }
    129 
    130   void RU(size_t i) {
    131     assert(i < n_);
    132     locks_[i]->rdunlock();
    133   }
    134 
    135   void *A(size_t i) {
    136     assert(i < n_);
    137     return locks_[i];
    138   }
    139 
    140   bool T(size_t i) {
    141     assert(i < n_);
    142     return locks_[i]->try_lock();
    143   }
    144 
    145   // Simple lock order onversion.
    146   void Test1() {
    147     if (test_number > 0 && test_number != 1) return;
    148     fprintf(stderr, "Starting Test1\n");
    149     // CHECK: Starting Test1
    150     Init(5);
    151     fprintf(stderr, "Expecting lock inversion: %p %p\n", A(0), A(1));
    152     // CHECK: Expecting lock inversion: [[A1:0x[a-f0-9]*]] [[A2:0x[a-f0-9]*]]
    153     Lock_0_1();
    154     Lock_1_0();
    155     // CHECK: WARNING: ThreadSanitizer: lock-order-inversion (potential deadlock)
    156     // CHECK: Cycle in lock order graph: [[M1:M[0-9]+]] ([[A1]]) => [[M2:M[0-9]+]] ([[A2]]) => [[M1]]
    157     // CHECK: Mutex [[M2]] acquired here while holding mutex [[M1]]
    158     // CHECK:   #0 pthread_
    159     // CHECK-SECOND:   Mutex [[M1]] previously acquired by the same thread here:
    160     // CHECK-SECOND:   #0 pthread_
    161     // CHECK-NOT-SECOND:   second_deadlock_stack=1 to get more informative warning message
    162     // CHECK-NOT-SECOND-NOT:   #0 pthread_
    163     // CHECK: Mutex [[M1]] acquired here while holding mutex [[M2]]
    164     // CHECK:   #0 pthread_
    165     // CHECK-SECOND:   Mutex [[M2]] previously acquired by the same thread here:
    166     // CHECK-SECOND:   #0 pthread_
    167     // CHECK-NOT-SECOND-NOT:   #0 pthread_
    168     // CHECK-NOT: WARNING: ThreadSanitizer:
    169   }
    170 
    171   // Simple lock order inversion with 3 locks.
    172   void Test2() {
    173     if (test_number > 0 && test_number != 2) return;
    174     fprintf(stderr, "Starting Test2\n");
    175     // CHECK: Starting Test2
    176     Init(5);
    177     fprintf(stderr, "Expecting lock inversion: %p %p %p\n", A(0), A(1), A(2));
    178     // CHECK: Expecting lock inversion: [[A1:0x[a-f0-9]*]] [[A2:0x[a-f0-9]*]] [[A3:0x[a-f0-9]*]]
    179     Lock2(0, 1);
    180     Lock2(1, 2);
    181     Lock2(2, 0);
    182     // CHECK: WARNING: ThreadSanitizer: lock-order-inversion (potential deadlock)
    183     // CHECK: Cycle in lock order graph: [[M1:M[0-9]+]] ([[A1]]) => [[M2:M[0-9]+]] ([[A2]]) => [[M3:M[0-9]+]] ([[A3]]) => [[M1]]
    184     // CHECK-NOT: WARNING: ThreadSanitizer:
    185   }
    186 
    187   // Lock order inversion with lots of new locks created (but not used)
    188   // between. Since the new locks are not used we should still detect the
    189   // deadlock.
    190   void Test3() {
    191     if (test_number > 0 && test_number != 3) return;
    192     fprintf(stderr, "Starting Test3\n");
    193     // CHECK: Starting Test3
    194     Init(5);
    195     Lock_0_1();
    196     L(2);
    197     CreateAndDestroyManyLocks();
    198     U(2);
    199     Lock_1_0();
    200     // CHECK: WARNING: ThreadSanitizer: lock-order-inversion (potential deadlock)
    201     // CHECK-NOT: WARNING: ThreadSanitizer:
    202   }
    203 
    204   // lock l0=>l1; then create and use lots of locks; then lock l1=>l0.
    205   // The deadlock epoch should have changed and we should not report anything.
    206   void Test4() {
    207     if (test_number > 0 && test_number != 4) return;
    208     fprintf(stderr, "Starting Test4\n");
    209     // CHECK: Starting Test4
    210     Init(5);
    211     Lock_0_1();
    212     L(2);
    213     CreateLockUnlockAndDestroyManyLocks();
    214     U(2);
    215     Lock_1_0();
    216     // CHECK-NOT: WARNING: ThreadSanitizer:
    217   }
    218 
    219   void Test5() {
    220     if (test_number > 0 && test_number != 5) return;
    221     fprintf(stderr, "Starting Test5\n");
    222     // CHECK: Starting Test5
    223     Init(5);
    224     RunThreads(&LockTest::Lock_0_1<true>, &LockTest::Lock_1_0<true>);
    225     // CHECK: WARNING: ThreadSanitizer: lock-order-inversion
    226     // CHECK: Cycle in lock order graph: [[M1:M[0-9]+]] ({{.*}}) => [[M2:M[0-9]+]] ({{.*}}) => [[M1]]
    227     // CHECK: Mutex [[M2]] acquired here while holding mutex [[M1]] in thread [[T1:T[0-9]+]]
    228     // CHECK: Mutex [[M1]] acquired here while holding mutex [[M2]] in thread [[T2:T[0-9]+]]
    229     // CHECK: Thread [[T1]] {{.*}} created by main thread
    230     // CHECK: Thread [[T2]] {{.*}} created by main thread
    231     // CHECK-NOT: WARNING: ThreadSanitizer:
    232   }
    233 
    234   void Test6() {
    235     if (test_number > 0 && test_number != 6) return;
    236     fprintf(stderr, "Starting Test6: 3 threads lock/unlock private mutexes\n");
    237     // CHECK: Starting Test6
    238     Init(100);
    239     // CHECK-NOT: WARNING: ThreadSanitizer:
    240     RunThreads(&LockTest::Lock1_Loop_0, &LockTest::Lock1_Loop_1,
    241                &LockTest::Lock1_Loop_2);
    242   }
    243 
    244   void Test7() {
    245     if (test_number > 0 && test_number != 7) return;
    246     fprintf(stderr, "Starting Test7\n");
    247     // CHECK: Starting Test7
    248     Init(10);
    249     L(0); T(1); U(1); U(0);
    250     T(1); L(0); U(1); U(0);
    251     // CHECK-NOT: WARNING: ThreadSanitizer:
    252     fprintf(stderr, "No cycle: 0=>1\n");
    253     // CHECK: No cycle: 0=>1
    254 
    255     T(2); L(3); U(3); U(2);
    256     L(3); T(2); U(3); U(2);
    257     // CHECK-NOT: WARNING: ThreadSanitizer:
    258     fprintf(stderr, "No cycle: 2=>3\n");
    259     // CHECK: No cycle: 2=>3
    260 
    261     T(4); L(5); U(4); U(5);
    262     L(5); L(4); U(4); U(5);
    263     // CHECK: WARNING: ThreadSanitizer: lock-order-inversion
    264     fprintf(stderr, "Have cycle: 4=>5\n");
    265     // CHECK: Have cycle: 4=>5
    266 
    267     L(7); L(6); U(6); U(7);
    268     T(6); L(7); U(6); U(7);
    269     // CHECK: WARNING: ThreadSanitizer: lock-order-inversion
    270     fprintf(stderr, "Have cycle: 6=>7\n");
    271     // CHECK: Have cycle: 6=>7
    272   }
    273 
    274   void Test8() {
    275     if (test_number > 0 && test_number != 8) return;
    276     if (!LockType::supports_read_lock()) return;
    277     fprintf(stderr, "Starting Test8\n");
    278     Init(5);
    279     // CHECK-RD: Starting Test8
    280     RL(0); L(1); RU(0); U(1);
    281     L(1); RL(0); RU(0); U(1);
    282     // CHECK-RD: WARNING: ThreadSanitizer: lock-order-inversion
    283     fprintf(stderr, "Have cycle: 0=>1\n");
    284     // CHECK-RD: Have cycle: 0=>1
    285 
    286     RL(2); RL(3); RU(2); RU(3);
    287     RL(3); RL(2); RU(2); RU(3);
    288     // CHECK-RD: WARNING: ThreadSanitizer: lock-order-inversion
    289     fprintf(stderr, "Have cycle: 2=>3\n");
    290     // CHECK-RD: Have cycle: 2=>3
    291   }
    292 
    293   void Test9() {
    294     if (test_number > 0 && test_number != 9) return;
    295     if (!LockType::supports_recursive_lock()) return;
    296     fprintf(stderr, "Starting Test9\n");
    297     // CHECK-REC: Starting Test9
    298     Init(5);
    299     L(0); L(0); L(0); L(1); U(1); U(0); U(0); U(0);
    300     L(1); L(1); L(1); L(0); U(0); U(1); U(1); U(1);
    301     // CHECK-REC: WARNING: ThreadSanitizer: lock-order-inversion
    302   }
    303 
    304   void Test10() {
    305     if (test_number > 0 && test_number != 10) return;
    306     fprintf(stderr, "Starting Test10: 4 threads lock/unlock 4 private mutexes, one under another\n");
    307     // CHECK: Starting Test10
    308     Init(100);
    309     // CHECK-NOT: WARNING: ThreadSanitizer:
    310     RunThreads(&LockTest::Test10_Thread1, &LockTest::Test10_Thread2,
    311                &LockTest::Test10_Thread3, &LockTest::Test10_Thread4);
    312   }
    313   void Test10_Thread1() { Test10_Thread(0); }
    314   void Test10_Thread2() { Test10_Thread(10); }
    315   void Test10_Thread3() { Test10_Thread(20); }
    316   void Test10_Thread4() { Test10_Thread(30); }
    317   void Test10_Thread(size_t m) {
    318     for (int i = 0; i < iter_count; i++) {
    319       L(m + 0);
    320       L(m + 1);
    321       L(m + 2);
    322       L(m + 3);
    323       U(m + 3);
    324       U(m + 2);
    325       U(m + 1);
    326       U(m + 0);
    327     }
    328   }
    329 
    330   void Test11() {
    331     if (test_number > 0 && test_number != 11) return;
    332     fprintf(stderr, "Starting Test11: 4 threads lock/unlock 4 private mutexes, all under another private mutex\n");
    333     // CHECK: Starting Test11
    334     Init(500);
    335     // CHECK-NOT: WARNING: ThreadSanitizer:
    336     RunThreads(&LockTest::Test11_Thread1, &LockTest::Test11_Thread2,
    337                &LockTest::Test11_Thread3, &LockTest::Test11_Thread4);
    338   }
    339   void Test11_Thread1() { Test10_Thread(0); }
    340   void Test11_Thread2() { Test10_Thread(10); }
    341   void Test11_Thread3() { Test10_Thread(20); }
    342   void Test11_Thread4() { Test10_Thread(30); }
    343   void Test11_Thread(size_t m) {
    344     for (int i = 0; i < iter_count; i++) {
    345       L(m);
    346       L(m + 100);
    347       U(m + 100);
    348       L(m + 200);
    349       U(m + 200);
    350       L(m + 300);
    351       U(m + 300);
    352       L(m + 400);
    353       U(m + 500);
    354       U(m);
    355     }
    356   }
    357 
    358   void Test12() {
    359     if (test_number > 0 && test_number != 12) return;
    360     if (!LockType::supports_read_lock()) return;
    361     fprintf(stderr, "Starting Test12: 4 threads read lock/unlock 4 shared mutexes, one under another\n");
    362     // CHECK-RD: Starting Test12
    363     Init(500);
    364     // CHECK-RD-NOT: WARNING: ThreadSanitizer:
    365     RunThreads(&LockTest::Test12_Thread, &LockTest::Test12_Thread,
    366                &LockTest::Test12_Thread, &LockTest::Test12_Thread);
    367   }
    368   void Test12_Thread() {
    369     for (int i = 0; i < iter_count; i++) {
    370       RL(000);
    371       RL(100);
    372       RL(200);
    373       RL(300);
    374       RU(300);
    375       RU(200);
    376       RU(100);
    377       RU(000);
    378     }
    379   }
    380 
    381   void Test13() {
    382     if (test_number > 0 && test_number != 13) return;
    383     if (!LockType::supports_read_lock()) return;
    384     fprintf(stderr, "Starting Test13: 4 threads read lock/unlock 4 shared mutexes, all under another shared mutex\n");
    385     // CHECK-RD: Starting Test13
    386     Init(500);
    387     // CHECK-RD-NOT: WARNING: ThreadSanitizer:
    388     RunThreads(&LockTest::Test13_Thread, &LockTest::Test13_Thread,
    389                &LockTest::Test13_Thread, &LockTest::Test13_Thread);
    390   }
    391   void Test13_Thread() {
    392     for (int i = 0; i < iter_count; i++) {
    393       RL(0);
    394       RL(100);
    395       RU(100);
    396       RL(200);
    397       RU(200);
    398       RL(300);
    399       RU(300);
    400       RL(400);
    401       RU(400);
    402       RU(0);
    403     }
    404   }
    405 
    406   void Test14() {
    407     if (test_number > 0 && test_number != 14) return;
    408     fprintf(stderr, "Starting Test14: create lots of locks in 4 threads\n");
    409     Init(10);
    410     // CHECK-RD: Starting Test14
    411     RunThreads(&LockTest::CreateAndDestroyLocksLoop,
    412                &LockTest::CreateAndDestroyLocksLoop,
    413                &LockTest::CreateAndDestroyLocksLoop,
    414                &LockTest::CreateAndDestroyLocksLoop);
    415   }
    416 
    417   void Test15() {
    418     if (test_number > 0 && test_number != 15) return;
    419     if (!LockType::supports_read_lock()) return;
    420     fprintf(stderr, "Starting Test15: recursive rlock\n");
    421     // DISABLEDCHECK-RD: Starting Test15
    422     Init(5);
    423     RL(0); RL(0); RU(0); RU(0);  // Recusrive reader lock.
    424     RL(0); RL(0); RL(0); RU(0); RU(0); RU(0);  // Recusrive reader lock.
    425   }
    426 
    427   // More detailed output test.
    428   void Test16() {
    429     if (test_number > 0 && test_number != 16) return;
    430     fprintf(stderr, "Starting Test16: detailed output test with two locks\n");
    431     // CHECK: Starting Test16
    432     // CHECK: WARNING: ThreadSanitizer: lock-order-inversion
    433     // CHECK: acquired here while holding mutex
    434     // CHECK: LockTest::Acquire1
    435     // CHECK-NEXT: LockTest::Acquire_0_then_1
    436     // CHECK-SECOND: previously acquired by the same thread here
    437     // CHECK-SECOND: LockTest::Acquire0
    438     // CHECK-SECOND-NEXT: LockTest::Acquire_0_then_1
    439     // CHECK: acquired here while holding mutex
    440     // CHECK: LockTest::Acquire0
    441     // CHECK-NEXT: LockTest::Acquire_1_then_0
    442     // CHECK-SECOND: previously acquired by the same thread here
    443     // CHECK-SECOND: LockTest::Acquire1
    444     // CHECK-SECOND-NEXT: LockTest::Acquire_1_then_0
    445     Init(5);
    446     Acquire_0_then_1();
    447     U(0); U(1);
    448     Acquire_1_then_0();
    449     U(0); U(1);
    450   }
    451 
    452   // More detailed output test.
    453   void Test17() {
    454     if (test_number > 0 && test_number != 17) return;
    455     fprintf(stderr, "Starting Test17: detailed output test with three locks\n");
    456     // CHECK: Starting Test17
    457     // CHECK: WARNING: ThreadSanitizer: lock-order-inversion
    458     // CHECK: LockTest::Acquire1
    459     // CHECK-NEXT: LockTest::Acquire_0_then_1
    460     // CHECK: LockTest::Acquire2
    461     // CHECK-NEXT: LockTest::Acquire_1_then_2
    462     // CHECK: LockTest::Acquire0
    463     // CHECK-NEXT: LockTest::Acquire_2_then_0
    464     Init(5);
    465     Acquire_0_then_1();
    466     U(0); U(1);
    467     Acquire_1_then_2();
    468     U(1); U(2);
    469     Acquire_2_then_0();
    470     U(0); U(2);
    471   }
    472 
    473   __attribute__((noinline)) void Acquire2() { L(2); }
    474   __attribute__((noinline)) void Acquire1() { L(1); }
    475   __attribute__((noinline)) void Acquire0() { L(0); }
    476   __attribute__((noinline)) void Acquire_1_then_0() { Acquire1(); Acquire0(); }
    477   __attribute__((noinline)) void Acquire_0_then_1() { Acquire0(); Acquire1(); }
    478   __attribute__((noinline)) void Acquire_1_then_2() { Acquire1(); Acquire2(); }
    479   __attribute__((noinline)) void Acquire_2_then_0() { Acquire2(); Acquire0(); }
    480 
    481   // This test creates, locks, unlocks and destroys lots of mutexes.
    482   void Test18() {
    483     if (test_number > 0 && test_number != 18) return;
    484     fprintf(stderr, "Starting Test18: create, lock and destroy 4 locks; all in "
    485                     "4 threads in a loop\n");
    486     RunThreads(&LockTest::Test18_Thread, &LockTest::Test18_Thread,
    487                &LockTest::Test18_Thread, &LockTest::Test18_Thread);
    488   }
    489 
    490   void Test18_Thread() {
    491     LockType *l = new LockType[4];
    492     for (size_t i = 0; i < iter_count / 100; i++) {
    493       for (int i = 0; i < 4; i++) l[i].lock();
    494       for (int i = 0; i < 4; i++) l[i].unlock();
    495       for (int i = 0; i < 4; i++) l[i].~LockType();
    496       for (int i = 0; i < 4; i++) new ((void*)&l[i]) LockType();
    497     }
    498     delete [] l;
    499   }
    500 
    501  private:
    502   void Lock2(size_t l1, size_t l2) { L(l1); L(l2); U(l2); U(l1); }
    503 
    504   template<bool wait = false>
    505   void Lock_0_1() {
    506     Lock2(0, 1);
    507     if (wait)
    508       barrier_wait(&barrier);
    509   }
    510 
    511   template<bool wait = false>
    512   void Lock_1_0() {
    513     if (wait)
    514       barrier_wait(&barrier);
    515     Lock2(1, 0);
    516   }
    517 
    518   void Lock1_Loop(size_t i, size_t n_iter) {
    519     for (size_t it = 0; it < n_iter; it++) {
    520       // if ((it & (it - 1)) == 0) fprintf(stderr, "%zd", i);
    521       L(i);
    522       U(i);
    523     }
    524     // fprintf(stderr, "\n");
    525   }
    526   void Lock1_Loop_0() { Lock1_Loop(0, iter_count); }
    527   void Lock1_Loop_1() { Lock1_Loop(10, iter_count); }
    528   void Lock1_Loop_2() { Lock1_Loop(20, iter_count); }
    529 
    530   void CreateAndDestroyManyLocks() {
    531     LockType *create_many_locks_but_never_acquire =
    532         new LockType[kDeadlockGraphSize];
    533     (void)create_many_locks_but_never_acquire;
    534     delete [] create_many_locks_but_never_acquire;
    535   }
    536 
    537   void CreateAndDestroyLocksLoop() {
    538     for (size_t it = 0; it <= iter_count; it++) {
    539       LockType some_locks[10];
    540       (void)some_locks;
    541     }
    542   }
    543 
    544   void CreateLockUnlockAndDestroyManyLocks() {
    545     LockType many_locks[kDeadlockGraphSize];
    546     for (size_t i = 0; i < kDeadlockGraphSize; i++) {
    547       many_locks[i].lock();
    548       many_locks[i].unlock();
    549     }
    550   }
    551 
    552   // LockTest Member function callback.
    553   struct CB {
    554     void (LockTest::*f)();
    555     LockTest *lt;
    556   };
    557 
    558   // Thread function with CB.
    559   static void *Thread(void *param) {
    560     CB *cb = (CB*)param;
    561     (cb->lt->*cb->f)();
    562     return NULL;
    563   }
    564 
    565   void RunThreads(void (LockTest::*f1)(), void (LockTest::*f2)(),
    566                   void (LockTest::*f3)() = 0, void (LockTest::*f4)() = 0) {
    567     const int kNumThreads = 4;
    568     pthread_t t[kNumThreads];
    569     CB cb[kNumThreads] = {{f1, this}, {f2, this}, {f3, this}, {f4, this}};
    570     for (int i = 0; i < kNumThreads && cb[i].f; i++)
    571       pthread_create(&t[i], 0, Thread, &cb[i]);
    572     for (int i = 0; i < kNumThreads && cb[i].f; i++)
    573       pthread_join(t[i], 0);
    574   }
    575 
    576   static const size_t kDeadlockGraphSize = 4096;
    577   size_t n_;
    578   LockType **locks_;
    579 };
    580 
    581 int main(int argc, char **argv) {
    582   barrier_init(&barrier, 2);
    583   if (argc > 1)
    584     test_number = atoi(argv[1]);
    585   if (argc > 2)
    586     iter_count = atoi(argv[2]);
    587   LockTest().Test1();
    588   LockTest().Test2();
    589   LockTest().Test3();
    590   LockTest().Test4();
    591   LockTest().Test5();
    592   LockTest().Test6();
    593   LockTest().Test7();
    594   LockTest().Test8();
    595   LockTest().Test9();
    596   LockTest().Test10();
    597   LockTest().Test11();
    598   LockTest().Test12();
    599   LockTest().Test13();
    600   LockTest().Test14();
    601   LockTest().Test15();
    602   LockTest().Test16();
    603   LockTest().Test17();
    604   LockTest().Test18();
    605   fprintf(stderr, "ALL-DONE\n");
    606   // CHECK: ALL-DONE
    607 }
    608