dd_rtl.cpp 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. //===-- dd_rtl.cpp --------------------------------------------------------===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. #include "dd_rtl.h"
  9. #include "sanitizer_common/sanitizer_common.h"
  10. #include "sanitizer_common/sanitizer_placement_new.h"
  11. #include "sanitizer_common/sanitizer_flags.h"
  12. #include "sanitizer_common/sanitizer_flag_parser.h"
  13. #include "sanitizer_common/sanitizer_stacktrace.h"
  14. #include "sanitizer_common/sanitizer_stackdepot.h"
  15. namespace __dsan {
  16. static Context *ctx;
  17. static u32 CurrentStackTrace(Thread *thr, uptr skip) {
  18. BufferedStackTrace stack;
  19. thr->ignore_interceptors = true;
  20. stack.Unwind(1000, 0, 0, 0, 0, 0, false);
  21. thr->ignore_interceptors = false;
  22. if (stack.size <= skip)
  23. return 0;
  24. return StackDepotPut(StackTrace(stack.trace + skip, stack.size - skip));
  25. }
  26. static void PrintStackTrace(Thread *thr, u32 stk) {
  27. StackTrace stack = StackDepotGet(stk);
  28. thr->ignore_interceptors = true;
  29. stack.Print();
  30. thr->ignore_interceptors = false;
  31. }
  32. static void ReportDeadlock(Thread *thr, DDReport *rep) {
  33. if (rep == 0)
  34. return;
  35. Lock lock(&ctx->report_mutex);
  36. Printf("==============================\n");
  37. Printf("WARNING: lock-order-inversion (potential deadlock)\n");
  38. for (int i = 0; i < rep->n; i++) {
  39. Printf("Thread %lld locks mutex %llu while holding mutex %llu:\n",
  40. rep->loop[i].thr_ctx, rep->loop[i].mtx_ctx1, rep->loop[i].mtx_ctx0);
  41. PrintStackTrace(thr, rep->loop[i].stk[1]);
  42. if (rep->loop[i].stk[0]) {
  43. Printf("Mutex %llu was acquired here:\n",
  44. rep->loop[i].mtx_ctx0);
  45. PrintStackTrace(thr, rep->loop[i].stk[0]);
  46. }
  47. }
  48. Printf("==============================\n");
  49. }
  50. Callback::Callback(Thread *thr)
  51. : thr(thr) {
  52. lt = thr->dd_lt;
  53. pt = thr->dd_pt;
  54. }
  55. u32 Callback::Unwind() {
  56. return CurrentStackTrace(thr, 3);
  57. }
  58. static void InitializeFlags() {
  59. Flags *f = flags();
  60. // Default values.
  61. f->second_deadlock_stack = false;
  62. SetCommonFlagsDefaults();
  63. {
  64. // Override some common flags defaults.
  65. CommonFlags cf;
  66. cf.CopyFrom(*common_flags());
  67. cf.allow_addr2line = true;
  68. OverrideCommonFlags(cf);
  69. }
  70. // Override from command line.
  71. FlagParser parser;
  72. RegisterFlag(&parser, "second_deadlock_stack", "", &f->second_deadlock_stack);
  73. RegisterCommonFlags(&parser);
  74. parser.ParseStringFromEnv("DSAN_OPTIONS");
  75. SetVerbosity(common_flags()->verbosity);
  76. }
  77. void Initialize() {
  78. static u64 ctx_mem[sizeof(Context) / sizeof(u64) + 1];
  79. ctx = new(ctx_mem) Context();
  80. InitializeInterceptors();
  81. InitializeFlags();
  82. ctx->dd = DDetector::Create(flags());
  83. }
  84. void ThreadInit(Thread *thr) {
  85. static atomic_uintptr_t id_gen;
  86. uptr id = atomic_fetch_add(&id_gen, 1, memory_order_relaxed);
  87. thr->dd_pt = ctx->dd->CreatePhysicalThread();
  88. thr->dd_lt = ctx->dd->CreateLogicalThread(id);
  89. }
  90. void ThreadDestroy(Thread *thr) {
  91. ctx->dd->DestroyPhysicalThread(thr->dd_pt);
  92. ctx->dd->DestroyLogicalThread(thr->dd_lt);
  93. }
  94. void MutexBeforeLock(Thread *thr, uptr m, bool writelock) {
  95. if (thr->ignore_interceptors)
  96. return;
  97. Callback cb(thr);
  98. {
  99. MutexHashMap::Handle h(&ctx->mutex_map, m);
  100. if (h.created())
  101. ctx->dd->MutexInit(&cb, &h->dd);
  102. ctx->dd->MutexBeforeLock(&cb, &h->dd, writelock);
  103. }
  104. ReportDeadlock(thr, ctx->dd->GetReport(&cb));
  105. }
  106. void MutexAfterLock(Thread *thr, uptr m, bool writelock, bool trylock) {
  107. if (thr->ignore_interceptors)
  108. return;
  109. Callback cb(thr);
  110. {
  111. MutexHashMap::Handle h(&ctx->mutex_map, m);
  112. if (h.created())
  113. ctx->dd->MutexInit(&cb, &h->dd);
  114. ctx->dd->MutexAfterLock(&cb, &h->dd, writelock, trylock);
  115. }
  116. ReportDeadlock(thr, ctx->dd->GetReport(&cb));
  117. }
  118. void MutexBeforeUnlock(Thread *thr, uptr m, bool writelock) {
  119. if (thr->ignore_interceptors)
  120. return;
  121. Callback cb(thr);
  122. {
  123. MutexHashMap::Handle h(&ctx->mutex_map, m);
  124. ctx->dd->MutexBeforeUnlock(&cb, &h->dd, writelock);
  125. }
  126. ReportDeadlock(thr, ctx->dd->GetReport(&cb));
  127. }
  128. void MutexDestroy(Thread *thr, uptr m) {
  129. if (thr->ignore_interceptors)
  130. return;
  131. Callback cb(thr);
  132. MutexHashMap::Handle h(&ctx->mutex_map, m, true);
  133. if (!h.exists())
  134. return;
  135. ctx->dd->MutexDestroy(&cb, &h->dd);
  136. }
  137. } // namespace __dsan