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