Path: blob/main/contrib/llvm-project/compiler-rt/lib/tsan/dd/dd_rtl.cpp
35269 views
//===-- dd_rtl.cpp --------------------------------------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#include "dd_rtl.h"9#include "sanitizer_common/sanitizer_common.h"10#include "sanitizer_common/sanitizer_placement_new.h"11#include "sanitizer_common/sanitizer_flags.h"12#include "sanitizer_common/sanitizer_flag_parser.h"13#include "sanitizer_common/sanitizer_stacktrace.h"14#include "sanitizer_common/sanitizer_stackdepot.h"1516namespace __dsan {1718static Context *ctx;1920static u32 CurrentStackTrace(Thread *thr, uptr skip) {21BufferedStackTrace stack;22thr->ignore_interceptors = true;23stack.Unwind(1000, 0, 0, 0, 0, 0, false);24thr->ignore_interceptors = false;25if (stack.size <= skip)26return 0;27return StackDepotPut(StackTrace(stack.trace + skip, stack.size - skip));28}2930static void PrintStackTrace(Thread *thr, u32 stk) {31StackTrace stack = StackDepotGet(stk);32thr->ignore_interceptors = true;33stack.Print();34thr->ignore_interceptors = false;35}3637static void ReportDeadlock(Thread *thr, DDReport *rep) {38if (rep == 0)39return;40Lock lock(&ctx->report_mutex);41Printf("==============================\n");42Printf("WARNING: lock-order-inversion (potential deadlock)\n");43for (int i = 0; i < rep->n; i++) {44Printf("Thread %lld locks mutex %llu while holding mutex %llu:\n",45rep->loop[i].thr_ctx, rep->loop[i].mtx_ctx1, rep->loop[i].mtx_ctx0);46PrintStackTrace(thr, rep->loop[i].stk[1]);47if (rep->loop[i].stk[0]) {48Printf("Mutex %llu was acquired here:\n",49rep->loop[i].mtx_ctx0);50PrintStackTrace(thr, rep->loop[i].stk[0]);51}52}53Printf("==============================\n");54}5556Callback::Callback(Thread *thr)57: thr(thr) {58lt = thr->dd_lt;59pt = thr->dd_pt;60}6162u32 Callback::Unwind() {63return CurrentStackTrace(thr, 3);64}6566static void InitializeFlags() {67Flags *f = flags();6869// Default values.70f->second_deadlock_stack = false;7172SetCommonFlagsDefaults();73{74// Override some common flags defaults.75CommonFlags cf;76cf.CopyFrom(*common_flags());77cf.allow_addr2line = true;78OverrideCommonFlags(cf);79}8081// Override from command line.82FlagParser parser;83RegisterFlag(&parser, "second_deadlock_stack", "", &f->second_deadlock_stack);84RegisterCommonFlags(&parser);85parser.ParseStringFromEnv("DSAN_OPTIONS");86SetVerbosity(common_flags()->verbosity);87}8889void Initialize() {90static u64 ctx_mem[sizeof(Context) / sizeof(u64) + 1];91ctx = new(ctx_mem) Context();9293InitializeInterceptors();94InitializeFlags();95ctx->dd = DDetector::Create(flags());96}9798void ThreadInit(Thread *thr) {99static atomic_uintptr_t id_gen;100uptr id = atomic_fetch_add(&id_gen, 1, memory_order_relaxed);101thr->dd_pt = ctx->dd->CreatePhysicalThread();102thr->dd_lt = ctx->dd->CreateLogicalThread(id);103}104105void ThreadDestroy(Thread *thr) {106ctx->dd->DestroyPhysicalThread(thr->dd_pt);107ctx->dd->DestroyLogicalThread(thr->dd_lt);108}109110void MutexBeforeLock(Thread *thr, uptr m, bool writelock) {111if (thr->ignore_interceptors)112return;113Callback cb(thr);114{115MutexHashMap::Handle h(&ctx->mutex_map, m);116if (h.created())117ctx->dd->MutexInit(&cb, &h->dd);118ctx->dd->MutexBeforeLock(&cb, &h->dd, writelock);119}120ReportDeadlock(thr, ctx->dd->GetReport(&cb));121}122123void MutexAfterLock(Thread *thr, uptr m, bool writelock, bool trylock) {124if (thr->ignore_interceptors)125return;126Callback cb(thr);127{128MutexHashMap::Handle h(&ctx->mutex_map, m);129if (h.created())130ctx->dd->MutexInit(&cb, &h->dd);131ctx->dd->MutexAfterLock(&cb, &h->dd, writelock, trylock);132}133ReportDeadlock(thr, ctx->dd->GetReport(&cb));134}135136void MutexBeforeUnlock(Thread *thr, uptr m, bool writelock) {137if (thr->ignore_interceptors)138return;139Callback cb(thr);140{141MutexHashMap::Handle h(&ctx->mutex_map, m);142ctx->dd->MutexBeforeUnlock(&cb, &h->dd, writelock);143}144ReportDeadlock(thr, ctx->dd->GetReport(&cb));145}146147void MutexDestroy(Thread *thr, uptr m) {148if (thr->ignore_interceptors)149return;150Callback cb(thr);151MutexHashMap::Handle h(&ctx->mutex_map, m, true);152if (!h.exists())153return;154ctx->dd->MutexDestroy(&cb, &h->dd);155}156157} // namespace __dsan158159160