12d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines//===-- dd_rtl.cc ---------------------------------------------------------===// 22d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines// 32d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines// The LLVM Compiler Infrastructure 42d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines// 52d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines// This file is distributed under the University of Illinois Open Source 62d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines// License. See LICENSE.TXT for details. 72d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines// 82d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines//===----------------------------------------------------------------------===// 92d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 102d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#include "dd_rtl.h" 112d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#include "sanitizer_common/sanitizer_common.h" 122d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#include "sanitizer_common/sanitizer_placement_new.h" 132d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#include "sanitizer_common/sanitizer_flags.h" 142d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#include "sanitizer_common/sanitizer_stacktrace.h" 152d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#include "sanitizer_common/sanitizer_stackdepot.h" 162d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 172d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesnamespace __dsan { 182d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 192d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesstatic Context *ctx; 202d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 212d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesstatic u32 CurrentStackTrace(Thread *thr, uptr skip) { 222d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines StackTrace trace; 232d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines thr->ignore_interceptors = true; 242d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines trace.Unwind(1000, 0, 0, 0, 0, 0, false); 252d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines thr->ignore_interceptors = false; 262d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines if (trace.size <= skip) 272d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines return 0; 282d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines return StackDepotPut(trace.trace + skip, trace.size - skip); 292d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines} 302d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 312d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesstatic void PrintStackTrace(Thread *thr, u32 stk) { 322d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines uptr size = 0; 332d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines const uptr *trace = StackDepotGet(stk, &size); 342d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines thr->ignore_interceptors = true; 352d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines StackTrace::PrintStack(trace, size); 362d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines thr->ignore_interceptors = false; 372d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines} 382d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 392d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesstatic void ReportDeadlock(Thread *thr, DDReport *rep) { 402d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines if (rep == 0) 412d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines return; 422d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines BlockingMutexLock lock(&ctx->report_mutex); 432d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines Printf("==============================\n"); 442d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines Printf("WARNING: lock-order-inversion (potential deadlock)\n"); 452d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines for (int i = 0; i < rep->n; i++) { 462d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines Printf("Thread %d locks mutex %llu while holding mutex %llu:\n", 472d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines rep->loop[i].thr_ctx, rep->loop[i].mtx_ctx1, rep->loop[i].mtx_ctx0); 482d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines PrintStackTrace(thr, rep->loop[i].stk[1]); 492d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines if (rep->loop[i].stk[0]) { 502d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines Printf("Mutex %llu was acquired here:\n", 512d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines rep->loop[i].mtx_ctx0); 522d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines PrintStackTrace(thr, rep->loop[i].stk[0]); 532d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines } 542d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines } 552d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines Printf("==============================\n"); 562d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines} 572d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 582d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen HinesCallback::Callback(Thread *thr) 592d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines : thr(thr) { 602d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines lt = thr->dd_lt; 612d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines pt = thr->dd_pt; 622d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines} 632d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 642d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesu32 Callback::Unwind() { 652d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines return CurrentStackTrace(thr, 3); 662d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines} 672d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 682d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesvoid InitializeFlags(Flags *f, const char *env) { 692d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines internal_memset(f, 0, sizeof(*f)); 702d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 712d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines // Default values. 722d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines f->second_deadlock_stack = false; 732d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 742d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines SetCommonFlagsDefaults(f); 752d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines // Override some common flags defaults. 762d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines f->allow_addr2line = true; 772d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 782d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines // Override from command line. 792d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines ParseFlag(env, &f->second_deadlock_stack, "second_deadlock_stack", ""); 802d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines ParseCommonFlagsFromString(f, env); 812d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 822d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines // Copy back to common flags. 832d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines *common_flags() = *f; 842d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines} 852d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 862d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesvoid Initialize() { 872d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines static u64 ctx_mem[sizeof(Context) / sizeof(u64) + 1]; 882d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines ctx = new(ctx_mem) Context(); 892d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 902d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines InitializeInterceptors(); 912d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines InitializeFlags(flags(), GetEnv("DSAN_OPTIONS")); 922d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines common_flags()->symbolize = true; 932d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines ctx->dd = DDetector::Create(flags()); 942d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines} 952d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 962d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesvoid ThreadInit(Thread *thr) { 972d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines static atomic_uintptr_t id_gen; 982d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines uptr id = atomic_fetch_add(&id_gen, 1, memory_order_relaxed); 992d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines thr->dd_pt = ctx->dd->CreatePhysicalThread(); 1002d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines thr->dd_lt = ctx->dd->CreateLogicalThread(id); 1012d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines} 1022d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 1032d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesvoid ThreadDestroy(Thread *thr) { 1042d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines ctx->dd->DestroyPhysicalThread(thr->dd_pt); 1052d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines ctx->dd->DestroyLogicalThread(thr->dd_lt); 1062d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines} 1072d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 1082d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesvoid MutexBeforeLock(Thread *thr, uptr m, bool writelock) { 1092d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines if (thr->ignore_interceptors) 1102d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines return; 1112d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines Callback cb(thr); 1122d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines { 1132d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines MutexHashMap::Handle h(&ctx->mutex_map, m); 1142d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines if (h.created()) 1152d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines ctx->dd->MutexInit(&cb, &h->dd); 1162d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines ctx->dd->MutexBeforeLock(&cb, &h->dd, writelock); 1172d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines } 1182d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines ReportDeadlock(thr, ctx->dd->GetReport(&cb)); 1192d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines} 1202d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 1212d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesvoid MutexAfterLock(Thread *thr, uptr m, bool writelock, bool trylock) { 1222d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines if (thr->ignore_interceptors) 1232d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines return; 1242d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines Callback cb(thr); 1252d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines { 1262d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines MutexHashMap::Handle h(&ctx->mutex_map, m); 1272d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines if (h.created()) 1282d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines ctx->dd->MutexInit(&cb, &h->dd); 1292d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines ctx->dd->MutexAfterLock(&cb, &h->dd, writelock, trylock); 1302d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines } 1312d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines ReportDeadlock(thr, ctx->dd->GetReport(&cb)); 1322d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines} 1332d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 1342d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesvoid MutexBeforeUnlock(Thread *thr, uptr m, bool writelock) { 1352d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines if (thr->ignore_interceptors) 1362d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines return; 1372d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines Callback cb(thr); 1382d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines { 1392d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines MutexHashMap::Handle h(&ctx->mutex_map, m); 1402d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines ctx->dd->MutexBeforeUnlock(&cb, &h->dd, writelock); 1412d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines } 1422d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines ReportDeadlock(thr, ctx->dd->GetReport(&cb)); 1432d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines} 1442d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 1452d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesvoid MutexDestroy(Thread *thr, uptr m) { 1462d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines if (thr->ignore_interceptors) 1472d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines return; 1482d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines Callback cb(thr); 1492d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines MutexHashMap::Handle h(&ctx->mutex_map, m, true); 1502d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines if (!h.exists()) 1512d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines return; 1522d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines ctx->dd->MutexDestroy(&cb, &h->dd); 1532d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines} 1542d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 1552d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines} // namespace __dsan 156