blob: 24cd69f074db6ba479bd29599e2ef638684ee2a2 [file] [log] [blame]
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "base/debug/task_trace.h"
#include <algorithm>
#include <iostream>
#include "base/pending_task.h"
#include "base/task/common/task_annotator.h"
namespace base {
namespace debug {
TaskTrace::TaskTrace() {
const PendingTask* current_task = TaskAnnotator::CurrentTaskForThread();
if (!current_task)
return;
std::array<const void*, PendingTask::kTaskBacktraceLength + 1> task_trace;
task_trace[0] = current_task->posted_from.program_counter();
std::copy(current_task->task_backtrace.begin(),
current_task->task_backtrace.end(), task_trace.begin() + 1);
size_t length = 0;
while (length < task_trace.size() && task_trace[length])
++length;
if (length == 0)
return;
stack_trace_.emplace(task_trace.data(), length);
trace_overflow_ = current_task->task_backtrace_overflow;
}
bool TaskTrace::empty() const {
return !stack_trace_.has_value();
}
void TaskTrace::Print() const {
OutputToStream(&std::cerr);
}
void TaskTrace::OutputToStream(std::ostream* os) const {
*os << "Task trace:" << std::endl;
if (!stack_trace_) {
*os << "No active task.";
return;
}
*os << *stack_trace_;
if (trace_overflow_) {
*os << "Task trace buffer limit hit, update "
"PendingTask::kTaskBacktraceLength to increase."
<< std::endl;
}
}
base::span<const void* const> TaskTrace::AddressesForTesting() const {
if (empty())
return {};
size_t count = 0;
const void* const* addresses = stack_trace_->Addresses(&count);
return {addresses, count};
}
std::ostream& operator<<(std::ostream& os, const TaskTrace& task_trace) {
task_trace.OutputToStream(&os);
return os;
}
} // namespace debug
} // namespace base