1 //===-- dd_rtl.cc ---------------------------------------------------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
11 #include "sanitizer_common/sanitizer_common.h"
12 #include "sanitizer_common/sanitizer_placement_new.h"
13 #include "sanitizer_common/sanitizer_flags.h"
14 #include "sanitizer_common/sanitizer_flag_parser.h"
15 #include "sanitizer_common/sanitizer_stacktrace.h"
16 #include "sanitizer_common/sanitizer_stackdepot.h"
22 static u32 CurrentStackTrace(Thread *thr, uptr skip) {
23 BufferedStackTrace stack;
24 thr->ignore_interceptors = true;
25 stack.Unwind(1000, 0, 0, 0, 0, 0, false);
26 thr->ignore_interceptors = false;
27 if (stack.size <= skip)
29 return StackDepotPut(StackTrace(stack.trace + skip, stack.size - skip));
32 static void PrintStackTrace(Thread *thr, u32 stk) {
33 StackTrace stack = StackDepotGet(stk);
34 thr->ignore_interceptors = true;
36 thr->ignore_interceptors = false;
39 static void ReportDeadlock(Thread *thr, DDReport *rep) {
42 BlockingMutexLock lock(&ctx->report_mutex);
43 Printf("==============================\n");
44 Printf("WARNING: lock-order-inversion (potential deadlock)\n");
45 for (int i = 0; i < rep->n; i++) {
46 Printf("Thread %d locks mutex %llu while holding mutex %llu:\n",
47 rep->loop[i].thr_ctx, rep->loop[i].mtx_ctx1, rep->loop[i].mtx_ctx0);
48 PrintStackTrace(thr, rep->loop[i].stk[1]);
49 if (rep->loop[i].stk[0]) {
50 Printf("Mutex %llu was acquired here:\n",
51 rep->loop[i].mtx_ctx0);
52 PrintStackTrace(thr, rep->loop[i].stk[0]);
55 Printf("==============================\n");
58 Callback::Callback(Thread *thr)
64 u32 Callback::Unwind() {
65 return CurrentStackTrace(thr, 3);
68 static void InitializeFlags() {
72 f->second_deadlock_stack = false;
74 SetCommonFlagsDefaults();
76 // Override some common flags defaults.
78 cf.CopyFrom(*common_flags());
79 cf.allow_addr2line = true;
80 OverrideCommonFlags(cf);
83 // Override from command line.
85 RegisterFlag(&parser, "second_deadlock_stack", "", &f->second_deadlock_stack);
86 RegisterCommonFlags(&parser);
87 parser.ParseString(GetEnv("DSAN_OPTIONS"));
88 SetVerbosity(common_flags()->verbosity);
92 static u64 ctx_mem[sizeof(Context) / sizeof(u64) + 1];
93 ctx = new(ctx_mem) Context();
95 InitializeInterceptors();
97 ctx->dd = DDetector::Create(flags());
100 void ThreadInit(Thread *thr) {
101 static atomic_uintptr_t id_gen;
102 uptr id = atomic_fetch_add(&id_gen, 1, memory_order_relaxed);
103 thr->dd_pt = ctx->dd->CreatePhysicalThread();
104 thr->dd_lt = ctx->dd->CreateLogicalThread(id);
107 void ThreadDestroy(Thread *thr) {
108 ctx->dd->DestroyPhysicalThread(thr->dd_pt);
109 ctx->dd->DestroyLogicalThread(thr->dd_lt);
112 void MutexBeforeLock(Thread *thr, uptr m, bool writelock) {
113 if (thr->ignore_interceptors)
117 MutexHashMap::Handle h(&ctx->mutex_map, m);
119 ctx->dd->MutexInit(&cb, &h->dd);
120 ctx->dd->MutexBeforeLock(&cb, &h->dd, writelock);
122 ReportDeadlock(thr, ctx->dd->GetReport(&cb));
125 void MutexAfterLock(Thread *thr, uptr m, bool writelock, bool trylock) {
126 if (thr->ignore_interceptors)
130 MutexHashMap::Handle h(&ctx->mutex_map, m);
132 ctx->dd->MutexInit(&cb, &h->dd);
133 ctx->dd->MutexAfterLock(&cb, &h->dd, writelock, trylock);
135 ReportDeadlock(thr, ctx->dd->GetReport(&cb));
138 void MutexBeforeUnlock(Thread *thr, uptr m, bool writelock) {
139 if (thr->ignore_interceptors)
143 MutexHashMap::Handle h(&ctx->mutex_map, m);
144 ctx->dd->MutexBeforeUnlock(&cb, &h->dd, writelock);
146 ReportDeadlock(thr, ctx->dd->GetReport(&cb));
149 void MutexDestroy(Thread *thr, uptr m) {
150 if (thr->ignore_interceptors)
153 MutexHashMap::Handle h(&ctx->mutex_map, m, true);
156 ctx->dd->MutexDestroy(&cb, &h->dd);
159 } // namespace __dsan