blob: 99b8ee597cd13d775f1b1ff4ce0f73c5181fcce1 [file] [log] [blame]
Dmitry Vyukov512a18e2014-02-28 14:52:20 +00001//===-- dd_rtl.cc ---------------------------------------------------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "dd_rtl.h"
11#include "sanitizer_common/sanitizer_common.h"
Dmitry Vyukov54a03032014-03-04 11:39:56 +000012#include "sanitizer_common/sanitizer_placement_new.h"
Dmitry Vyukov512a18e2014-02-28 14:52:20 +000013#include "sanitizer_common/sanitizer_flags.h"
Evgeniy Stepanovf294d5b2015-01-15 15:13:43 +000014#include "sanitizer_common/sanitizer_flag_parser.h"
Dmitry Vyukov512a18e2014-02-28 14:52:20 +000015#include "sanitizer_common/sanitizer_stacktrace.h"
16#include "sanitizer_common/sanitizer_stackdepot.h"
17
18namespace __dsan {
19
Dmitry Vyukov54a03032014-03-04 11:39:56 +000020static Context *ctx;
Dmitry Vyukov512a18e2014-02-28 14:52:20 +000021
Dmitry Vyukov9b410fb2014-03-05 13:41:21 +000022static u32 CurrentStackTrace(Thread *thr, uptr skip) {
Alexey Samsonov3741ab82014-10-26 06:23:07 +000023 BufferedStackTrace stack;
Dmitry Vyukov54a03032014-03-04 11:39:56 +000024 thr->ignore_interceptors = true;
Alexey Samsonov3741ab82014-10-26 06:23:07 +000025 stack.Unwind(1000, 0, 0, 0, 0, 0, false);
Dmitry Vyukov54a03032014-03-04 11:39:56 +000026 thr->ignore_interceptors = false;
Alexey Samsonov3741ab82014-10-26 06:23:07 +000027 if (stack.size <= skip)
Dmitry Vyukov512a18e2014-02-28 14:52:20 +000028 return 0;
Alexey Samsonov3741ab82014-10-26 06:23:07 +000029 return StackDepotPut(StackTrace(stack.trace + skip, stack.size - skip));
Dmitry Vyukov512a18e2014-02-28 14:52:20 +000030}
31
32static void PrintStackTrace(Thread *thr, u32 stk) {
Alexey Samsonov6e7af812014-10-26 05:43:17 +000033 StackTrace stack = StackDepotGet(stk);
Dmitry Vyukov54a03032014-03-04 11:39:56 +000034 thr->ignore_interceptors = true;
Alexey Samsonov6e7af812014-10-26 05:43:17 +000035 stack.Print();
Dmitry Vyukov54a03032014-03-04 11:39:56 +000036 thr->ignore_interceptors = false;
Dmitry Vyukov512a18e2014-02-28 14:52:20 +000037}
38
39static void ReportDeadlock(Thread *thr, DDReport *rep) {
Dmitry Vyukov9b410fb2014-03-05 13:41:21 +000040 if (rep == 0)
41 return;
Dmitry Vyukov51f5b5f2014-04-11 17:54:27 +000042 BlockingMutexLock lock(&ctx->report_mutex);
Dmitry Vyukov512a18e2014-02-28 14:52:20 +000043 Printf("==============================\n");
Dmitry Vyukov9b410fb2014-03-05 13:41:21 +000044 Printf("WARNING: lock-order-inversion (potential deadlock)\n");
Dmitry Vyukov512a18e2014-02-28 14:52:20 +000045 for (int i = 0; i < rep->n; i++) {
Dmitry Vyukov69bd9ca2014-03-06 12:02:17 +000046 Printf("Thread %d locks mutex %llu while holding mutex %llu:\n",
Dmitry Vyukov9b410fb2014-03-05 13:41:21 +000047 rep->loop[i].thr_ctx, rep->loop[i].mtx_ctx1, rep->loop[i].mtx_ctx0);
Kostya Serebryanye7846202014-03-17 15:16:25 +000048 PrintStackTrace(thr, rep->loop[i].stk[1]);
Dmitry Vyukov3cd028c2014-03-18 13:13:47 +000049 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]);
53 }
Dmitry Vyukov512a18e2014-02-28 14:52:20 +000054 }
55 Printf("==============================\n");
56}
57
Dmitry Vyukov9b410fb2014-03-05 13:41:21 +000058Callback::Callback(Thread *thr)
59 : thr(thr) {
60 lt = thr->dd_lt;
61 pt = thr->dd_pt;
62}
63
64u32 Callback::Unwind() {
65 return CurrentStackTrace(thr, 3);
66}
67
Alexey Samsonov12258162015-02-12 00:36:42 +000068static void InitializeFlags() {
69 Flags *f = flags();
Dmitry Vyukov3cd028c2014-03-18 13:13:47 +000070
71 // Default values.
72 f->second_deadlock_stack = false;
73
Alexey Samsonov2f8c8d52014-12-19 21:40:04 +000074 SetCommonFlagsDefaults();
Alexey Samsonovc426c332015-01-02 21:28:37 +000075 {
76 // Override some common flags defaults.
77 CommonFlags cf;
78 cf.CopyFrom(*common_flags());
79 cf.allow_addr2line = true;
80 OverrideCommonFlags(cf);
81 }
Dmitry Vyukov3cd028c2014-03-18 13:13:47 +000082
83 // Override from command line.
Evgeniy Stepanovf294d5b2015-01-15 15:13:43 +000084 FlagParser parser;
85 RegisterFlag(&parser, "second_deadlock_stack", "", &f->second_deadlock_stack);
86 RegisterCommonFlags(&parser);
Alexey Samsonov12258162015-02-12 00:36:42 +000087 parser.ParseString(GetEnv("DSAN_OPTIONS"));
Evgeniy Stepanovf074b3c2015-01-20 13:21:20 +000088 SetVerbosity(common_flags()->verbosity);
Dmitry Vyukov3cd028c2014-03-18 13:13:47 +000089}
90
Dmitry Vyukov9b410fb2014-03-05 13:41:21 +000091void Initialize() {
92 static u64 ctx_mem[sizeof(Context) / sizeof(u64) + 1];
93 ctx = new(ctx_mem) Context();
94
95 InitializeInterceptors();
Alexey Samsonov12258162015-02-12 00:36:42 +000096 InitializeFlags();
Dmitry Vyukov3cd028c2014-03-18 13:13:47 +000097 ctx->dd = DDetector::Create(flags());
Dmitry Vyukov9b410fb2014-03-05 13:41:21 +000098}
99
100void 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);
105}
106
107void ThreadDestroy(Thread *thr) {
108 ctx->dd->DestroyPhysicalThread(thr->dd_pt);
109 ctx->dd->DestroyLogicalThread(thr->dd_lt);
110}
111
112void MutexBeforeLock(Thread *thr, uptr m, bool writelock) {
Dmitry Vyukov54a03032014-03-04 11:39:56 +0000113 if (thr->ignore_interceptors)
Dmitry Vyukov512a18e2014-02-28 14:52:20 +0000114 return;
Dmitry Vyukov9b410fb2014-03-05 13:41:21 +0000115 Callback cb(thr);
Dmitry Vyukov54a03032014-03-04 11:39:56 +0000116 {
117 MutexHashMap::Handle h(&ctx->mutex_map, m);
118 if (h.created())
Dmitry Vyukov9b410fb2014-03-05 13:41:21 +0000119 ctx->dd->MutexInit(&cb, &h->dd);
120 ctx->dd->MutexBeforeLock(&cb, &h->dd, writelock);
Dmitry Vyukov54a03032014-03-04 11:39:56 +0000121 }
Dmitry Vyukov9b410fb2014-03-05 13:41:21 +0000122 ReportDeadlock(thr, ctx->dd->GetReport(&cb));
Dmitry Vyukov512a18e2014-02-28 14:52:20 +0000123}
124
Dmitry Vyukov9b410fb2014-03-05 13:41:21 +0000125void MutexAfterLock(Thread *thr, uptr m, bool writelock, bool trylock) {
Dmitry Vyukov54a03032014-03-04 11:39:56 +0000126 if (thr->ignore_interceptors)
Dmitry Vyukov512a18e2014-02-28 14:52:20 +0000127 return;
Dmitry Vyukov9b410fb2014-03-05 13:41:21 +0000128 Callback cb(thr);
129 {
130 MutexHashMap::Handle h(&ctx->mutex_map, m);
131 if (h.created())
132 ctx->dd->MutexInit(&cb, &h->dd);
133 ctx->dd->MutexAfterLock(&cb, &h->dd, writelock, trylock);
134 }
135 ReportDeadlock(thr, ctx->dd->GetReport(&cb));
136}
137
138void MutexBeforeUnlock(Thread *thr, uptr m, bool writelock) {
139 if (thr->ignore_interceptors)
140 return;
141 Callback cb(thr);
142 {
143 MutexHashMap::Handle h(&ctx->mutex_map, m);
144 ctx->dd->MutexBeforeUnlock(&cb, &h->dd, writelock);
145 }
146 ReportDeadlock(thr, ctx->dd->GetReport(&cb));
Dmitry Vyukov512a18e2014-02-28 14:52:20 +0000147}
148
149void MutexDestroy(Thread *thr, uptr m) {
Dmitry Vyukov54a03032014-03-04 11:39:56 +0000150 if (thr->ignore_interceptors)
Dmitry Vyukov512a18e2014-02-28 14:52:20 +0000151 return;
Dmitry Vyukov9b410fb2014-03-05 13:41:21 +0000152 Callback cb(thr);
Dmitry Vyukov54a03032014-03-04 11:39:56 +0000153 MutexHashMap::Handle h(&ctx->mutex_map, m, true);
154 if (!h.exists())
Dmitry Vyukov512a18e2014-02-28 14:52:20 +0000155 return;
Dmitry Vyukov9b410fb2014-03-05 13:41:21 +0000156 ctx->dd->MutexDestroy(&cb, &h->dd);
Dmitry Vyukov512a18e2014-02-28 14:52:20 +0000157}
158
159} // namespace __dsan