blob: c77ffe555ce5c88270ffa3403b69fb15c7422bb8 [file] [log] [blame]
Stephen Hines2d1fdb22014-05-28 23:58:16 -07001// RUN: %clangxx_tsan %s -o %t -DLockType=PthreadMutex
Stephen Hines6a211c52014-07-21 00:49:56 -07002// RUN: TSAN_OPTIONS=detect_deadlocks=1 %deflake %run %t | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-NOT-SECOND
Pirama Arumuga Nainar259f7062015-05-06 11:49:53 -07003// RUN: TSAN_OPTIONS="detect_deadlocks=1 second_deadlock_stack=1" %deflake %run %t | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-SECOND
Stephen Hines2d1fdb22014-05-28 23:58:16 -07004// RUN: %clangxx_tsan %s -o %t -DLockType=PthreadSpinLock
Stephen Hines6a211c52014-07-21 00:49:56 -07005// RUN: TSAN_OPTIONS=detect_deadlocks=1 %deflake %run %t | FileCheck %s
Stephen Hines2d1fdb22014-05-28 23:58:16 -07006// RUN: %clangxx_tsan %s -o %t -DLockType=PthreadRWLock
Stephen Hines6a211c52014-07-21 00:49:56 -07007// RUN: TSAN_OPTIONS=detect_deadlocks=1 %deflake %run %t | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-RD
Stephen Hines2d1fdb22014-05-28 23:58:16 -07008// RUN: %clangxx_tsan %s -o %t -DLockType=PthreadRecursiveMutex
Stephen Hines6a211c52014-07-21 00:49:56 -07009// RUN: TSAN_OPTIONS=detect_deadlocks=1 %deflake %run %t | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-REC
Stephen Hines86277eb2015-03-23 12:06:32 -070010#include "test.h"
Stephen Hines2d1fdb22014-05-28 23:58:16 -070011#undef NDEBUG
12#include <assert.h>
Stephen Hines2d1fdb22014-05-28 23:58:16 -070013#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.
20static int test_number = -1;
21static int iter_count = 100000;
22
23class 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
53class PthreadRecursiveMutex : public PthreadMutex {
54 public:
55 PthreadRecursiveMutex() : PthreadMutex(true) { }
56 static bool supports_recursive_lock() { return true; }
57};
58
59class 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
80class 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
101class 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);
Stephen Hines86277eb2015-03-23 12:06:32 -0700224 RunThreads(&LockTest::Lock_0_1<true>, &LockTest::Lock_1_0<true>);
Stephen Hines2d1fdb22014-05-28 23:58:16 -0700225 // 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); }
Stephen Hines86277eb2015-03-23 12:06:32 -0700503
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
Stephen Hines2d1fdb22014-05-28 23:58:16 -0700518 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
581int main(int argc, char **argv) {
Stephen Hines86277eb2015-03-23 12:06:32 -0700582 barrier_init(&barrier, 2);
Stephen Hines2d1fdb22014-05-28 23:58:16 -0700583 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}