1b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// Copyright (c) 2012 The Chromium Authors. All rights reserved. 2b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// Use of this source code is governed by a BSD-style license that can be 3b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// found in the LICENSE file. 4b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 5b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include "base/tracked_objects.h" 6b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 7b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include <limits.h> 8b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include <stdlib.h> 9b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 10b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include "base/atomicops.h" 11b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include "base/base_switches.h" 12b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include "base/command_line.h" 13b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include "base/compiler_specific.h" 1494ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez#include "base/debug/leak_annotations.h" 15b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include "base/logging.h" 16b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include "base/process/process_handle.h" 17b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include "base/strings/stringprintf.h" 1894ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez#include "base/third_party/valgrind/memcheck.h" 190c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavez#include "base/threading/worker_pool.h" 20b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include "base/tracking_info.h" 210d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko#include "build/build_config.h" 22b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 23b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratusing base::TimeDelta; 24b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 25b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratnamespace base { 26b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratclass TimeDelta; 27b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 28b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 29b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratnamespace tracked_objects { 30b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 31b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratnamespace { 32b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// When ThreadData is first initialized, should we start in an ACTIVE state to 33b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// record all of the startup-time tasks, or should we start up DEACTIVATED, so 34b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// that we only record after parsing the command line flag --enable-tracking. 35b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// Note that the flag may force either state, so this really controls only the 36b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// period of time up until that flag is parsed. If there is no flag seen, then 37b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// this state may prevail for much or all of the process lifetime. 38b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratconst ThreadData::Status kInitialStartupState = ThreadData::PROFILING_ACTIVE; 39b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 40b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// Possible states of the profiler timing enabledness. 41b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratenum { 42b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat UNDEFINED_TIMING, 43b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat ENABLED_TIMING, 44b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat DISABLED_TIMING, 45b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}; 46b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 47b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// State of the profiler timing enabledness. 48b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratbase::subtle::Atomic32 g_profiler_timing_enabled = UNDEFINED_TIMING; 49b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 50b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// Returns whether profiler timing is enabled. The default is true, but this 51b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// may be overridden by a command-line flag. Some platforms may 52b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// programmatically set this command-line flag to the "off" value if it's not 53b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// specified. 54b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// This in turn can be overridden by explicitly calling 55b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// ThreadData::EnableProfilerTiming, say, based on a field trial. 56b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratinline bool IsProfilerTimingEnabled() { 57b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // Reading |g_profiler_timing_enabled| is done without barrier because 58b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // multiple initialization is not an issue while the barrier can be relatively 59b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // costly given that this method is sometimes called in a tight loop. 60b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat base::subtle::Atomic32 current_timing_enabled = 61b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat base::subtle::NoBarrier_Load(&g_profiler_timing_enabled); 62b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat if (current_timing_enabled == UNDEFINED_TIMING) { 63b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat if (!base::CommandLine::InitializedForCurrentProcess()) 64b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return true; 65b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat current_timing_enabled = 66b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat (base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII( 67b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat switches::kProfilerTiming) == 68b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat switches::kProfilerTimingDisabledValue) 69b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat ? DISABLED_TIMING 70b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat : ENABLED_TIMING; 71b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat base::subtle::NoBarrier_Store(&g_profiler_timing_enabled, 72b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat current_timing_enabled); 73b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } 74b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return current_timing_enabled == ENABLED_TIMING; 75b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 76b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 77b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} // namespace 78b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 79b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat//------------------------------------------------------------------------------ 80b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// DeathData tallies durations when a death takes place. 81b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 82b8cf94937c52feb53b55c39e3f82094d27de464cDaniel EratDeathData::DeathData() 83b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat : count_(0), 84b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat sample_probability_count_(0), 85b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat run_duration_sum_(0), 86b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat queue_duration_sum_(0), 87b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat run_duration_max_(0), 88b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat queue_duration_max_(0), 89b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat run_duration_sample_(0), 90b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat queue_duration_sample_(0), 91b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat last_phase_snapshot_(nullptr) { 92b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 93b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 94b8cf94937c52feb53b55c39e3f82094d27de464cDaniel EratDeathData::DeathData(const DeathData& other) 95b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat : count_(other.count_), 96b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat sample_probability_count_(other.sample_probability_count_), 97b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat run_duration_sum_(other.run_duration_sum_), 98b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat queue_duration_sum_(other.queue_duration_sum_), 99b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat run_duration_max_(other.run_duration_max_), 100b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat queue_duration_max_(other.queue_duration_max_), 101b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat run_duration_sample_(other.run_duration_sample_), 102b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat queue_duration_sample_(other.queue_duration_sample_), 103b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat last_phase_snapshot_(nullptr) { 104b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // This constructor will be used by std::map when adding new DeathData values 105b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // to the map. At that point, last_phase_snapshot_ is still NULL, so we don't 106b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // need to worry about ownership transfer. 107b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat DCHECK(other.last_phase_snapshot_ == nullptr); 108b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 109b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 110b8cf94937c52feb53b55c39e3f82094d27de464cDaniel EratDeathData::~DeathData() { 111b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat while (last_phase_snapshot_) { 112b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat const DeathDataPhaseSnapshot* snapshot = last_phase_snapshot_; 113b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat last_phase_snapshot_ = snapshot->prev; 114b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat delete snapshot; 115b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } 116b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 117b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 118b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// TODO(jar): I need to see if this macro to optimize branching is worth using. 119b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// 120b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// This macro has no branching, so it is surely fast, and is equivalent to: 121b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// if (assign_it) 122b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// target = source; 123b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// We use a macro rather than a template to force this to inline. 124b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// Related code for calculating max is discussed on the web. 125b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#define CONDITIONAL_ASSIGN(assign_it, target, source) \ 1260d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko ((target) ^= ((target) ^ (source)) & -static_cast<int32_t>(assign_it)) 127b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 1280d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenkovoid DeathData::RecordDeath(const int32_t queue_duration, 1290d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko const int32_t run_duration, 1300d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko const uint32_t random_number) { 131b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // We'll just clamp at INT_MAX, but we should note this in the UI as such. 132b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat if (count_ < INT_MAX) 1330d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko base::subtle::NoBarrier_Store(&count_, count_ + 1); 134b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 1350d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko int sample_probability_count = 1360d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko base::subtle::NoBarrier_Load(&sample_probability_count_); 137b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat if (sample_probability_count < INT_MAX) 138b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat ++sample_probability_count; 1390d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko base::subtle::NoBarrier_Store(&sample_probability_count_, 1400d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko sample_probability_count); 141b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 1420d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko base::subtle::NoBarrier_Store(&queue_duration_sum_, 1430d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko queue_duration_sum_ + queue_duration); 1440d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko base::subtle::NoBarrier_Store(&run_duration_sum_, 1450d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko run_duration_sum_ + run_duration); 146b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 1470d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko if (queue_duration_max() < queue_duration) 1480d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko base::subtle::NoBarrier_Store(&queue_duration_max_, queue_duration); 1490d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko if (run_duration_max() < run_duration) 1500d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko base::subtle::NoBarrier_Store(&run_duration_max_, run_duration); 151b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 152b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // Take a uniformly distributed sample over all durations ever supplied during 153b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // the current profiling phase. 154b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // The probability that we (instead) use this new sample is 155b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // 1/sample_probability_count_. This results in a completely uniform selection 156b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // of the sample (at least when we don't clamp sample_probability_count_... 157b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // but that should be inconsequentially likely). We ignore the fact that we 158b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // correlated our selection of a sample to the run and queue times (i.e., we 159b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // used them to generate random_number). 160b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat CHECK_GT(sample_probability_count, 0); 161b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat if (0 == (random_number % sample_probability_count)) { 1620d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko base::subtle::NoBarrier_Store(&queue_duration_sample_, queue_duration); 1630d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko base::subtle::NoBarrier_Store(&run_duration_sample_, run_duration); 164b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } 165b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 166b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 167b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratvoid DeathData::OnProfilingPhaseCompleted(int profiling_phase) { 168b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // Snapshotting and storing current state. 169b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat last_phase_snapshot_ = new DeathDataPhaseSnapshot( 1700d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko profiling_phase, count(), run_duration_sum(), run_duration_max(), 1710d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko run_duration_sample(), queue_duration_sum(), queue_duration_max(), 1720d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko queue_duration_sample(), last_phase_snapshot_); 173b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 174b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // Not touching fields for which a delta can be computed by comparing with a 175b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // snapshot from the previous phase. Resetting other fields. Sample values 176b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // will be reset upon next death recording because sample_probability_count_ 177b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // is set to 0. 178b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // We avoid resetting to 0 in favor of deltas whenever possible. The reason 179b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // is that for incrementable fields, resetting to 0 from the snapshot thread 180b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // potentially in parallel with incrementing in the death thread may result in 181b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // significant data corruption that has a potential to grow with time. Not 182b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // resetting incrementable fields and using deltas will cause any 183b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // off-by-little corruptions to be likely fixed at the next snapshot. 184b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // The max values are not incrementable, and cannot be deduced using deltas 185b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // for a given phase. Hence, we have to reset them to 0. But the potential 186b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // damage is limited to getting the previous phase's max to apply for the next 187b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // phase, and the error doesn't have a potential to keep growing with new 188b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // resets. 189b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // sample_probability_count_ is incrementable, but must be reset to 0 at the 190b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // phase end, so that we start a new uniformly randomized sample selection 1910d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko // after the reset. These fields are updated using atomics. However, race 1920d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko // conditions are possible since these are updated individually and not 1930d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko // together atomically, resulting in the values being mutually inconsistent. 1940d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko // The damage is limited to selecting a wrong sample, which is not something 1950d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko // that can cause accumulating or cascading effects. 1960d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko // If there were no inconsistencies caused by race conditions, we never send a 197b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // sample for the previous phase in the next phase's snapshot because 198b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // ThreadData::SnapshotExecutedTasks doesn't send deltas with 0 count. 1990d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko base::subtle::NoBarrier_Store(&sample_probability_count_, 0); 2000d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko base::subtle::NoBarrier_Store(&run_duration_max_, 0); 2010d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko base::subtle::NoBarrier_Store(&queue_duration_max_, 0); 202b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 203b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 204b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat//------------------------------------------------------------------------------ 205b8cf94937c52feb53b55c39e3f82094d27de464cDaniel EratDeathDataSnapshot::DeathDataSnapshot() 206b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat : count(-1), 207b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat run_duration_sum(-1), 208b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat run_duration_max(-1), 209b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat run_duration_sample(-1), 210b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat queue_duration_sum(-1), 211b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat queue_duration_max(-1), 212b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat queue_duration_sample(-1) { 213b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 214b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 215b8cf94937c52feb53b55c39e3f82094d27de464cDaniel EratDeathDataSnapshot::DeathDataSnapshot(int count, 2160d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko int32_t run_duration_sum, 2170d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko int32_t run_duration_max, 2180d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko int32_t run_duration_sample, 2190d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko int32_t queue_duration_sum, 2200d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko int32_t queue_duration_max, 2210d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko int32_t queue_duration_sample) 222b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat : count(count), 223b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat run_duration_sum(run_duration_sum), 224b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat run_duration_max(run_duration_max), 225b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat run_duration_sample(run_duration_sample), 226b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat queue_duration_sum(queue_duration_sum), 227b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat queue_duration_max(queue_duration_max), 2280d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko queue_duration_sample(queue_duration_sample) {} 229b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 230b8cf94937c52feb53b55c39e3f82094d27de464cDaniel EratDeathDataSnapshot::~DeathDataSnapshot() { 231b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 232b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 233b8cf94937c52feb53b55c39e3f82094d27de464cDaniel EratDeathDataSnapshot DeathDataSnapshot::Delta( 234b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat const DeathDataSnapshot& older) const { 235b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return DeathDataSnapshot(count - older.count, 236b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat run_duration_sum - older.run_duration_sum, 237b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat run_duration_max, run_duration_sample, 238b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat queue_duration_sum - older.queue_duration_sum, 239b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat queue_duration_max, queue_duration_sample); 240b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 241b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 242b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat//------------------------------------------------------------------------------ 243b8cf94937c52feb53b55c39e3f82094d27de464cDaniel EratBirthOnThread::BirthOnThread(const Location& location, 244b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat const ThreadData& current) 245b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat : location_(location), 246b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat birth_thread_(¤t) { 247b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 248b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 249b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat//------------------------------------------------------------------------------ 250b8cf94937c52feb53b55c39e3f82094d27de464cDaniel EratBirthOnThreadSnapshot::BirthOnThreadSnapshot() { 251b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 252b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 253b8cf94937c52feb53b55c39e3f82094d27de464cDaniel EratBirthOnThreadSnapshot::BirthOnThreadSnapshot(const BirthOnThread& birth) 254b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat : location(birth.location()), 255b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat thread_name(birth.birth_thread()->thread_name()) { 256b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 257b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 258b8cf94937c52feb53b55c39e3f82094d27de464cDaniel EratBirthOnThreadSnapshot::~BirthOnThreadSnapshot() { 259b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 260b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 261b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat//------------------------------------------------------------------------------ 262b8cf94937c52feb53b55c39e3f82094d27de464cDaniel EratBirths::Births(const Location& location, const ThreadData& current) 263b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat : BirthOnThread(location, current), 264b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat birth_count_(1) { } 265b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 266b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratint Births::birth_count() const { return birth_count_; } 267b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 268b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratvoid Births::RecordBirth() { ++birth_count_; } 269b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 270b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat//------------------------------------------------------------------------------ 271b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// ThreadData maintains the central data for all births and deaths on a single 272b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// thread. 273b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 274b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// TODO(jar): We should pull all these static vars together, into a struct, and 275b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// optimize layout so that we benefit from locality of reference during accesses 276b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// to them. 277b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 278b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// static 27945779228f8c9e40851cfd23f727e2bd8ffdd4714Alex VakulenkoThreadData::NowFunction* ThreadData::now_function_for_testing_ = NULL; 280b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 281b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// A TLS slot which points to the ThreadData instance for the current thread. 282b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// We do a fake initialization here (zeroing out data), and then the real 283b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// in-place construction happens when we call tls_index_.Initialize(). 284b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// static 285b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratbase::ThreadLocalStorage::StaticSlot ThreadData::tls_index_ = TLS_INITIALIZER; 286b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 287b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// static 288b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratint ThreadData::worker_thread_data_creation_count_ = 0; 289b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 290b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// static 291b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratint ThreadData::cleanup_count_ = 0; 292b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 293b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// static 294b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratint ThreadData::incarnation_counter_ = 0; 295b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 296b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// static 297b8cf94937c52feb53b55c39e3f82094d27de464cDaniel EratThreadData* ThreadData::all_thread_data_list_head_ = NULL; 298b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 299b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// static 300b8cf94937c52feb53b55c39e3f82094d27de464cDaniel EratThreadData* ThreadData::first_retired_worker_ = NULL; 301b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 302b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// static 303b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratbase::LazyInstance<base::Lock>::Leaky 304b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat ThreadData::list_lock_ = LAZY_INSTANCE_INITIALIZER; 305b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 306b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// static 3070d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenkobase::subtle::Atomic32 ThreadData::status_ = ThreadData::UNINITIALIZED; 308b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 309b8cf94937c52feb53b55c39e3f82094d27de464cDaniel EratThreadData::ThreadData(const std::string& suggested_name) 310b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat : next_(NULL), 311b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat next_retired_worker_(NULL), 312b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat worker_thread_number_(0), 313b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat incarnation_count_for_pool_(-1), 314b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat current_stopwatch_(NULL) { 315b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat DCHECK_GE(suggested_name.size(), 0u); 316b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat thread_name_ = suggested_name; 317b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat PushToHeadOfList(); // Which sets real incarnation_count_for_pool_. 318b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 319b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 320b8cf94937c52feb53b55c39e3f82094d27de464cDaniel EratThreadData::ThreadData(int thread_number) 321b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat : next_(NULL), 322b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat next_retired_worker_(NULL), 323b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat worker_thread_number_(thread_number), 324b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat incarnation_count_for_pool_(-1), 325b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat current_stopwatch_(NULL) { 326b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat CHECK_GT(thread_number, 0); 327b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat base::StringAppendF(&thread_name_, "WorkerThread-%d", thread_number); 328b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat PushToHeadOfList(); // Which sets real incarnation_count_for_pool_. 329b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 330b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 331b8cf94937c52feb53b55c39e3f82094d27de464cDaniel EratThreadData::~ThreadData() { 332b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 333b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 334b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratvoid ThreadData::PushToHeadOfList() { 335b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // Toss in a hint of randomness (atop the uniniitalized value). 336b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat (void)VALGRIND_MAKE_MEM_DEFINED_IF_ADDRESSABLE(&random_number_, 337b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat sizeof(random_number_)); 338b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat MSAN_UNPOISON(&random_number_, sizeof(random_number_)); 3390d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko random_number_ += static_cast<uint32_t>(this - static_cast<ThreadData*>(0)); 340b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat random_number_ ^= (Now() - TrackedTime()).InMilliseconds(); 341b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 342b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat DCHECK(!next_); 343b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat base::AutoLock lock(*list_lock_.Pointer()); 344b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat incarnation_count_for_pool_ = incarnation_counter_; 345b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat next_ = all_thread_data_list_head_; 346b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat all_thread_data_list_head_ = this; 347b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 348b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 349b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// static 350b8cf94937c52feb53b55c39e3f82094d27de464cDaniel EratThreadData* ThreadData::first() { 351b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat base::AutoLock lock(*list_lock_.Pointer()); 352b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return all_thread_data_list_head_; 353b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 354b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 355b8cf94937c52feb53b55c39e3f82094d27de464cDaniel EratThreadData* ThreadData::next() const { return next_; } 356b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 357b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// static 358b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratvoid ThreadData::InitializeThreadContext(const std::string& suggested_name) { 3590c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavez if (base::WorkerPool::RunsTasksOnCurrentThread()) 3600c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavez return; 3610c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavez EnsureTlsInitialization(); 362b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat ThreadData* current_thread_data = 363b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat reinterpret_cast<ThreadData*>(tls_index_.Get()); 364b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat if (current_thread_data) 365b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return; // Browser tests instigate this. 366b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat current_thread_data = new ThreadData(suggested_name); 367b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat tls_index_.Set(current_thread_data); 368b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 369b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 370b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// static 371b8cf94937c52feb53b55c39e3f82094d27de464cDaniel EratThreadData* ThreadData::Get() { 372b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat if (!tls_index_.initialized()) 373b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return NULL; // For unittests only. 374b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat ThreadData* registered = reinterpret_cast<ThreadData*>(tls_index_.Get()); 375b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat if (registered) 376b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return registered; 377b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 378b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // We must be a worker thread, since we didn't pre-register. 379b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat ThreadData* worker_thread_data = NULL; 380b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat int worker_thread_number = 0; 381b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat { 382b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat base::AutoLock lock(*list_lock_.Pointer()); 383b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat if (first_retired_worker_) { 384b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat worker_thread_data = first_retired_worker_; 385b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat first_retired_worker_ = first_retired_worker_->next_retired_worker_; 386b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat worker_thread_data->next_retired_worker_ = NULL; 387b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } else { 388b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat worker_thread_number = ++worker_thread_data_creation_count_; 389b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } 390b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } 391b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 392b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // If we can't find a previously used instance, then we have to create one. 393b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat if (!worker_thread_data) { 394b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat DCHECK_GT(worker_thread_number, 0); 395b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat worker_thread_data = new ThreadData(worker_thread_number); 396b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } 397b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat DCHECK_GT(worker_thread_data->worker_thread_number_, 0); 398b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 399b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat tls_index_.Set(worker_thread_data); 400b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return worker_thread_data; 401b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 402b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 403b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// static 404b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratvoid ThreadData::OnThreadTermination(void* thread_data) { 405b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat DCHECK(thread_data); // TLS should *never* call us with a NULL. 406b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // We must NOT do any allocations during this callback. There is a chance 407b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // that the allocator is no longer active on this thread. 408b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat reinterpret_cast<ThreadData*>(thread_data)->OnThreadTerminationCleanup(); 409b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 410b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 411b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratvoid ThreadData::OnThreadTerminationCleanup() { 412b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // The list_lock_ was created when we registered the callback, so it won't be 413b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // allocated here despite the lazy reference. 414b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat base::AutoLock lock(*list_lock_.Pointer()); 415b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat if (incarnation_counter_ != incarnation_count_for_pool_) 416b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return; // ThreadData was constructed in an earlier unit test. 417b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat ++cleanup_count_; 418b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // Only worker threads need to be retired and reused. 419b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat if (!worker_thread_number_) { 420b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return; 421b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } 422b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // We must NOT do any allocations during this callback. 423b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // Using the simple linked lists avoids all allocations. 424b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat DCHECK_EQ(this->next_retired_worker_, reinterpret_cast<ThreadData*>(NULL)); 425b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat this->next_retired_worker_ = first_retired_worker_; 426b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat first_retired_worker_ = this; 427b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 428b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 429b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// static 430b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratvoid ThreadData::Snapshot(int current_profiling_phase, 431b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat ProcessDataSnapshot* process_data_snapshot) { 432b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // Get an unchanging copy of a ThreadData list. 433b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat ThreadData* my_list = ThreadData::first(); 434b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 435b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // Gather data serially. 436b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // This hackish approach *can* get some slightly corrupt tallies, as we are 437b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // grabbing values without the protection of a lock, but it has the advantage 438b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // of working even with threads that don't have message loops. If a user 439b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // sees any strangeness, they can always just run their stats gathering a 440b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // second time. 441b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat BirthCountMap birth_counts; 442b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat for (ThreadData* thread_data = my_list; thread_data; 443b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat thread_data = thread_data->next()) { 444b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat thread_data->SnapshotExecutedTasks(current_profiling_phase, 445b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat &process_data_snapshot->phased_snapshots, 446b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat &birth_counts); 447b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } 448b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 449b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // Add births that are still active -- i.e. objects that have tallied a birth, 450b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // but have not yet tallied a matching death, and hence must be either 451b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // running, queued up, or being held in limbo for future posting. 452b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat auto* current_phase_tasks = 453b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat &process_data_snapshot->phased_snapshots[current_profiling_phase].tasks; 454b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat for (const auto& birth_count : birth_counts) { 455b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat if (birth_count.second > 0) { 456b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat current_phase_tasks->push_back( 457b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat TaskSnapshot(BirthOnThreadSnapshot(*birth_count.first), 458b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat DeathDataSnapshot(birth_count.second, 0, 0, 0, 0, 0, 0), 459b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat "Still_Alive")); 460b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } 461b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } 462b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 463b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 464b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// static 465b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratvoid ThreadData::OnProfilingPhaseCompleted(int profiling_phase) { 466b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // Get an unchanging copy of a ThreadData list. 467b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat ThreadData* my_list = ThreadData::first(); 468b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 469b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // Add snapshots for all instances of death data in all threads serially. 470b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // This hackish approach *can* get some slightly corrupt tallies, as we are 471b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // grabbing values without the protection of a lock, but it has the advantage 472b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // of working even with threads that don't have message loops. Any corruption 473b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // shouldn't cause "cascading damage" to anything else (in later phases). 474b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat for (ThreadData* thread_data = my_list; thread_data; 475b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat thread_data = thread_data->next()) { 476b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat thread_data->OnProfilingPhaseCompletedOnThread(profiling_phase); 477b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } 478b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 479b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 480b8cf94937c52feb53b55c39e3f82094d27de464cDaniel EratBirths* ThreadData::TallyABirth(const Location& location) { 481b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat BirthMap::iterator it = birth_map_.find(location); 482b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat Births* child; 483b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat if (it != birth_map_.end()) { 484b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat child = it->second; 485b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat child->RecordBirth(); 486b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } else { 487b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat child = new Births(location, *this); // Leak this. 488b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // Lock since the map may get relocated now, and other threads sometimes 489b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // snapshot it (but they lock before copying it). 490b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat base::AutoLock lock(map_lock_); 491b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat birth_map_[location] = child; 492b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } 493b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 494b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return child; 495b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 496b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 497b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratvoid ThreadData::TallyADeath(const Births& births, 4980d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko int32_t queue_duration, 499b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat const TaskStopwatch& stopwatch) { 5000d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko int32_t run_duration = stopwatch.RunDurationMs(); 501b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 502b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // Stir in some randomness, plus add constant in case durations are zero. 5030d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko const uint32_t kSomePrimeNumber = 2147483647; 504b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat random_number_ += queue_duration + run_duration + kSomePrimeNumber; 505b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // An address is going to have some randomness to it as well ;-). 5060d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko random_number_ ^= 5070d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko static_cast<uint32_t>(&births - reinterpret_cast<Births*>(0)); 508b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 509b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat DeathMap::iterator it = death_map_.find(&births); 510b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat DeathData* death_data; 511b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat if (it != death_map_.end()) { 512b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat death_data = &it->second; 513b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } else { 514b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat base::AutoLock lock(map_lock_); // Lock as the map may get relocated now. 515b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat death_data = &death_map_[&births]; 516b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } // Release lock ASAP. 517b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat death_data->RecordDeath(queue_duration, run_duration, random_number_); 518b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 519b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 520b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// static 521b8cf94937c52feb53b55c39e3f82094d27de464cDaniel EratBirths* ThreadData::TallyABirthIfActive(const Location& location) { 522b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat if (!TrackingStatus()) 523b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return NULL; 524b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat ThreadData* current_thread_data = Get(); 525b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat if (!current_thread_data) 526b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return NULL; 527b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return current_thread_data->TallyABirth(location); 528b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 529b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 530b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// static 531b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratvoid ThreadData::TallyRunOnNamedThreadIfTracking( 532b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat const base::TrackingInfo& completed_task, 533b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat const TaskStopwatch& stopwatch) { 534b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // Even if we have been DEACTIVATED, we will process any pending births so 535b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // that our data structures (which counted the outstanding births) remain 536b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // consistent. 537b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat const Births* births = completed_task.birth_tally; 538b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat if (!births) 539b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return; 540b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat ThreadData* current_thread_data = stopwatch.GetThreadData(); 541b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat if (!current_thread_data) 542b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return; 543b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 544b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // Watch out for a race where status_ is changing, and hence one or both 545b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // of start_of_run or end_of_run is zero. In that case, we didn't bother to 546b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // get a time value since we "weren't tracking" and we were trying to be 547b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // efficient by not calling for a genuine time value. For simplicity, we'll 548b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // use a default zero duration when we can't calculate a true value. 549b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat TrackedTime start_of_run = stopwatch.StartTime(); 5500d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko int32_t queue_duration = 0; 551b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat if (!start_of_run.is_null()) { 552b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat queue_duration = (start_of_run - completed_task.EffectiveTimePosted()) 553b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat .InMilliseconds(); 554b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } 555b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat current_thread_data->TallyADeath(*births, queue_duration, stopwatch); 556b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 557b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 558b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// static 559b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratvoid ThreadData::TallyRunOnWorkerThreadIfTracking( 560b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat const Births* births, 561b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat const TrackedTime& time_posted, 562b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat const TaskStopwatch& stopwatch) { 563b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // Even if we have been DEACTIVATED, we will process any pending births so 564b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // that our data structures (which counted the outstanding births) remain 565b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // consistent. 566b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat if (!births) 567b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return; 568b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 569b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // TODO(jar): Support the option to coalesce all worker-thread activity under 570b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // one ThreadData instance that uses locks to protect *all* access. This will 571b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // reduce memory (making it provably bounded), but run incrementally slower 572b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // (since we'll use locks on TallyABirth and TallyADeath). The good news is 573b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // that the locks on TallyADeath will be *after* the worker thread has run, 574b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // and hence nothing will be waiting for the completion (... besides some 575b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // other thread that might like to run). Also, the worker threads tasks are 576b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // generally longer, and hence the cost of the lock may perchance be amortized 577b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // over the long task's lifetime. 578b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat ThreadData* current_thread_data = stopwatch.GetThreadData(); 579b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat if (!current_thread_data) 580b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return; 581b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 582b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat TrackedTime start_of_run = stopwatch.StartTime(); 5830d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko int32_t queue_duration = 0; 584b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat if (!start_of_run.is_null()) { 585b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat queue_duration = (start_of_run - time_posted).InMilliseconds(); 586b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } 587b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat current_thread_data->TallyADeath(*births, queue_duration, stopwatch); 588b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 589b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 590b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// static 591b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratvoid ThreadData::TallyRunInAScopedRegionIfTracking( 592b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat const Births* births, 593b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat const TaskStopwatch& stopwatch) { 594b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // Even if we have been DEACTIVATED, we will process any pending births so 595b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // that our data structures (which counted the outstanding births) remain 596b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // consistent. 597b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat if (!births) 598b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return; 599b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 600b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat ThreadData* current_thread_data = stopwatch.GetThreadData(); 601b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat if (!current_thread_data) 602b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return; 603b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 6040d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko int32_t queue_duration = 0; 605b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat current_thread_data->TallyADeath(*births, queue_duration, stopwatch); 606b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 607b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 608b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratvoid ThreadData::SnapshotExecutedTasks( 609b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat int current_profiling_phase, 610b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat PhasedProcessDataSnapshotMap* phased_snapshots, 611b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat BirthCountMap* birth_counts) { 612b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // Get copy of data, so that the data will not change during the iterations 613b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // and processing. 614b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat BirthMap birth_map; 615b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat DeathsSnapshot deaths; 616b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat SnapshotMaps(current_profiling_phase, &birth_map, &deaths); 617b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 618b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat for (const auto& birth : birth_map) { 619b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat (*birth_counts)[birth.second] += birth.second->birth_count(); 620b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } 621b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 622b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat for (const auto& death : deaths) { 623b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat (*birth_counts)[death.first] -= death.first->birth_count(); 624b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 625b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // For the current death data, walk through all its snapshots, starting from 626b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // the current one, then from the previous profiling phase etc., and for 627b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // each snapshot calculate the delta between the snapshot and the previous 628b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // phase, if any. Store the deltas in the result. 629b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat for (const DeathDataPhaseSnapshot* phase = &death.second; phase; 630b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat phase = phase->prev) { 631b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat const DeathDataSnapshot& death_data = 632b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat phase->prev ? phase->death_data.Delta(phase->prev->death_data) 633b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat : phase->death_data; 634b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 635b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat if (death_data.count > 0) { 636b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat (*phased_snapshots)[phase->profiling_phase].tasks.push_back( 637b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat TaskSnapshot(BirthOnThreadSnapshot(*death.first), death_data, 638b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat thread_name())); 639b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } 640b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } 641b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } 642b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 643b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 644b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// This may be called from another thread. 645b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratvoid ThreadData::SnapshotMaps(int profiling_phase, 646b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat BirthMap* birth_map, 647b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat DeathsSnapshot* deaths) { 648b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat base::AutoLock lock(map_lock_); 649b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 650b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat for (const auto& birth : birth_map_) 651b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat (*birth_map)[birth.first] = birth.second; 652b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 653b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat for (const auto& death : death_map_) { 654b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat deaths->push_back(std::make_pair( 655b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat death.first, 656b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat DeathDataPhaseSnapshot(profiling_phase, death.second.count(), 657b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat death.second.run_duration_sum(), 658b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat death.second.run_duration_max(), 659b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat death.second.run_duration_sample(), 660b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat death.second.queue_duration_sum(), 661b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat death.second.queue_duration_max(), 662b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat death.second.queue_duration_sample(), 663b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat death.second.last_phase_snapshot()))); 664b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } 665b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 666b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 667b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratvoid ThreadData::OnProfilingPhaseCompletedOnThread(int profiling_phase) { 668b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat base::AutoLock lock(map_lock_); 669b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 670b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat for (auto& death : death_map_) { 671b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat death.second.OnProfilingPhaseCompleted(profiling_phase); 672b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } 673b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 674b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 6750c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavezvoid ThreadData::EnsureTlsInitialization() { 6760d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko if (base::subtle::Acquire_Load(&status_) >= DEACTIVATED) 677b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return; // Someone else did the initialization. 678b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // Due to racy lazy initialization in tests, we'll need to recheck status_ 679b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // after we acquire the lock. 680b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 681b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // Ensure that we don't double initialize tls. We are called when single 682b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // threaded in the product, but some tests may be racy and lazy about our 683b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // initialization. 684b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat base::AutoLock lock(*list_lock_.Pointer()); 6850d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko if (base::subtle::Acquire_Load(&status_) >= DEACTIVATED) 686b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return; // Someone raced in here and beat us. 687b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 688b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // Perform the "real" TLS initialization now, and leave it intact through 689b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // process termination. 690b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat if (!tls_index_.initialized()) { // Testing may have initialized this. 6910d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko DCHECK_EQ(base::subtle::NoBarrier_Load(&status_), UNINITIALIZED); 692b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat tls_index_.Initialize(&ThreadData::OnThreadTermination); 693b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat DCHECK(tls_index_.initialized()); 694b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } else { 695b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // TLS was initialzed for us earlier. 6960d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko DCHECK_EQ(base::subtle::NoBarrier_Load(&status_), DORMANT_DURING_TESTS); 697b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } 698b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 699b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // Incarnation counter is only significant to testing, as it otherwise will 700b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // never again change in this process. 701b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat ++incarnation_counter_; 702b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 703b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // The lock is not critical for setting status_, but it doesn't hurt. It also 704b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // ensures that if we have a racy initialization, that we'll bail as soon as 705b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // we get the lock earlier in this method. 7060d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko base::subtle::Release_Store(&status_, kInitialStartupState); 7070d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko DCHECK(base::subtle::NoBarrier_Load(&status_) != UNINITIALIZED); 708b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 709b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 710b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// static 711b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratvoid ThreadData::InitializeAndSetTrackingStatus(Status status) { 712b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat DCHECK_GE(status, DEACTIVATED); 713b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat DCHECK_LE(status, PROFILING_ACTIVE); 714b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 7150c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavez EnsureTlsInitialization(); // No-op if already initialized. 716b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 717b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat if (status > DEACTIVATED) 718b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat status = PROFILING_ACTIVE; 7190d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko base::subtle::Release_Store(&status_, status); 720b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 721b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 722b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// static 723b8cf94937c52feb53b55c39e3f82094d27de464cDaniel EratThreadData::Status ThreadData::status() { 7240d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko return static_cast<ThreadData::Status>(base::subtle::Acquire_Load(&status_)); 725b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 726b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 727b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// static 728b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratbool ThreadData::TrackingStatus() { 7290d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko return base::subtle::Acquire_Load(&status_) > DEACTIVATED; 730b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 731b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 732b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// static 733b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratvoid ThreadData::EnableProfilerTiming() { 734b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat base::subtle::NoBarrier_Store(&g_profiler_timing_enabled, ENABLED_TIMING); 735b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 736b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 737b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// static 738b8cf94937c52feb53b55c39e3f82094d27de464cDaniel EratTrackedTime ThreadData::Now() { 73945779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko if (now_function_for_testing_) 74045779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko return TrackedTime::FromMilliseconds((*now_function_for_testing_)()); 741b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat if (IsProfilerTimingEnabled() && TrackingStatus()) 742b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return TrackedTime::Now(); 743b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return TrackedTime(); // Super fast when disabled, or not compiled. 744b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 745b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 746b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// static 74794ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavezvoid ThreadData::EnsureCleanupWasCalled(int /*major_threads_shutdown_count*/) { 748b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat base::AutoLock lock(*list_lock_.Pointer()); 749b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat if (worker_thread_data_creation_count_ == 0) 750b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return; // We haven't really run much, and couldn't have leaked. 751b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 752b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // TODO(jar): until this is working on XP, don't run the real test. 753b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#if 0 754b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // Verify that we've at least shutdown/cleanup the major namesd threads. The 755b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // caller should tell us how many thread shutdowns should have taken place by 756b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // now. 757b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat CHECK_GT(cleanup_count_, major_threads_shutdown_count); 758b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#endif 759b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 760b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 761b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// static 762b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratvoid ThreadData::ShutdownSingleThreadedCleanup(bool leak) { 763b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // This is only called from test code, where we need to cleanup so that 764b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // additional tests can be run. 765b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // We must be single threaded... but be careful anyway. 766b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat InitializeAndSetTrackingStatus(DEACTIVATED); 767b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 768b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat ThreadData* thread_data_list; 769b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat { 770b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat base::AutoLock lock(*list_lock_.Pointer()); 771b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat thread_data_list = all_thread_data_list_head_; 772b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat all_thread_data_list_head_ = NULL; 773b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat ++incarnation_counter_; 774b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // To be clean, break apart the retired worker list (though we leak them). 775b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat while (first_retired_worker_) { 776b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat ThreadData* worker = first_retired_worker_; 777b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat CHECK_GT(worker->worker_thread_number_, 0); 778b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat first_retired_worker_ = worker->next_retired_worker_; 779b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat worker->next_retired_worker_ = NULL; 780b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } 781b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } 782b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 783b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // Put most global static back in pristine shape. 784b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat worker_thread_data_creation_count_ = 0; 785b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat cleanup_count_ = 0; 786b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat tls_index_.Set(NULL); 7870d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko // Almost UNINITIALIZED. 7880d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko base::subtle::Release_Store(&status_, DORMANT_DURING_TESTS); 789b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 790b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // To avoid any chance of racing in unit tests, which is the only place we 791b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // call this function, we may sometimes leak all the data structures we 792b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // recovered, as they may still be in use on threads from prior tests! 793b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat if (leak) { 794b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat ThreadData* thread_data = thread_data_list; 795b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat while (thread_data) { 79694ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez ANNOTATE_LEAKING_OBJECT_PTR(thread_data); 797b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat thread_data = thread_data->next(); 798b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } 799b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return; 800b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } 801b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 802b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // When we want to cleanup (on a single thread), here is what we do. 803b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 804b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // Do actual recursive delete in all ThreadData instances. 805b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat while (thread_data_list) { 806b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat ThreadData* next_thread_data = thread_data_list; 807b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat thread_data_list = thread_data_list->next(); 808b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 809b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat for (BirthMap::iterator it = next_thread_data->birth_map_.begin(); 810b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat next_thread_data->birth_map_.end() != it; ++it) 811b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat delete it->second; // Delete the Birth Records. 812b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat delete next_thread_data; // Includes all Death Records. 813b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } 814b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 815b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 816b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat//------------------------------------------------------------------------------ 817b8cf94937c52feb53b55c39e3f82094d27de464cDaniel EratTaskStopwatch::TaskStopwatch() 818b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat : wallclock_duration_ms_(0), 819b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat current_thread_data_(NULL), 820b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat excluded_duration_ms_(0), 821b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat parent_(NULL) { 822b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#if DCHECK_IS_ON() 823b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat state_ = CREATED; 824b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat child_ = NULL; 825b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#endif 826b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 827b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 828b8cf94937c52feb53b55c39e3f82094d27de464cDaniel EratTaskStopwatch::~TaskStopwatch() { 829b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#if DCHECK_IS_ON() 830b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat DCHECK(state_ != RUNNING); 831b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat DCHECK(child_ == NULL); 832b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#endif 833b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 834b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 835b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratvoid TaskStopwatch::Start() { 836b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#if DCHECK_IS_ON() 837b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat DCHECK(state_ == CREATED); 838b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat state_ = RUNNING; 839b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#endif 840b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 841b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat start_time_ = ThreadData::Now(); 842b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 843b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat current_thread_data_ = ThreadData::Get(); 844b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat if (!current_thread_data_) 845b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return; 846b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 847b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat parent_ = current_thread_data_->current_stopwatch_; 848b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#if DCHECK_IS_ON() 849b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat if (parent_) { 850b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat DCHECK(parent_->state_ == RUNNING); 851b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat DCHECK(parent_->child_ == NULL); 852b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat parent_->child_ = this; 853b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } 854b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#endif 855b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat current_thread_data_->current_stopwatch_ = this; 856b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 857b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 858b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratvoid TaskStopwatch::Stop() { 859b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat const TrackedTime end_time = ThreadData::Now(); 860b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#if DCHECK_IS_ON() 861b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat DCHECK(state_ == RUNNING); 862b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat state_ = STOPPED; 863b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat DCHECK(child_ == NULL); 864b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#endif 865b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 866b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat if (!start_time_.is_null() && !end_time.is_null()) { 867b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat wallclock_duration_ms_ = (end_time - start_time_).InMilliseconds(); 868b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } 869b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 870b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat if (!current_thread_data_) 871b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return; 872b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 873b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat DCHECK(current_thread_data_->current_stopwatch_ == this); 874b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat current_thread_data_->current_stopwatch_ = parent_; 875b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat if (!parent_) 876b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return; 877b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 878b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#if DCHECK_IS_ON() 879b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat DCHECK(parent_->state_ == RUNNING); 880b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat DCHECK(parent_->child_ == this); 881b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat parent_->child_ = NULL; 882b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#endif 883b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat parent_->excluded_duration_ms_ += wallclock_duration_ms_; 884b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat parent_ = NULL; 885b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 886b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 887b8cf94937c52feb53b55c39e3f82094d27de464cDaniel EratTrackedTime TaskStopwatch::StartTime() const { 888b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#if DCHECK_IS_ON() 889b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat DCHECK(state_ != CREATED); 890b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#endif 891b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 892b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return start_time_; 893b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 894b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 8950d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenkoint32_t TaskStopwatch::RunDurationMs() const { 896b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#if DCHECK_IS_ON() 897b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat DCHECK(state_ == STOPPED); 898b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#endif 899b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 900b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return wallclock_duration_ms_ - excluded_duration_ms_; 901b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 902b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 903b8cf94937c52feb53b55c39e3f82094d27de464cDaniel EratThreadData* TaskStopwatch::GetThreadData() const { 904b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#if DCHECK_IS_ON() 905b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat DCHECK(state_ != CREATED); 906b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#endif 907b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 908b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return current_thread_data_; 909b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 910b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 911b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat//------------------------------------------------------------------------------ 912b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// DeathDataPhaseSnapshot 913b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 914b8cf94937c52feb53b55c39e3f82094d27de464cDaniel EratDeathDataPhaseSnapshot::DeathDataPhaseSnapshot( 915b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat int profiling_phase, 916b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat int count, 9170d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko int32_t run_duration_sum, 9180d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko int32_t run_duration_max, 9190d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko int32_t run_duration_sample, 9200d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko int32_t queue_duration_sum, 9210d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko int32_t queue_duration_max, 9220d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko int32_t queue_duration_sample, 923b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat const DeathDataPhaseSnapshot* prev) 924b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat : profiling_phase(profiling_phase), 925b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat death_data(count, 926b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat run_duration_sum, 927b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat run_duration_max, 928b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat run_duration_sample, 929b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat queue_duration_sum, 930b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat queue_duration_max, 931b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat queue_duration_sample), 9320d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko prev(prev) {} 933b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 934b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat//------------------------------------------------------------------------------ 935b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// TaskSnapshot 936b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 937b8cf94937c52feb53b55c39e3f82094d27de464cDaniel EratTaskSnapshot::TaskSnapshot() { 938b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 939b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 940b8cf94937c52feb53b55c39e3f82094d27de464cDaniel EratTaskSnapshot::TaskSnapshot(const BirthOnThreadSnapshot& birth, 941b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat const DeathDataSnapshot& death_data, 942b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat const std::string& death_thread_name) 943b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat : birth(birth), 944b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat death_data(death_data), 945b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat death_thread_name(death_thread_name) { 946b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 947b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 948b8cf94937c52feb53b55c39e3f82094d27de464cDaniel EratTaskSnapshot::~TaskSnapshot() { 949b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 950b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 951b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat//------------------------------------------------------------------------------ 952b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// ProcessDataPhaseSnapshot 953b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 954b8cf94937c52feb53b55c39e3f82094d27de464cDaniel EratProcessDataPhaseSnapshot::ProcessDataPhaseSnapshot() { 955b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 956b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 95745779228f8c9e40851cfd23f727e2bd8ffdd4714Alex VakulenkoProcessDataPhaseSnapshot::ProcessDataPhaseSnapshot( 95845779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko const ProcessDataPhaseSnapshot& other) = default; 95945779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko 960b8cf94937c52feb53b55c39e3f82094d27de464cDaniel EratProcessDataPhaseSnapshot::~ProcessDataPhaseSnapshot() { 961b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 962b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 963b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat//------------------------------------------------------------------------------ 964b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// ProcessDataPhaseSnapshot 965b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 966b8cf94937c52feb53b55c39e3f82094d27de464cDaniel EratProcessDataSnapshot::ProcessDataSnapshot() 967b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#if !defined(OS_NACL) 968b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat : process_id(base::GetCurrentProcId()) { 969b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#else 970b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat : process_id(base::kNullProcessId) { 971b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#endif 972b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 973b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 97445779228f8c9e40851cfd23f727e2bd8ffdd4714Alex VakulenkoProcessDataSnapshot::ProcessDataSnapshot(const ProcessDataSnapshot& other) = 97545779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko default; 97645779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko 977b8cf94937c52feb53b55c39e3f82094d27de464cDaniel EratProcessDataSnapshot::~ProcessDataSnapshot() { 978b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 979b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 980b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} // namespace tracked_objects 981