Files
clang-p2996/compiler-rt/lib/memprof/memprof_descriptions.cpp
Teresa Johnson 3d4bba302d [MemProf] Memory profiling runtime support
See RFC for background:
http://lists.llvm.org/pipermail/llvm-dev/2020-June/142744.html

Follow on companion to the clang/llvm instrumentation support in D85948
and committed earlier.

This patch adds the compiler-rt runtime support for the memory
profiling.

Note that much of this support was cloned from asan (and then greatly
simplified and renamed). For example the interactions with the
sanitizer_common allocators, error handling, interception, etc.

The bulk of the memory profiling specific code can be found in the
MemInfoBlock, MemInfoBlockCache, and related classes defined and used
in memprof_allocator.cpp.

For now, the memory profile is dumped to text (stderr by default, but
honors the sanitizer_common log_path flag). It is dumped in either a
default verbose format, or an optional terse format.

This patch also adds a set of tests for the core functionality.

Differential Revision: https://reviews.llvm.org/D87120
2020-10-16 09:47:02 -07:00

71 lines
2.3 KiB
C++

//===-- 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 == 0 || context->announced) {
return;
}
context->announced = true;
InternalScopedString str(1024);
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