blob: 08456540398cf0987288dc4500b30cbbf6f7d36b [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
21void Initialize() {
Dmitry Vyukov54a03032014-03-04 11:39:56 +000022 static u64 ctx_mem[sizeof(Context) / sizeof(u64) + 1];
23 ctx = new(ctx_mem) Context();
24
Dmitry Vyukov512a18e2014-02-28 14:52:20 +000025 InitializeInterceptors();
26 //common_flags()->allow_addr2line = true;
27 common_flags()->symbolize = true;
28 ctx->dd = DDetector::Create();
29}
30
31void ThreadInit(Thread *thr) {
32 thr->dd_pt = ctx->dd->CreatePhysicalThread();
33 thr->dd_lt = ctx->dd->CreateLogicalThread(0);
34}
35
36void ThreadDestroy(Thread *thr) {
37 ctx->dd->DestroyPhysicalThread(thr->dd_pt);
38 ctx->dd->DestroyLogicalThread(thr->dd_lt);
39}
40
41static u32 CurrentStackTrace(Thread *thr) {
42 StackTrace trace;
Dmitry Vyukov54a03032014-03-04 11:39:56 +000043 thr->ignore_interceptors = true;
Dmitry Vyukov512a18e2014-02-28 14:52:20 +000044 trace.Unwind(1000, 0, 0, 0, 0, 0, false);
Dmitry Vyukov54a03032014-03-04 11:39:56 +000045 thr->ignore_interceptors = false;
Dmitry Vyukov512a18e2014-02-28 14:52:20 +000046 const uptr skip = 4;
47 if (trace.size <= skip)
48 return 0;
49 return StackDepotPut(trace.trace + skip, trace.size - skip);
50}
51
52static void PrintStackTrace(Thread *thr, u32 stk) {
53 uptr size = 0;
54 const uptr *trace = StackDepotGet(stk, &size);
Dmitry Vyukov54a03032014-03-04 11:39:56 +000055 thr->ignore_interceptors = true;
Dmitry Vyukov512a18e2014-02-28 14:52:20 +000056 StackTrace::PrintStack(trace, size);
Dmitry Vyukov54a03032014-03-04 11:39:56 +000057 thr->ignore_interceptors = false;
Dmitry Vyukov512a18e2014-02-28 14:52:20 +000058}
59
60static void ReportDeadlock(Thread *thr, DDReport *rep) {
61 Printf("==============================\n");
62 Printf("DEADLOCK\n");
63 PrintStackTrace(thr, CurrentStackTrace(thr));
64 for (int i = 0; i < rep->n; i++) {
65 Printf("Mutex %llu created at:\n", rep->loop[i].mtx_ctx0);
66 PrintStackTrace(thr, rep->loop[i].stk);
67 }
68 Printf("==============================\n");
69}
70
71void MutexLock(Thread *thr, uptr m, bool writelock, bool trylock) {
Dmitry Vyukov54a03032014-03-04 11:39:56 +000072 if (thr->ignore_interceptors)
Dmitry Vyukov512a18e2014-02-28 14:52:20 +000073 return;
Dmitry Vyukov54a03032014-03-04 11:39:56 +000074 DDReport *rep = 0;
75 {
76 MutexHashMap::Handle h(&ctx->mutex_map, m);
77 if (h.created())
78 ctx->dd->MutexInit(&h->dd, CurrentStackTrace(thr), m);
79 rep = ctx->dd->MutexLock(thr->dd_pt, thr->dd_lt, &h->dd,
80 writelock, trylock);
81 }
Dmitry Vyukov512a18e2014-02-28 14:52:20 +000082 if (rep)
83 ReportDeadlock(thr, rep);
84}
85
86void MutexUnlock(Thread *thr, uptr m, bool writelock) {
Dmitry Vyukov54a03032014-03-04 11:39:56 +000087 if (thr->ignore_interceptors)
Dmitry Vyukov512a18e2014-02-28 14:52:20 +000088 return;
Dmitry Vyukov54a03032014-03-04 11:39:56 +000089 MutexHashMap::Handle h(&ctx->mutex_map, m);
90 ctx->dd->MutexUnlock(thr->dd_pt, thr->dd_lt, &h->dd, writelock);
Dmitry Vyukov512a18e2014-02-28 14:52:20 +000091}
92
93void MutexDestroy(Thread *thr, uptr m) {
Dmitry Vyukov54a03032014-03-04 11:39:56 +000094 if (thr->ignore_interceptors)
Dmitry Vyukov512a18e2014-02-28 14:52:20 +000095 return;
Dmitry Vyukov54a03032014-03-04 11:39:56 +000096 MutexHashMap::Handle h(&ctx->mutex_map, m, true);
97 if (!h.exists())
Dmitry Vyukov512a18e2014-02-28 14:52:20 +000098 return;
Dmitry Vyukov54a03032014-03-04 11:39:56 +000099 ctx->dd->MutexDestroy(thr->dd_pt, thr->dd_lt, &h->dd);
Dmitry Vyukov512a18e2014-02-28 14:52:20 +0000100}
101
102} // namespace __dsan