1 | //===-- memprof_descriptions.cpp -------------------------------*- C++ -*-===// |
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 | //===----------------------------------------------------------------------===// |
8 | // |
9 | // This file is a part of MemProfiler, a memory profiler. |
10 | // |
11 | // MemProf functions for getting information about an address and/or printing |
12 | // it. |
13 | //===----------------------------------------------------------------------===// |
14 | |
15 | #include "memprof_descriptions.h" |
16 | #include "memprof_mapping.h" |
17 | #include "memprof_stack.h" |
18 | #include "sanitizer_common/sanitizer_stackdepot.h" |
19 | |
20 | namespace __memprof { |
21 | |
22 | MemprofThreadIdAndName::MemprofThreadIdAndName(MemprofThreadContext *t) { |
23 | Init(tid: t->tid, tname: t->name); |
24 | } |
25 | |
26 | MemprofThreadIdAndName::MemprofThreadIdAndName(u32 tid) { |
27 | if (tid == kInvalidTid) { |
28 | Init(tid, tname: "" ); |
29 | } else { |
30 | memprofThreadRegistry().CheckLocked(); |
31 | MemprofThreadContext *t = GetThreadContextByTidLocked(tid); |
32 | Init(tid, tname: t->name); |
33 | } |
34 | } |
35 | |
36 | void MemprofThreadIdAndName::Init(u32 tid, const char *tname) { |
37 | int len = internal_snprintf(buffer: name, length: sizeof(name), format: "T%d" , tid); |
38 | CHECK(((unsigned int)len) < sizeof(name)); |
39 | if (tname[0] != '\0') |
40 | internal_snprintf(buffer: &name[len], length: sizeof(name) - len, format: " (%s)" , tname); |
41 | } |
42 | |
43 | void DescribeThread(MemprofThreadContext *context) { |
44 | CHECK(context); |
45 | memprofThreadRegistry().CheckLocked(); |
46 | // No need to announce the main thread. |
47 | if (context->tid == kMainTid || context->announced) { |
48 | return; |
49 | } |
50 | context->announced = true; |
51 | InternalScopedString str; |
52 | str.AppendF(format: "Thread %s" , MemprofThreadIdAndName(context).c_str()); |
53 | if (context->parent_tid == kInvalidTid) { |
54 | str.Append(str: " created by unknown thread\n" ); |
55 | Printf(format: "%s" , str.data()); |
56 | return; |
57 | } |
58 | str.AppendF(format: " created by %s here:\n" , |
59 | MemprofThreadIdAndName(context->parent_tid).c_str()); |
60 | Printf(format: "%s" , str.data()); |
61 | StackDepotGet(id: context->stack_id).Print(); |
62 | // Recursively described parent thread if needed. |
63 | if (flags()->print_full_thread_history) { |
64 | MemprofThreadContext *parent_context = |
65 | GetThreadContextByTidLocked(tid: context->parent_tid); |
66 | DescribeThread(context: parent_context); |
67 | } |
68 | } |
69 | |
70 | } // namespace __memprof |
71 | |