123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158 |
- //===-- dd_rtl.cpp --------------------------------------------------------===//
- //
- // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
- // See https://llvm.org/LICENSE.txt for license information.
- // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
- //
- //===----------------------------------------------------------------------===//
- #include "dd_rtl.h"
- #include "sanitizer_common/sanitizer_common.h"
- #include "sanitizer_common/sanitizer_placement_new.h"
- #include "sanitizer_common/sanitizer_flags.h"
- #include "sanitizer_common/sanitizer_flag_parser.h"
- #include "sanitizer_common/sanitizer_stacktrace.h"
- #include "sanitizer_common/sanitizer_stackdepot.h"
- namespace __dsan {
- static Context *ctx;
- static u32 CurrentStackTrace(Thread *thr, uptr skip) {
- BufferedStackTrace stack;
- thr->ignore_interceptors = true;
- stack.Unwind(1000, 0, 0, 0, 0, 0, false);
- thr->ignore_interceptors = false;
- if (stack.size <= skip)
- return 0;
- return StackDepotPut(StackTrace(stack.trace + skip, stack.size - skip));
- }
- static void PrintStackTrace(Thread *thr, u32 stk) {
- StackTrace stack = StackDepotGet(stk);
- thr->ignore_interceptors = true;
- stack.Print();
- thr->ignore_interceptors = false;
- }
- static void ReportDeadlock(Thread *thr, DDReport *rep) {
- if (rep == 0)
- return;
- Lock lock(&ctx->report_mutex);
- Printf("==============================\n");
- Printf("WARNING: lock-order-inversion (potential deadlock)\n");
- for (int i = 0; i < rep->n; i++) {
- Printf("Thread %lld locks mutex %llu while holding mutex %llu:\n",
- rep->loop[i].thr_ctx, rep->loop[i].mtx_ctx1, rep->loop[i].mtx_ctx0);
- PrintStackTrace(thr, rep->loop[i].stk[1]);
- if (rep->loop[i].stk[0]) {
- Printf("Mutex %llu was acquired here:\n",
- rep->loop[i].mtx_ctx0);
- PrintStackTrace(thr, rep->loop[i].stk[0]);
- }
- }
- Printf("==============================\n");
- }
- Callback::Callback(Thread *thr)
- : thr(thr) {
- lt = thr->dd_lt;
- pt = thr->dd_pt;
- }
- u32 Callback::Unwind() {
- return CurrentStackTrace(thr, 3);
- }
- static void InitializeFlags() {
- Flags *f = flags();
- // Default values.
- f->second_deadlock_stack = false;
- SetCommonFlagsDefaults();
- {
- // Override some common flags defaults.
- CommonFlags cf;
- cf.CopyFrom(*common_flags());
- cf.allow_addr2line = true;
- OverrideCommonFlags(cf);
- }
- // Override from command line.
- FlagParser parser;
- RegisterFlag(&parser, "second_deadlock_stack", "", &f->second_deadlock_stack);
- RegisterCommonFlags(&parser);
- parser.ParseStringFromEnv("DSAN_OPTIONS");
- SetVerbosity(common_flags()->verbosity);
- }
- void Initialize() {
- static u64 ctx_mem[sizeof(Context) / sizeof(u64) + 1];
- ctx = new(ctx_mem) Context();
- InitializeInterceptors();
- InitializeFlags();
- ctx->dd = DDetector::Create(flags());
- }
- void ThreadInit(Thread *thr) {
- static atomic_uintptr_t id_gen;
- uptr id = atomic_fetch_add(&id_gen, 1, memory_order_relaxed);
- thr->dd_pt = ctx->dd->CreatePhysicalThread();
- thr->dd_lt = ctx->dd->CreateLogicalThread(id);
- }
- void ThreadDestroy(Thread *thr) {
- ctx->dd->DestroyPhysicalThread(thr->dd_pt);
- ctx->dd->DestroyLogicalThread(thr->dd_lt);
- }
- void MutexBeforeLock(Thread *thr, uptr m, bool writelock) {
- if (thr->ignore_interceptors)
- return;
- Callback cb(thr);
- {
- MutexHashMap::Handle h(&ctx->mutex_map, m);
- if (h.created())
- ctx->dd->MutexInit(&cb, &h->dd);
- ctx->dd->MutexBeforeLock(&cb, &h->dd, writelock);
- }
- ReportDeadlock(thr, ctx->dd->GetReport(&cb));
- }
- void MutexAfterLock(Thread *thr, uptr m, bool writelock, bool trylock) {
- if (thr->ignore_interceptors)
- return;
- Callback cb(thr);
- {
- MutexHashMap::Handle h(&ctx->mutex_map, m);
- if (h.created())
- ctx->dd->MutexInit(&cb, &h->dd);
- ctx->dd->MutexAfterLock(&cb, &h->dd, writelock, trylock);
- }
- ReportDeadlock(thr, ctx->dd->GetReport(&cb));
- }
- void MutexBeforeUnlock(Thread *thr, uptr m, bool writelock) {
- if (thr->ignore_interceptors)
- return;
- Callback cb(thr);
- {
- MutexHashMap::Handle h(&ctx->mutex_map, m);
- ctx->dd->MutexBeforeUnlock(&cb, &h->dd, writelock);
- }
- ReportDeadlock(thr, ctx->dd->GetReport(&cb));
- }
- void MutexDestroy(Thread *thr, uptr m) {
- if (thr->ignore_interceptors)
- return;
- Callback cb(thr);
- MutexHashMap::Handle h(&ctx->mutex_map, m, true);
- if (!h.exists())
- return;
- ctx->dd->MutexDestroy(&cb, &h->dd);
- }
- } // namespace __dsan
|