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" 1486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#include "sanitizer_common/sanitizer_flag_parser.h" 152d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#include "sanitizer_common/sanitizer_stacktrace.h" 162d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#include "sanitizer_common/sanitizer_stackdepot.h" 172d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 182d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesnamespace __dsan { 192d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 202d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesstatic Context *ctx; 212d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 222d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesstatic u32 CurrentStackTrace(Thread *thr, uptr skip) { 236d1862363c88c183b0ed7740fca876342cf0474bStephen Hines BufferedStackTrace stack; 242d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines thr->ignore_interceptors = true; 256d1862363c88c183b0ed7740fca876342cf0474bStephen Hines stack.Unwind(1000, 0, 0, 0, 0, 0, false); 262d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines thr->ignore_interceptors = false; 276d1862363c88c183b0ed7740fca876342cf0474bStephen Hines if (stack.size <= skip) 282d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines return 0; 296d1862363c88c183b0ed7740fca876342cf0474bStephen Hines return StackDepotPut(StackTrace(stack.trace + skip, stack.size - skip)); 302d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines} 312d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 322d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesstatic void PrintStackTrace(Thread *thr, u32 stk) { 336d1862363c88c183b0ed7740fca876342cf0474bStephen Hines StackTrace stack = StackDepotGet(stk); 342d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines thr->ignore_interceptors = true; 356d1862363c88c183b0ed7740fca876342cf0474bStephen Hines stack.Print(); 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 6886277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesstatic void InitializeFlags() { 6986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines Flags *f = flags(); 702d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 712d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines // Default values. 722d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines f->second_deadlock_stack = false; 732d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 7486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines SetCommonFlagsDefaults(); 7586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines { 7686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines // Override some common flags defaults. 7786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines CommonFlags cf; 7886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines cf.CopyFrom(*common_flags()); 7986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines cf.allow_addr2line = true; 8086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines OverrideCommonFlags(cf); 8186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines } 822d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 832d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines // Override from command line. 8486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines FlagParser parser; 8586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines RegisterFlag(&parser, "second_deadlock_stack", "", &f->second_deadlock_stack); 8686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines RegisterCommonFlags(&parser); 8786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines parser.ParseString(GetEnv("DSAN_OPTIONS")); 8886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines SetVerbosity(common_flags()->verbosity); 892d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines} 902d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 912d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesvoid Initialize() { 922d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines static u64 ctx_mem[sizeof(Context) / sizeof(u64) + 1]; 932d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines ctx = new(ctx_mem) Context(); 942d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 952d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines InitializeInterceptors(); 9686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines InitializeFlags(); 972d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines ctx->dd = DDetector::Create(flags()); 982d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines} 992d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 1002d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesvoid ThreadInit(Thread *thr) { 1012d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines static atomic_uintptr_t id_gen; 1022d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines uptr id = atomic_fetch_add(&id_gen, 1, memory_order_relaxed); 1032d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines thr->dd_pt = ctx->dd->CreatePhysicalThread(); 1042d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines thr->dd_lt = ctx->dd->CreateLogicalThread(id); 1052d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines} 1062d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 1072d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesvoid ThreadDestroy(Thread *thr) { 1082d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines ctx->dd->DestroyPhysicalThread(thr->dd_pt); 1092d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines ctx->dd->DestroyLogicalThread(thr->dd_lt); 1102d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines} 1112d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 1122d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesvoid MutexBeforeLock(Thread *thr, uptr m, bool writelock) { 1132d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines if (thr->ignore_interceptors) 1142d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines return; 1152d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines Callback cb(thr); 1162d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines { 1172d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines MutexHashMap::Handle h(&ctx->mutex_map, m); 1182d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines if (h.created()) 1192d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines ctx->dd->MutexInit(&cb, &h->dd); 1202d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines ctx->dd->MutexBeforeLock(&cb, &h->dd, writelock); 1212d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines } 1222d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines ReportDeadlock(thr, ctx->dd->GetReport(&cb)); 1232d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines} 1242d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 1252d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesvoid MutexAfterLock(Thread *thr, uptr m, bool writelock, bool trylock) { 1262d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines if (thr->ignore_interceptors) 1272d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines return; 1282d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines Callback cb(thr); 1292d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines { 1302d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines MutexHashMap::Handle h(&ctx->mutex_map, m); 1312d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines if (h.created()) 1322d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines ctx->dd->MutexInit(&cb, &h->dd); 1332d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines ctx->dd->MutexAfterLock(&cb, &h->dd, writelock, trylock); 1342d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines } 1352d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines ReportDeadlock(thr, ctx->dd->GetReport(&cb)); 1362d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines} 1372d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 1382d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesvoid MutexBeforeUnlock(Thread *thr, uptr m, bool writelock) { 1392d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines if (thr->ignore_interceptors) 1402d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines return; 1412d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines Callback cb(thr); 1422d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines { 1432d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines MutexHashMap::Handle h(&ctx->mutex_map, m); 1442d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines ctx->dd->MutexBeforeUnlock(&cb, &h->dd, writelock); 1452d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines } 1462d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines ReportDeadlock(thr, ctx->dd->GetReport(&cb)); 1472d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines} 1482d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 1492d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesvoid MutexDestroy(Thread *thr, uptr m) { 1502d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines if (thr->ignore_interceptors) 1512d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines return; 1522d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines Callback cb(thr); 1532d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines MutexHashMap::Handle h(&ctx->mutex_map, m, true); 1542d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines if (!h.exists()) 1552d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines return; 1562d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines ctx->dd->MutexDestroy(&cb, &h->dd); 1572d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines} 1582d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 1592d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines} // namespace __dsan 160