[Reland][Runtimes] Merge 'compile_commands.json' files from runtimes build (#116303)
[llvm-project.git] / compiler-rt / lib / sanitizer_common / sanitizer_thread_history.cpp
blob0f5bec3ca083e372813fc5e68064824ac315cae8
1 //===-- sanitizer_thread_history.cpp --------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
9 #include "sanitizer_thread_history.h"
11 #include "sanitizer_stackdepot.h"
12 namespace __sanitizer {
14 void PrintThreadHistory(ThreadRegistry &registry, InternalScopedString &out) {
15 ThreadRegistryLock l(&registry);
16 // Stack traces are largest part of printout and they often the same for
17 // multiple threads, so we will deduplicate them.
18 InternalMmapVector<const ThreadContextBase *> stacks;
20 registry.RunCallbackForEachThreadLocked(
21 [](ThreadContextBase *context, void *arg) {
22 static_cast<decltype(&stacks)>(arg)->push_back(context);
24 &stacks);
26 Sort(stacks.data(), stacks.size(),
27 [](const ThreadContextBase *a, const ThreadContextBase *b) {
28 if (a->stack_id < b->stack_id)
29 return true;
30 if (a->stack_id > b->stack_id)
31 return false;
32 return a->unique_id < b->unique_id;
33 });
35 auto describe_thread = [&](const ThreadContextBase *context) {
36 if (!context) {
37 out.Append("T-1");
38 return;
40 out.AppendF("T%llu/%llu", context->unique_id, context->os_id);
41 if (internal_strlen(context->name))
42 out.AppendF(" (%s)", context->name);
45 auto get_parent =
46 [&](const ThreadContextBase *context) -> const ThreadContextBase * {
47 if (!context)
48 return nullptr;
49 ThreadContextBase *parent = registry.GetThreadLocked(context->parent_tid);
50 if (!parent)
51 return nullptr;
52 if (parent->unique_id >= context->unique_id)
53 return nullptr;
54 return parent;
57 const ThreadContextBase *prev = nullptr;
58 for (const ThreadContextBase *context : stacks) {
59 if (prev && prev->stack_id != context->stack_id)
60 StackDepotGet(prev->stack_id).PrintTo(&out);
61 prev = context;
62 out.Append("Thread ");
63 describe_thread(context);
64 out.Append(" was created by ");
65 describe_thread(get_parent(context));
66 out.Append("\n");
68 if (prev)
69 StackDepotGet(prev->stack_id).PrintTo(&out);
72 } // namespace __sanitizer