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.
23static int test_number = -1;
24static int iter_count = 100000;
25
26class 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
56class PthreadRecursiveMutex : public PthreadMutex {
57 public:
58  PthreadRecursiveMutex() : PthreadMutex(true) { }
59  static bool supports_recursive_lock() { return true; }
60};
61
62class 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
83class 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
104class 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
571int 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