| //===-- memprof_descriptions.cpp -------------------------------*- C++ -*-===// |
| // |
| // 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 |
| // |
| //===----------------------------------------------------------------------===// |
| // |
| // This file is a part of MemProfiler, a memory profiler. |
| // |
| // MemProf functions for getting information about an address and/or printing |
| // it. |
| //===----------------------------------------------------------------------===// |
| |
| #include "memprof_descriptions.h" |
| #include "memprof_mapping.h" |
| #include "memprof_stack.h" |
| #include "sanitizer_common/sanitizer_stackdepot.h" |
| |
| namespace __memprof { |
| |
| MemprofThreadIdAndName::MemprofThreadIdAndName(MemprofThreadContext *t) { |
| Init(t->tid, t->name); |
| } |
| |
| MemprofThreadIdAndName::MemprofThreadIdAndName(u32 tid) { |
| if (tid == kInvalidTid) { |
| Init(tid, ""); |
| } else { |
| memprofThreadRegistry().CheckLocked(); |
| MemprofThreadContext *t = GetThreadContextByTidLocked(tid); |
| Init(tid, t->name); |
| } |
| } |
| |
| void MemprofThreadIdAndName::Init(u32 tid, const char *tname) { |
| int len = internal_snprintf(name, sizeof(name), "T%d", tid); |
| CHECK(((unsigned int)len) < sizeof(name)); |
| if (tname[0] != '\0') |
| internal_snprintf(&name[len], sizeof(name) - len, " (%s)", tname); |
| } |
| |
| void DescribeThread(MemprofThreadContext *context) { |
| CHECK(context); |
| memprofThreadRegistry().CheckLocked(); |
| // No need to announce the main thread. |
| if (context->tid == kMainTid || context->announced) { |
| return; |
| } |
| context->announced = true; |
| InternalScopedString str; |
| str.append("Thread %s", MemprofThreadIdAndName(context).c_str()); |
| if (context->parent_tid == kInvalidTid) { |
| str.append(" created by unknown thread\n"); |
| Printf("%s", str.data()); |
| return; |
| } |
| str.append(" created by %s here:\n", |
| MemprofThreadIdAndName(context->parent_tid).c_str()); |
| Printf("%s", str.data()); |
| StackDepotGet(context->stack_id).Print(); |
| // Recursively described parent thread if needed. |
| if (flags()->print_full_thread_history) { |
| MemprofThreadContext *parent_context = |
| GetThreadContextByTidLocked(context->parent_tid); |
| DescribeThread(parent_context); |
| } |
| } |
| |
| } // namespace __memprof |