summaryrefslogtreecommitdiffstats
path: root/llvm/tools
diff options
context:
space:
mode:
authorDean Michael Berris <dberris@google.com>2017-08-31 01:07:24 +0000
committerDean Michael Berris <dberris@google.com>2017-08-31 01:07:24 +0000
commit415f15c5e206127c57fe7996014569dae0f1419f (patch)
tree564595a024d5570b41a1919fe982cf91a05e108c /llvm/tools
parent84614f851c4661b219c680457ec0e6eb99ceabc5 (diff)
downloadbcm5719-llvm-415f15c5e206127c57fe7996014569dae0f1419f.tar.gz
bcm5719-llvm-415f15c5e206127c57fe7996014569dae0f1419f.zip
[XRay][tools] Fix an accounting bug in llvm-xray account
Summary: Before this patch, llvm-xray account will assume that thread stacks will not be empty. Unfortunately there are cases where an instrumented function will see a call to `fork()` which will cause the child process to not see the start of the function, but only see the end of the function. The tooling cannot assume that threads will always have perfect stacks, and so we change it to support this reality. Reviewers: dblaikie Subscribers: llvm-commits Differential Revision: https://reviews.llvm.org/D31870 llvm-svn: 312204
Diffstat (limited to 'llvm/tools')
-rw-r--r--llvm/tools/llvm-xray/xray-account.cc34
1 files changed, 31 insertions, 3 deletions
diff --git a/llvm/tools/llvm-xray/xray-account.cc b/llvm/tools/llvm-xray/xray-account.cc
index 13654c3911f..e97b4d8d1ed 100644
--- a/llvm/tools/llvm-xray/xray-account.cc
+++ b/llvm/tools/llvm-xray/xray-account.cc
@@ -147,12 +147,13 @@ bool LatencyAccountant::accountRecord(const XRayRecord &Record) {
auto &ThreadStack = PerThreadFunctionStack[Record.TId];
switch (Record.Type) {
case RecordTypes::ENTER: {
- // Function Enter
ThreadStack.emplace_back(Record.FuncId, Record.TSC);
break;
}
case RecordTypes::EXIT: {
- // Function Exit
+ if (ThreadStack.empty())
+ return false;
+
if (ThreadStack.back().first == Record.FuncId) {
const auto &Top = ThreadStack.back();
recordLatency(Top.first, diff(Top.second, Record.TSC));
@@ -407,6 +408,22 @@ void LatencyAccountant::exportStatsAsCSV(raw_ostream &OS,
using namespace llvm::xray;
+namespace llvm {
+template <> struct format_provider<llvm::xray::RecordTypes> {
+ static void format(const llvm::xray::RecordTypes &T, raw_ostream &Stream,
+ StringRef Style) {
+ switch(T) {
+ case RecordTypes::ENTER:
+ Stream << "enter";
+ break;
+ case RecordTypes::EXIT:
+ Stream << "exit";
+ break;
+ }
+ }
+};
+} // namespace llvm
+
static CommandRegistration Unused(&Account, []() -> Error {
InstrumentationMap Map;
if (!AccountInstrMap.empty()) {
@@ -445,11 +462,22 @@ static CommandRegistration Unused(&Account, []() -> Error {
for (const auto &Record : T) {
if (FCA.accountRecord(Record))
continue;
+ errs()
+ << "Error processing record: "
+ << llvm::formatv(
+ R"({{type: {0}; cpu: {1}; record-type: {2}; function-id: {3}; tsc: {4}; thread-id: {5}}})",
+ Record.RecordType, Record.CPU, Record.Type, Record.FuncId,
+ Record.TId)
+ << '\n';
for (const auto &ThreadStack : FCA.getPerThreadFunctionStack()) {
errs() << "Thread ID: " << ThreadStack.first << "\n";
+ if (ThreadStack.second.empty()) {
+ errs() << " (empty stack)\n";
+ continue;
+ }
auto Level = ThreadStack.second.size();
for (const auto &Entry : llvm::reverse(ThreadStack.second))
- errs() << "#" << Level-- << "\t"
+ errs() << " #" << Level-- << "\t"
<< FuncIdHelper.SymbolOrNumber(Entry.first) << '\n';
}
if (!AccountKeepGoing)
OpenPOWER on IntegriCloud