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_stacktrace.h"
15 #include "sanitizer_common/sanitizer_stackdepot.h"
21 static u32 CurrentStackTrace(Thread *thr, uptr skip) {
22 BufferedStackTrace stack;
23 thr->ignore_interceptors = true;
24 stack.Unwind(1000, 0, 0, 0, 0, 0, false);
25 thr->ignore_interceptors = false;
26 if (stack.size <= skip)
28 return StackDepotPut(StackTrace(stack.trace + skip, stack.size - skip));
31 static void PrintStackTrace(Thread *thr, u32 stk) {
32 StackTrace stack = StackDepotGet(stk);
33 thr->ignore_interceptors = true;
35 thr->ignore_interceptors = false;
38 static void ReportDeadlock(Thread *thr, DDReport *rep) {
41 BlockingMutexLock lock(&ctx->report_mutex);
42 Printf("==============================\n");
43 Printf("WARNING: lock-order-inversion (potential deadlock)\n");
44 for (int i = 0; i < rep->n; i++) {
45 Printf("Thread %d locks mutex %llu while holding mutex %llu:\n",
46 rep->loop[i].thr_ctx, rep->loop[i].mtx_ctx1, rep->loop[i].mtx_ctx0);
47 PrintStackTrace(thr, rep->loop[i].stk[1]);
48 if (rep->loop[i].stk[0]) {
49 Printf("Mutex %llu was acquired here:\n",
50 rep->loop[i].mtx_ctx0);
51 PrintStackTrace(thr, rep->loop[i].stk[0]);
54 Printf("==============================\n");
57 Callback::Callback(Thread *thr)
63 u32 Callback::Unwind() {
64 return CurrentStackTrace(thr, 3);
67 void InitializeFlags(Flags *f, const char *env) {
68 internal_memset(f, 0, sizeof(*f));
71 f->second_deadlock_stack = false;
73 CommonFlags *cf = common_flags();
74 SetCommonFlagsDefaults(cf);
75 // Override some common flags defaults.
76 cf->allow_addr2line = true;
78 // Override from command line.
79 ParseFlag(env, &f->second_deadlock_stack, "second_deadlock_stack", "");
80 ParseCommonFlagsFromString(cf, env);
84 static u64 ctx_mem[sizeof(Context) / sizeof(u64) + 1];
85 ctx = new(ctx_mem) Context();
87 InitializeInterceptors();
88 InitializeFlags(flags(), GetEnv("DSAN_OPTIONS"));
89 ctx->dd = DDetector::Create(flags());
92 void ThreadInit(Thread *thr) {
93 static atomic_uintptr_t id_gen;
94 uptr id = atomic_fetch_add(&id_gen, 1, memory_order_relaxed);
95 thr->dd_pt = ctx->dd->CreatePhysicalThread();
96 thr->dd_lt = ctx->dd->CreateLogicalThread(id);
99 void ThreadDestroy(Thread *thr) {
100 ctx->dd->DestroyPhysicalThread(thr->dd_pt);
101 ctx->dd->DestroyLogicalThread(thr->dd_lt);
104 void MutexBeforeLock(Thread *thr, uptr m, bool writelock) {
105 if (thr->ignore_interceptors)
109 MutexHashMap::Handle h(&ctx->mutex_map, m);
111 ctx->dd->MutexInit(&cb, &h->dd);
112 ctx->dd->MutexBeforeLock(&cb, &h->dd, writelock);
114 ReportDeadlock(thr, ctx->dd->GetReport(&cb));
117 void MutexAfterLock(Thread *thr, uptr m, bool writelock, bool trylock) {
118 if (thr->ignore_interceptors)
122 MutexHashMap::Handle h(&ctx->mutex_map, m);
124 ctx->dd->MutexInit(&cb, &h->dd);
125 ctx->dd->MutexAfterLock(&cb, &h->dd, writelock, trylock);
127 ReportDeadlock(thr, ctx->dd->GetReport(&cb));
130 void MutexBeforeUnlock(Thread *thr, uptr m, bool writelock) {
131 if (thr->ignore_interceptors)
135 MutexHashMap::Handle h(&ctx->mutex_map, m);
136 ctx->dd->MutexBeforeUnlock(&cb, &h->dd, writelock);
138 ReportDeadlock(thr, ctx->dd->GetReport(&cb));
141 void MutexDestroy(Thread *thr, uptr m) {
142 if (thr->ignore_interceptors)
145 MutexHashMap::Handle h(&ctx->mutex_map, m, true);
148 ctx->dd->MutexDestroy(&cb, &h->dd);
151 } // namespace __dsan