Index: compiler-rt/trunk/lib/sanitizer_common/sanitizer_deadlock_detector1.cc =================================================================== --- compiler-rt/trunk/lib/sanitizer_common/sanitizer_deadlock_detector1.cc +++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_deadlock_detector1.cc @@ -119,11 +119,16 @@ void DD::ReportDeadlock(DDCallback *cb, DDMutex *m) { DDLogicalThread *lt = cb->lt; - uptr path[10]; + uptr path[20]; uptr len = dd.findPathToLock(<->dd, m->id, path, ARRAY_SIZE(path)); - CHECK_GT(len, 0U); // Hm.. cycle of 10 locks? I'd like to see that. + if (len == 0U) { + // A cycle of 20+ locks? Well, that's a bit odd... + Printf("WARNING: too long mutex cycle found\n"); + return; + } CHECK_EQ(m->id, path[0]); lt->report_pending = true; + len = Min(len, DDReport::kMaxLoopSize); DDReport *rep = <->rep; rep->n = len; for (uptr i = 0; i < len; i++) { Index: compiler-rt/trunk/lib/sanitizer_common/sanitizer_deadlock_detector_interface.h =================================================================== --- compiler-rt/trunk/lib/sanitizer_common/sanitizer_deadlock_detector_interface.h +++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_deadlock_detector_interface.h @@ -51,7 +51,7 @@ }; struct DDReport { - enum { kMaxLoopSize = 8 }; + enum { kMaxLoopSize = 20 }; int n; // number of entries in loop struct { u64 thr_ctx; // user thread context Index: compiler-rt/trunk/test/tsan/mutex_cycle_long.c =================================================================== --- compiler-rt/trunk/test/tsan/mutex_cycle_long.c +++ compiler-rt/trunk/test/tsan/mutex_cycle_long.c @@ -0,0 +1,42 @@ +// RUN: %clangxx_tsan %s -o %t +// RUN: not %run %t 5 2>&1 | FileCheck %s +// RUN: not %run %t 10 2>&1 | FileCheck %s +// RUN: not %run %t 15 2>&1 | FileCheck %s +// RUN: not %run %t 20 2>&1 | FileCheck %s +// RUN: %run %t 30 2>&1 | FileCheck %s --check-prefix=CHECK-TOO-LONG-CYCLE + +#include +#include +#include + +int main(int argc, char *argv[]) { + int num_mutexes = 5; + if (argc > 1) num_mutexes = atoi(argv[1]); + + pthread_mutex_t m[num_mutexes]; + for (int i = 0; i < num_mutexes; ++i) + pthread_mutex_init(&m[i], NULL); + + for (int i = 0; i < num_mutexes - 1; ++i) { + pthread_mutex_lock(&m[i]); + pthread_mutex_lock(&m[i + 1]); + + pthread_mutex_unlock(&m[i]); + pthread_mutex_unlock(&m[i + 1]); + } + + pthread_mutex_lock(&m[num_mutexes - 1]); + pthread_mutex_lock(&m[0]); + + pthread_mutex_unlock(&m[num_mutexes - 1]); + pthread_mutex_unlock(&m[0]); + + for (int i = 0; i < num_mutexes; ++i) + pthread_mutex_destroy(&m[i]); + + fprintf(stderr, "PASS\n"); +} + +// CHECK: ThreadSanitizer: lock-order-inversion (potential deadlock) +// CHECK-TOO-LONG-CYCLE: WARNING: too long mutex cycle found +// CHECK: PASS