1 // Copyright 2014 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "base/debug/task_annotator.h" 6 7 #include <array> 8 9 #include "base/debug/activity_tracker.h" 10 #include "base/debug/alias.h" 11 #include "base/pending_task.h" 12 #include "base/trace_event/trace_event.h" 13 #include "base/tracked_objects.h" 14 15 namespace base { 16 namespace debug { 17 18 TaskAnnotator::TaskAnnotator() { 19 } 20 21 TaskAnnotator::~TaskAnnotator() { 22 } 23 24 void TaskAnnotator::DidQueueTask(const char* queue_function, 25 const PendingTask& pending_task) { 26 TRACE_EVENT_WITH_FLOW0(TRACE_DISABLED_BY_DEFAULT("toplevel.flow"), 27 queue_function, 28 TRACE_ID_MANGLE(GetTaskTraceID(pending_task)), 29 TRACE_EVENT_FLAG_FLOW_OUT); 30 } 31 32 void TaskAnnotator::RunTask(const char* queue_function, 33 PendingTask* pending_task) { 34 ScopedTaskRunActivity task_activity(*pending_task); 35 36 tracked_objects::TaskStopwatch stopwatch; 37 stopwatch.Start(); 38 tracked_objects::Duration queue_duration = 39 stopwatch.StartTime() - pending_task->EffectiveTimePosted(); 40 41 TRACE_EVENT_WITH_FLOW1( 42 TRACE_DISABLED_BY_DEFAULT("toplevel.flow"), queue_function, 43 TRACE_ID_MANGLE(GetTaskTraceID(*pending_task)), TRACE_EVENT_FLAG_FLOW_IN, 44 "queue_duration", queue_duration.InMilliseconds()); 45 46 // Before running the task, store the task backtrace with the chain of 47 // PostTasks that resulted in this call and deliberately alias it to ensure 48 // it is on the stack if the task crashes. Be careful not to assume that the 49 // variable itself will have the expected value when displayed by the 50 // optimizer in an optimized build. Look at a memory dump of the stack. 51 static constexpr int kStackTaskTraceSnapshotSize = 52 std::tuple_size<decltype(pending_task->task_backtrace)>::value + 1; 53 std::array<const void*, kStackTaskTraceSnapshotSize> task_backtrace; 54 task_backtrace[0] = pending_task->posted_from.program_counter(); 55 std::copy(pending_task->task_backtrace.begin(), 56 pending_task->task_backtrace.end(), task_backtrace.begin() + 1); 57 debug::Alias(&task_backtrace); 58 59 std::move(pending_task->task).Run(); 60 61 stopwatch.Stop(); 62 tracked_objects::ThreadData::TallyRunOnNamedThreadIfTracking(*pending_task, 63 stopwatch); 64 } 65 66 uint64_t TaskAnnotator::GetTaskTraceID(const PendingTask& task) const { 67 return (static_cast<uint64_t>(task.sequence_num) << 32) | 68 ((static_cast<uint64_t>(reinterpret_cast<intptr_t>(this)) << 32) >> 69 32); 70 } 71 72 } // namespace debug 73 } // namespace base 74