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_(&current) {
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