sanitizer_deadlock_detector1.cc 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. //===-- sanitizer_deadlock_detector1.cc -----------------------------------===//
  2. //
  3. // This file is distributed under the University of Illinois Open Source
  4. // License. See LICENSE.TXT for details.
  5. //
  6. //===----------------------------------------------------------------------===//
  7. //
  8. // Deadlock detector implementation based on NxN adjacency bit matrix.
  9. //
  10. //===----------------------------------------------------------------------===//
  11. #include "sanitizer_deadlock_detector_interface.h"
  12. #include "sanitizer_deadlock_detector.h"
  13. #include "sanitizer_allocator_internal.h"
  14. #include "sanitizer_placement_new.h"
  15. #include "sanitizer_mutex.h"
  16. #if SANITIZER_DEADLOCK_DETECTOR_VERSION == 1
  17. namespace __sanitizer {
  18. typedef TwoLevelBitVector<> DDBV; // DeadlockDetector's bit vector.
  19. struct DDPhysicalThread {
  20. };
  21. struct DDLogicalThread {
  22. u64 ctx;
  23. DeadlockDetectorTLS<DDBV> dd;
  24. DDReport rep;
  25. bool report_pending;
  26. };
  27. struct DD : public DDetector {
  28. SpinMutex mtx;
  29. DeadlockDetector<DDBV> dd;
  30. DDFlags flags;
  31. explicit DD(const DDFlags *flags);
  32. DDPhysicalThread* CreatePhysicalThread();
  33. void DestroyPhysicalThread(DDPhysicalThread *pt);
  34. DDLogicalThread* CreateLogicalThread(u64 ctx);
  35. void DestroyLogicalThread(DDLogicalThread *lt);
  36. void MutexInit(DDCallback *cb, DDMutex *m);
  37. void MutexBeforeLock(DDCallback *cb, DDMutex *m, bool wlock);
  38. void MutexAfterLock(DDCallback *cb, DDMutex *m, bool wlock, bool trylock);
  39. void MutexBeforeUnlock(DDCallback *cb, DDMutex *m, bool wlock);
  40. void MutexDestroy(DDCallback *cb, DDMutex *m);
  41. DDReport *GetReport(DDCallback *cb);
  42. void MutexEnsureID(DDLogicalThread *lt, DDMutex *m);
  43. void ReportDeadlock(DDCallback *cb, DDMutex *m);
  44. };
  45. DDetector *DDetector::Create(const DDFlags *flags) {
  46. (void)flags;
  47. void *mem = MmapOrDie(sizeof(DD), "deadlock detector");
  48. return new(mem) DD(flags);
  49. }
  50. DD::DD(const DDFlags *flags)
  51. : flags(*flags) {
  52. dd.clear();
  53. }
  54. DDPhysicalThread* DD::CreatePhysicalThread() {
  55. return 0;
  56. }
  57. void DD::DestroyPhysicalThread(DDPhysicalThread *pt) {
  58. }
  59. DDLogicalThread* DD::CreateLogicalThread(u64 ctx) {
  60. DDLogicalThread *lt = (DDLogicalThread*)InternalAlloc(sizeof(*lt));
  61. lt->ctx = ctx;
  62. lt->dd.clear();
  63. lt->report_pending = false;
  64. return lt;
  65. }
  66. void DD::DestroyLogicalThread(DDLogicalThread *lt) {
  67. lt->~DDLogicalThread();
  68. InternalFree(lt);
  69. }
  70. void DD::MutexInit(DDCallback *cb, DDMutex *m) {
  71. m->id = 0;
  72. m->stk = cb->Unwind();
  73. }
  74. void DD::MutexEnsureID(DDLogicalThread *lt, DDMutex *m) {
  75. if (!dd.nodeBelongsToCurrentEpoch(m->id))
  76. m->id = dd.newNode(reinterpret_cast<uptr>(m));
  77. dd.ensureCurrentEpoch(&lt->dd);
  78. }
  79. void DD::MutexBeforeLock(DDCallback *cb,
  80. DDMutex *m, bool wlock) {
  81. DDLogicalThread *lt = cb->lt;
  82. if (lt->dd.empty()) return; // This will be the first lock held by lt.
  83. if (dd.hasAllEdges(&lt->dd, m->id)) return; // We already have all edges.
  84. SpinMutexLock lk(&mtx);
  85. MutexEnsureID(lt, m);
  86. if (dd.isHeld(&lt->dd, m->id))
  87. return; // FIXME: allow this only for recursive locks.
  88. if (dd.onLockBefore(&lt->dd, m->id)) {
  89. // Actually add this edge now so that we have all the stack traces.
  90. dd.addEdges(&lt->dd, m->id, cb->Unwind(), cb->UniqueTid());
  91. ReportDeadlock(cb, m);
  92. }
  93. }
  94. void DD::ReportDeadlock(DDCallback *cb, DDMutex *m) {
  95. DDLogicalThread *lt = cb->lt;
  96. uptr path[10];
  97. uptr len = dd.findPathToLock(&lt->dd, m->id, path, ARRAY_SIZE(path));
  98. CHECK_GT(len, 0U); // Hm.. cycle of 10 locks? I'd like to see that.
  99. CHECK_EQ(m->id, path[0]);
  100. lt->report_pending = true;
  101. DDReport *rep = &lt->rep;
  102. rep->n = len;
  103. for (uptr i = 0; i < len; i++) {
  104. uptr from = path[i];
  105. uptr to = path[(i + 1) % len];
  106. DDMutex *m0 = (DDMutex*)dd.getData(from);
  107. DDMutex *m1 = (DDMutex*)dd.getData(to);
  108. u32 stk_from = -1U, stk_to = -1U;
  109. int unique_tid = 0;
  110. dd.findEdge(from, to, &stk_from, &stk_to, &unique_tid);
  111. // Printf("Edge: %zd=>%zd: %u/%u T%d\n", from, to, stk_from, stk_to,
  112. // unique_tid);
  113. rep->loop[i].thr_ctx = unique_tid;
  114. rep->loop[i].mtx_ctx0 = m0->ctx;
  115. rep->loop[i].mtx_ctx1 = m1->ctx;
  116. rep->loop[i].stk[0] = stk_to;
  117. rep->loop[i].stk[1] = stk_from;
  118. }
  119. }
  120. void DD::MutexAfterLock(DDCallback *cb, DDMutex *m, bool wlock, bool trylock) {
  121. DDLogicalThread *lt = cb->lt;
  122. u32 stk = 0;
  123. if (flags.second_deadlock_stack)
  124. stk = cb->Unwind();
  125. // Printf("T%p MutexLock: %zx stk %u\n", lt, m->id, stk);
  126. if (dd.onFirstLock(&lt->dd, m->id, stk))
  127. return;
  128. if (dd.onLockFast(&lt->dd, m->id, stk))
  129. return;
  130. SpinMutexLock lk(&mtx);
  131. MutexEnsureID(lt, m);
  132. if (wlock) // Only a recursive rlock may be held.
  133. CHECK(!dd.isHeld(&lt->dd, m->id));
  134. if (!trylock)
  135. dd.addEdges(&lt->dd, m->id, stk ? stk : cb->Unwind(), cb->UniqueTid());
  136. dd.onLockAfter(&lt->dd, m->id, stk);
  137. }
  138. void DD::MutexBeforeUnlock(DDCallback *cb, DDMutex *m, bool wlock) {
  139. // Printf("T%p MutexUnLock: %zx\n", cb->lt, m->id);
  140. dd.onUnlock(&cb->lt->dd, m->id);
  141. }
  142. void DD::MutexDestroy(DDCallback *cb,
  143. DDMutex *m) {
  144. if (!m->id) return;
  145. SpinMutexLock lk(&mtx);
  146. if (dd.nodeBelongsToCurrentEpoch(m->id))
  147. dd.removeNode(m->id);
  148. m->id = 0;
  149. }
  150. DDReport *DD::GetReport(DDCallback *cb) {
  151. if (!cb->lt->report_pending)
  152. return 0;
  153. cb->lt->report_pending = false;
  154. return &cb->lt->rep;
  155. }
  156. } // namespace __sanitizer
  157. #endif // #if SANITIZER_DEADLOCK_DETECTOR_VERSION == 1