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
20namespace __memprof {
21
22MemprofThreadIdAndName::MemprofThreadIdAndName(MemprofThreadContext *t) {
23  Init(t->tid, t->name);
24}
25
26MemprofThreadIdAndName::MemprofThreadIdAndName(u32 tid) {
27  if (tid == kInvalidTid) {
28    Init(tid, "");
29  } else {
30    memprofThreadRegistry().CheckLocked();
31    MemprofThreadContext *t = GetThreadContextByTidLocked(tid);
32    Init(tid, t->name);
33  }
34}
35
36void MemprofThreadIdAndName::Init(u32 tid, const char *tname) {
37  int len = internal_snprintf(name, sizeof(name), "T%d", tid);
38  CHECK(((unsigned int)len) < sizeof(name));
39  if (tname[0] != '\0')
40    internal_snprintf(&name[len], sizeof(name) - len, " (%s)", tname);
41}
42
43void 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("Thread %s", MemprofThreadIdAndName(context).c_str());
53  if (context->parent_tid == kInvalidTid) {
54    str.AppendF(" created by unknown thread\n");
55    Printf("%s", str.data());
56    return;
57  }
58  str.AppendF(" created by %s here:\n",
59              MemprofThreadIdAndName(context->parent_tid).c_str());
60  Printf("%s", str.data());
61  StackDepotGet(context->stack_id).Print();
62  // Recursively described parent thread if needed.
63  if (flags()->print_full_thread_history) {
64    MemprofThreadContext *parent_context =
65        GetThreadContextByTidLocked(context->parent_tid);
66    DescribeThread(parent_context);
67  }
68}
69
70} // namespace __memprof
71