diff options
author | nkozlovskiy <nmk@ydb.tech> | 2023-10-11 19:11:46 +0300 |
---|---|---|
committer | nkozlovskiy <nmk@ydb.tech> | 2023-10-11 19:33:28 +0300 |
commit | 61b3971447e473726d6cdb23fc298e457b4d973c (patch) | |
tree | e2a2a864bb7717f7ae6138f6a3194a254dd2c7bb /contrib/libs/clang14-rt/lib/tsan/dd/dd_rtl.cpp | |
parent | a674dc57d88d43c2e8e90a6084d5d2c988e0402c (diff) | |
download | ydb-61b3971447e473726d6cdb23fc298e457b4d973c.tar.gz |
add sanitizers dependencies
Diffstat (limited to 'contrib/libs/clang14-rt/lib/tsan/dd/dd_rtl.cpp')
-rw-r--r-- | contrib/libs/clang14-rt/lib/tsan/dd/dd_rtl.cpp | 158 |
1 files changed, 158 insertions, 0 deletions
diff --git a/contrib/libs/clang14-rt/lib/tsan/dd/dd_rtl.cpp b/contrib/libs/clang14-rt/lib/tsan/dd/dd_rtl.cpp new file mode 100644 index 0000000000..35b367c0ce --- /dev/null +++ b/contrib/libs/clang14-rt/lib/tsan/dd/dd_rtl.cpp @@ -0,0 +1,158 @@ +//===-- 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 |