blob: 38716d5c3f1102f69b0c80a60161dcaa3cfe3594 [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"
14#include "sanitizer_common/sanitizer_stacktrace.h"
15#include "sanitizer_common/sanitizer_stackdepot.h"
16
17namespace __dsan {
18
Dmitry Vyukov54a03032014-03-04 11:39:56 +000019static Context *ctx;
Dmitry Vyukov512a18e2014-02-28 14:52:20 +000020
Dmitry Vyukov9b410fb2014-03-05 13:41:21 +000021static u32 CurrentStackTrace(Thread *thr, uptr skip) {
Dmitry Vyukov512a18e2014-02-28 14:52:20 +000022 StackTrace trace;
Dmitry Vyukov54a03032014-03-04 11:39:56 +000023 thr->ignore_interceptors = true;
Dmitry Vyukov512a18e2014-02-28 14:52:20 +000024 trace.Unwind(1000, 0, 0, 0, 0, 0, false);
Dmitry Vyukov54a03032014-03-04 11:39:56 +000025 thr->ignore_interceptors = false;
Dmitry Vyukov512a18e2014-02-28 14:52:20 +000026 if (trace.size <= skip)
27 return 0;
28 return StackDepotPut(trace.trace + skip, trace.size - skip);
29}
30
31static void PrintStackTrace(Thread *thr, u32 stk) {
32 uptr size = 0;
33 const uptr *trace = StackDepotGet(stk, &size);
Dmitry Vyukov54a03032014-03-04 11:39:56 +000034 thr->ignore_interceptors = true;
Dmitry Vyukov512a18e2014-02-28 14:52:20 +000035 StackTrace::PrintStack(trace, size);
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 Vyukov512a18e2014-02-28 14:52:20 +000042 Printf("==============================\n");
Dmitry Vyukov9b410fb2014-03-05 13:41:21 +000043 Printf("WARNING: lock-order-inversion (potential deadlock)\n");
Dmitry Vyukov512a18e2014-02-28 14:52:20 +000044 for (int i = 0; i < rep->n; i++) {
Dmitry Vyukov69bd9ca2014-03-06 12:02:17 +000045 Printf("Thread %d locks mutex %llu while holding mutex %llu:\n",
Dmitry Vyukov9b410fb2014-03-05 13:41:21 +000046 rep->loop[i].thr_ctx, rep->loop[i].mtx_ctx1, rep->loop[i].mtx_ctx0);
Kostya Serebryanye7846202014-03-17 15:16:25 +000047 PrintStackTrace(thr, rep->loop[i].stk[1]);
Dmitry Vyukovb72bc2e2014-03-18 12:53:05 +000048 Printf("Mutex %llu was acquired here:\n",
49 rep->loop[i].mtx_ctx0);
50 PrintStackTrace(thr, rep->loop[i].stk[0]);
Dmitry Vyukov512a18e2014-02-28 14:52:20 +000051 }
52 Printf("==============================\n");
Dmitry Vyukovb72bc2e2014-03-18 12:53:05 +000053 Die();
Dmitry Vyukov512a18e2014-02-28 14:52:20 +000054}
55
Dmitry Vyukov9b410fb2014-03-05 13:41:21 +000056Callback::Callback(Thread *thr)
57 : thr(thr) {
58 lt = thr->dd_lt;
59 pt = thr->dd_pt;
60}
61
62u32 Callback::Unwind() {
63 return CurrentStackTrace(thr, 3);
64}
65
66void Initialize() {
67 static u64 ctx_mem[sizeof(Context) / sizeof(u64) + 1];
68 ctx = new(ctx_mem) Context();
69
70 InitializeInterceptors();
71 ParseCommonFlagsFromString(flags(), GetEnv("DSAN_OPTIONS"));
72 //common_flags()->allow_addr2line = true;
73 common_flags()->symbolize = true;
74 ctx->dd = DDetector::Create();
75}
76
77void ThreadInit(Thread *thr) {
78 static atomic_uintptr_t id_gen;
79 uptr id = atomic_fetch_add(&id_gen, 1, memory_order_relaxed);
80 thr->dd_pt = ctx->dd->CreatePhysicalThread();
81 thr->dd_lt = ctx->dd->CreateLogicalThread(id);
82}
83
84void ThreadDestroy(Thread *thr) {
85 ctx->dd->DestroyPhysicalThread(thr->dd_pt);
86 ctx->dd->DestroyLogicalThread(thr->dd_lt);
87}
88
89void MutexBeforeLock(Thread *thr, uptr m, bool writelock) {
Dmitry Vyukov54a03032014-03-04 11:39:56 +000090 if (thr->ignore_interceptors)
Dmitry Vyukov512a18e2014-02-28 14:52:20 +000091 return;
Dmitry Vyukov9b410fb2014-03-05 13:41:21 +000092 Callback cb(thr);
Dmitry Vyukov54a03032014-03-04 11:39:56 +000093 {
94 MutexHashMap::Handle h(&ctx->mutex_map, m);
95 if (h.created())
Dmitry Vyukov9b410fb2014-03-05 13:41:21 +000096 ctx->dd->MutexInit(&cb, &h->dd);
97 ctx->dd->MutexBeforeLock(&cb, &h->dd, writelock);
Dmitry Vyukov54a03032014-03-04 11:39:56 +000098 }
Dmitry Vyukov9b410fb2014-03-05 13:41:21 +000099 ReportDeadlock(thr, ctx->dd->GetReport(&cb));
Dmitry Vyukov512a18e2014-02-28 14:52:20 +0000100}
101
Dmitry Vyukov9b410fb2014-03-05 13:41:21 +0000102void MutexAfterLock(Thread *thr, uptr m, bool writelock, bool trylock) {
Dmitry Vyukov54a03032014-03-04 11:39:56 +0000103 if (thr->ignore_interceptors)
Dmitry Vyukov512a18e2014-02-28 14:52:20 +0000104 return;
Dmitry Vyukov9b410fb2014-03-05 13:41:21 +0000105 Callback cb(thr);
106 {
107 MutexHashMap::Handle h(&ctx->mutex_map, m);
108 if (h.created())
109 ctx->dd->MutexInit(&cb, &h->dd);
110 ctx->dd->MutexAfterLock(&cb, &h->dd, writelock, trylock);
111 }
112 ReportDeadlock(thr, ctx->dd->GetReport(&cb));
113}
114
115void MutexBeforeUnlock(Thread *thr, uptr m, bool writelock) {
116 if (thr->ignore_interceptors)
117 return;
118 Callback cb(thr);
119 {
120 MutexHashMap::Handle h(&ctx->mutex_map, m);
121 ctx->dd->MutexBeforeUnlock(&cb, &h->dd, writelock);
122 }
123 ReportDeadlock(thr, ctx->dd->GetReport(&cb));
Dmitry Vyukov512a18e2014-02-28 14:52:20 +0000124}
125
126void MutexDestroy(Thread *thr, uptr m) {
Dmitry Vyukov54a03032014-03-04 11:39:56 +0000127 if (thr->ignore_interceptors)
Dmitry Vyukov512a18e2014-02-28 14:52:20 +0000128 return;
Dmitry Vyukov9b410fb2014-03-05 13:41:21 +0000129 Callback cb(thr);
Dmitry Vyukov54a03032014-03-04 11:39:56 +0000130 MutexHashMap::Handle h(&ctx->mutex_map, m, true);
131 if (!h.exists())
Dmitry Vyukov512a18e2014-02-28 14:52:20 +0000132 return;
Dmitry Vyukov9b410fb2014-03-05 13:41:21 +0000133 ctx->dd->MutexDestroy(&cb, &h->dd);
Dmitry Vyukov512a18e2014-02-28 14:52:20 +0000134}
135
136} // namespace __dsan