136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe// Copyright 2016 The Chromium Authors. All rights reserved.
236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe// Use of this source code is governed by a BSD-style license that can be
336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe// found in the LICENSE file.
436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe
536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe#include "base/debug/activity_tracker.h"
636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe
736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe#include <algorithm>
836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe#include <limits>
936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe#include <utility>
1036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe
1136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe#include "base/atomic_sequence_num.h"
1236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe#include "base/debug/stack_trace.h"
1336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe#include "base/files/file.h"
1436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe#include "base/files/file_path.h"
1536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe#include "base/files/memory_mapped_file.h"
1636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe#include "base/logging.h"
1736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe#include "base/memory/ptr_util.h"
1836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe#include "base/metrics/field_trial.h"
1936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe#include "base/metrics/histogram_macros.h"
2036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe#include "base/pending_task.h"
2136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe#include "base/pickle.h"
2236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe#include "base/process/process.h"
2336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe#include "base/process/process_handle.h"
2436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe#include "base/stl_util.h"
2536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe#include "base/strings/string_util.h"
26319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski#include "base/strings/utf_string_conversions.h"
2736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe#include "base/threading/platform_thread.h"
2836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe
2936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abenamespace base {
3036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abenamespace debug {
3136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe
3236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abenamespace {
3336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe
3436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe// The minimum depth a stack should support.
3536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abeconst int kMinStackDepth = 2;
3636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe
3736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe// The amount of memory set aside for holding arbitrary user data (key/value
3836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe// pairs) globally or associated with ActivityData entries.
3936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abeconst size_t kUserDataSize = 1 << 10;     // 1 KiB
40319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowskiconst size_t kProcessDataSize = 4 << 10;  // 4 KiB
4136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abeconst size_t kGlobalDataSize = 16 << 10;  // 16 KiB
4236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abeconst size_t kMaxUserDataNameLength =
4336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    static_cast<size_t>(std::numeric_limits<uint8_t>::max());
4436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe
4536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe// A constant used to indicate that module information is changing.
4636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abeconst uint32_t kModuleInformationChanging = 0x80000000;
4736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe
48319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski// The key used to record process information.
49319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowskiconst char kProcessPhaseDataKey[] = "process-phase";
50319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski
51319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski// An atomically incrementing number, used to check for recreations of objects
52319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski// in the same memory space.
53319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub PawlowskiStaticAtomicSequenceNumber g_next_id;
54319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski
5536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abeunion ThreadRef {
5636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  int64_t as_id;
5736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe#if defined(OS_WIN)
5836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  // On Windows, the handle itself is often a pseudo-handle with a common
5936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  // value meaning "this thread" and so the thread-id is used. The former
6036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  // can be converted to a thread-id with a system call.
6136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  PlatformThreadId as_tid;
6236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe#elif defined(OS_POSIX)
6336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  // On Posix, the handle is always a unique identifier so no conversion
6436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  // needs to be done. However, it's value is officially opaque so there
6536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  // is no one correct way to convert it to a numerical identifier.
6636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  PlatformThreadHandle::Handle as_handle;
6736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe#endif
6836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe};
6936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe
70f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe// Gets the next non-zero identifier. It is only unique within a process.
71319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowskiuint32_t GetNextDataId() {
72319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski  uint32_t id;
73319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski  while ((id = g_next_id.GetNext()) == 0)
74319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski    ;
75319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski  return id;
76319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski}
77319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski
78f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe// Gets the current process-id, either from the GlobalActivityTracker if it
79f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe// exists (where the PID can be defined for testing) or from the system if
80f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe// there isn't such.
81f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abeint64_t GetProcessId() {
82f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe  GlobalActivityTracker* global = GlobalActivityTracker::Get();
83f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe  if (global)
84f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe    return global->process_id();
85f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe  return GetCurrentProcId();
86f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe}
87f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe
88319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski// Finds and reuses a specific allocation or creates a new one.
89319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub PawlowskiPersistentMemoryAllocator::Reference AllocateFrom(
90319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski    PersistentMemoryAllocator* allocator,
91319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski    uint32_t from_type,
92319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski    size_t size,
93319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski    uint32_t to_type) {
94319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski  PersistentMemoryAllocator::Iterator iter(allocator);
95319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski  PersistentMemoryAllocator::Reference ref;
96319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski  while ((ref = iter.GetNextOfType(from_type)) != 0) {
97319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski    DCHECK_LE(size, allocator->GetAllocSize(ref));
98319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski    // This can fail if a another thread has just taken it. It is assumed that
99319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski    // the memory is cleared during the "free" operation.
100319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski    if (allocator->ChangeType(ref, to_type, from_type, /*clear=*/false))
101319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski      return ref;
102319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski  }
103319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski
104319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski  return allocator->Allocate(size, to_type);
105319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski}
106319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski
10736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe// Determines the previous aligned index.
10836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abesize_t RoundDownToAlignment(size_t index, size_t alignment) {
10936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  return index & (0 - alignment);
11036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe}
11136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe
11236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe// Determines the next aligned index.
11336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abesize_t RoundUpToAlignment(size_t index, size_t alignment) {
11436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  return (index + (alignment - 1)) & (0 - alignment);
11536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe}
11636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe
117319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski// Converts "tick" timing into wall time.
118319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub PawlowskiTime WallTimeFromTickTime(int64_t ticks_start, int64_t ticks, Time time_start) {
119319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski  return time_start + TimeDelta::FromInternalValue(ticks - ticks_start);
120319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski}
121319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski
12236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe}  // namespace
12336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe
124319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub PawlowskiOwningProcess::OwningProcess() {}
125319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub PawlowskiOwningProcess::~OwningProcess() {}
126319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski
127f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abevoid OwningProcess::Release_Initialize(int64_t pid) {
128319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski  uint32_t old_id = data_id.load(std::memory_order_acquire);
129319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski  DCHECK_EQ(0U, old_id);
130f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe  process_id = pid != 0 ? pid : GetProcessId();
131319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski  create_stamp = Time::Now().ToInternalValue();
132319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski  data_id.store(GetNextDataId(), std::memory_order_release);
133319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski}
134319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski
135f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abevoid OwningProcess::SetOwningProcessIdForTesting(int64_t pid, int64_t stamp) {
136319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski  DCHECK_NE(0U, data_id);
137319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski  process_id = pid;
138319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski  create_stamp = stamp;
139319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski}
140319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski
141319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski// static
142319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowskibool OwningProcess::GetOwningProcessId(const void* memory,
143f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe                                       int64_t* out_id,
144319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski                                       int64_t* out_stamp) {
145319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski  const OwningProcess* info = reinterpret_cast<const OwningProcess*>(memory);
146319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski  uint32_t id = info->data_id.load(std::memory_order_acquire);
147319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski  if (id == 0)
148319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski    return false;
149319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski
150f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe  *out_id = info->process_id;
151319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski  *out_stamp = info->create_stamp;
152319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski  return id == info->data_id.load(std::memory_order_seq_cst);
153319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski}
15436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe
15536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe// It doesn't matter what is contained in this (though it will be all zeros)
15636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe// as only the address of it is important.
15736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abeconst ActivityData kNullActivityData = {};
15836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe
15936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko AbeActivityData ActivityData::ForThread(const PlatformThreadHandle& handle) {
16036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  ThreadRef thread_ref;
16136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  thread_ref.as_id = 0;  // Zero the union in case other is smaller.
16236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe#if defined(OS_WIN)
16336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  thread_ref.as_tid = ::GetThreadId(handle.platform_handle());
16436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe#elif defined(OS_POSIX)
16536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  thread_ref.as_handle = handle.platform_handle();
16636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe#endif
16736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  return ForThread(thread_ref.as_id);
16836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe}
16936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe
17036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko AbeActivityTrackerMemoryAllocator::ActivityTrackerMemoryAllocator(
17136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    PersistentMemoryAllocator* allocator,
17236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    uint32_t object_type,
17336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    uint32_t object_free_type,
17436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    size_t object_size,
17536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    size_t cache_size,
17636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    bool make_iterable)
17736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    : allocator_(allocator),
17836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe      object_type_(object_type),
17936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe      object_free_type_(object_free_type),
18036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe      object_size_(object_size),
18136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe      cache_size_(cache_size),
18236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe      make_iterable_(make_iterable),
18336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe      iterator_(allocator),
18436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe      cache_values_(new Reference[cache_size]),
18536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe      cache_used_(0) {
18636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  DCHECK(allocator);
18736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe}
18836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe
18936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko AbeActivityTrackerMemoryAllocator::~ActivityTrackerMemoryAllocator() {}
19036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe
19136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko AbeActivityTrackerMemoryAllocator::Reference
19236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko AbeActivityTrackerMemoryAllocator::GetObjectReference() {
19336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  // First see if there is a cached value that can be returned. This is much
19436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  // faster than searching the memory system for free blocks.
19536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  while (cache_used_ > 0) {
19636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    Reference cached = cache_values_[--cache_used_];
19736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    // Change the type of the cached object to the proper type and return it.
19836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    // If the type-change fails that means another thread has taken this from
19936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    // under us (via the search below) so ignore it and keep trying. Don't
20036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    // clear the memory because that was done when the type was made "free".
20136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    if (allocator_->ChangeType(cached, object_type_, object_free_type_, false))
20236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe      return cached;
20336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  }
20436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe
20536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  // Fetch the next "free" object from persistent memory. Rather than restart
20636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  // the iterator at the head each time and likely waste time going again
20736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  // through objects that aren't relevant, the iterator continues from where
20836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  // it last left off and is only reset when the end is reached. If the
20936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  // returned reference matches |last|, then it has wrapped without finding
21036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  // anything.
21136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  const Reference last = iterator_.GetLast();
21236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  while (true) {
21336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    uint32_t type;
21436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    Reference found = iterator_.GetNext(&type);
21536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    if (found && type == object_free_type_) {
21636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe      // Found a free object. Change it to the proper type and return it. If
21736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe      // the type-change fails that means another thread has taken this from
21836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe      // under us so ignore it and keep trying.
21936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe      if (allocator_->ChangeType(found, object_type_, object_free_type_, false))
22036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe        return found;
22136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    }
22236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    if (found == last) {
22336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe      // Wrapped. No desired object was found.
22436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe      break;
22536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    }
22636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    if (!found) {
22736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe      // Reached end; start over at the beginning.
22836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe      iterator_.Reset();
22936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    }
23036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  }
23136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe
23236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  // No free block was found so instead allocate a new one.
23336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  Reference allocated = allocator_->Allocate(object_size_, object_type_);
23436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  if (allocated && make_iterable_)
23536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    allocator_->MakeIterable(allocated);
23636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  return allocated;
23736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe}
23836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe
23936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abevoid ActivityTrackerMemoryAllocator::ReleaseObjectReference(Reference ref) {
24036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  // Mark object as free.
24136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  bool success = allocator_->ChangeType(ref, object_free_type_, object_type_,
24236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe                                        /*clear=*/true);
24336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  DCHECK(success);
24436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe
24536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  // Add this reference to our "free" cache if there is space. If not, the type
24636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  // has still been changed to indicate that it is free so this (or another)
24736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  // thread can find it, albeit more slowly, using the iteration method above.
24836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  if (cache_used_ < cache_size_)
24936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    cache_values_[cache_used_++] = ref;
25036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe}
25136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe
25236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe// static
25336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abevoid Activity::FillFrom(Activity* activity,
25436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe                        const void* program_counter,
25536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe                        const void* origin,
25636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe                        Type type,
25736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe                        const ActivityData& data) {
25836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  activity->time_internal = base::TimeTicks::Now().ToInternalValue();
25936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  activity->calling_address = reinterpret_cast<uintptr_t>(program_counter);
26036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  activity->origin_address = reinterpret_cast<uintptr_t>(origin);
26136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  activity->activity_type = type;
26236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  activity->data = data;
26336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe
26436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe#if defined(SYZYASAN)
26536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  // Create a stacktrace from the current location and get the addresses.
26636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  StackTrace stack_trace;
26736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  size_t stack_depth;
26836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  const void* const* stack_addrs = stack_trace.Addresses(&stack_depth);
26936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  // Copy the stack addresses, ignoring the first one (here).
27036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  size_t i;
27136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  for (i = 1; i < stack_depth && i < kActivityCallStackSize; ++i) {
27236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    activity->call_stack[i - 1] = reinterpret_cast<uintptr_t>(stack_addrs[i]);
27336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  }
27436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  activity->call_stack[i - 1] = 0;
27536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe#else
27636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  activity->call_stack[0] = 0;
27736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe#endif
27836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe}
27936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe
28036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko AbeActivityUserData::TypedValue::TypedValue() {}
28136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko AbeActivityUserData::TypedValue::TypedValue(const TypedValue& other) = default;
28236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko AbeActivityUserData::TypedValue::~TypedValue() {}
28336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe
28436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko AbeStringPiece ActivityUserData::TypedValue::Get() const {
28536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  DCHECK_EQ(RAW_VALUE, type_);
28636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  return long_value_;
28736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe}
28836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe
28936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko AbeStringPiece ActivityUserData::TypedValue::GetString() const {
29036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  DCHECK_EQ(STRING_VALUE, type_);
29136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  return long_value_;
29236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe}
29336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe
29436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abebool ActivityUserData::TypedValue::GetBool() const {
29536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  DCHECK_EQ(BOOL_VALUE, type_);
29636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  return short_value_ != 0;
29736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe}
29836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe
29936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abechar ActivityUserData::TypedValue::GetChar() const {
30036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  DCHECK_EQ(CHAR_VALUE, type_);
30136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  return static_cast<char>(short_value_);
30236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe}
30336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe
30436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abeint64_t ActivityUserData::TypedValue::GetInt() const {
30536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  DCHECK_EQ(SIGNED_VALUE, type_);
30636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  return static_cast<int64_t>(short_value_);
30736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe}
30836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe
30936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abeuint64_t ActivityUserData::TypedValue::GetUint() const {
31036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  DCHECK_EQ(UNSIGNED_VALUE, type_);
31136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  return static_cast<uint64_t>(short_value_);
31236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe}
31336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe
31436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko AbeStringPiece ActivityUserData::TypedValue::GetReference() const {
31536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  DCHECK_EQ(RAW_VALUE_REFERENCE, type_);
31636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  return ref_value_;
31736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe}
31836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe
31936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko AbeStringPiece ActivityUserData::TypedValue::GetStringReference() const {
32036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  DCHECK_EQ(STRING_VALUE_REFERENCE, type_);
32136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  return ref_value_;
32236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe}
32336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe
324319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski// These are required because std::atomic is (currently) not a POD type and
325319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski// thus clang requires explicit out-of-line constructors and destructors even
326319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski// when they do nothing.
32736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko AbeActivityUserData::ValueInfo::ValueInfo() {}
32836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko AbeActivityUserData::ValueInfo::ValueInfo(ValueInfo&&) = default;
32936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko AbeActivityUserData::ValueInfo::~ValueInfo() {}
330319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub PawlowskiActivityUserData::MemoryHeader::MemoryHeader() {}
331319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub PawlowskiActivityUserData::MemoryHeader::~MemoryHeader() {}
332319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub PawlowskiActivityUserData::FieldHeader::FieldHeader() {}
333319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub PawlowskiActivityUserData::FieldHeader::~FieldHeader() {}
33436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe
335f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko AbeActivityUserData::ActivityUserData() : ActivityUserData(nullptr, 0, -1) {}
33636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe
337f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko AbeActivityUserData::ActivityUserData(void* memory, size_t size, int64_t pid)
33836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    : memory_(reinterpret_cast<char*>(memory)),
33936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe      available_(RoundDownToAlignment(size, kMemoryAlignment)),
340f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe      header_(reinterpret_cast<MemoryHeader*>(memory)),
341f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe      orig_data_id(0),
342f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe      orig_process_id(0),
343f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe      orig_create_stamp(0) {
34436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  // It's possible that no user data is being stored.
34536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  if (!memory_)
34636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    return;
34736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe
348319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski  static_assert(0 == sizeof(MemoryHeader) % kMemoryAlignment, "invalid header");
349319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski  DCHECK_LT(sizeof(MemoryHeader), available_);
350319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski  if (header_->owner.data_id.load(std::memory_order_acquire) == 0)
351f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe    header_->owner.Release_Initialize(pid);
352319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski  memory_ += sizeof(MemoryHeader);
353319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski  available_ -= sizeof(MemoryHeader);
35436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe
355f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe  // Make a copy of identifying information for later comparison.
356f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe  *const_cast<uint32_t*>(&orig_data_id) =
357f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe      header_->owner.data_id.load(std::memory_order_acquire);
358f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe  *const_cast<int64_t*>(&orig_process_id) = header_->owner.process_id;
359f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe  *const_cast<int64_t*>(&orig_create_stamp) = header_->owner.create_stamp;
360f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe
36136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  // If there is already data present, load that. This allows the same class
36236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  // to be used for analysis through snapshots.
36336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  ImportExistingData();
36436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe}
36536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe
36636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko AbeActivityUserData::~ActivityUserData() {}
36736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe
368319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowskibool ActivityUserData::CreateSnapshot(Snapshot* output_snapshot) const {
369319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski  DCHECK(output_snapshot);
370319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski  DCHECK(output_snapshot->empty());
371319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski
372319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski  // Find any new data that may have been added by an active instance of this
373319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski  // class that is adding records.
374319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski  ImportExistingData();
375319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski
376f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe  // Add all the values to the snapshot.
377319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski  for (const auto& entry : values_) {
378319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski    TypedValue value;
379f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe    const size_t size = entry.second.size_ptr->load(std::memory_order_acquire);
380319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski    value.type_ = entry.second.type;
381f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe    DCHECK_GE(entry.second.extent, size);
382319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski
383319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski    switch (entry.second.type) {
384319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski      case RAW_VALUE:
385319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski      case STRING_VALUE:
386319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski        value.long_value_ =
387f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe            std::string(reinterpret_cast<char*>(entry.second.memory), size);
388319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski        break;
389319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski      case RAW_VALUE_REFERENCE:
390319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski      case STRING_VALUE_REFERENCE: {
391319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski        ReferenceRecord* ref =
392319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski            reinterpret_cast<ReferenceRecord*>(entry.second.memory);
393319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski        value.ref_value_ = StringPiece(
394319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski            reinterpret_cast<char*>(static_cast<uintptr_t>(ref->address)),
395319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski            static_cast<size_t>(ref->size));
396319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski      } break;
397319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski      case BOOL_VALUE:
398319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski      case CHAR_VALUE:
399319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski        value.short_value_ = *reinterpret_cast<char*>(entry.second.memory);
400319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski        break;
401319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski      case SIGNED_VALUE:
402319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski      case UNSIGNED_VALUE:
403319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski        value.short_value_ = *reinterpret_cast<uint64_t*>(entry.second.memory);
404319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski        break;
405319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski      case END_OF_VALUES:  // Included for completeness purposes.
406319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski        NOTREACHED();
407319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski    }
408319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski    auto inserted = output_snapshot->insert(
409319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski        std::make_pair(entry.second.name.as_string(), std::move(value)));
410319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski    DCHECK(inserted.second);  // True if inserted, false if existed.
411319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski  }
412319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski
413f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe  // Another import attempt will validate that the underlying memory has not
414f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe  // been reused for another purpose. Entries added since the first import
415f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe  // will be ignored here but will be returned if another snapshot is created.
416f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe  ImportExistingData();
417f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe  if (!memory_) {
418f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe    output_snapshot->clear();
419f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe    return false;
420f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe  }
421f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe
422f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe  // Successful snapshot.
423319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski  return true;
424319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski}
425319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski
426319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowskiconst void* ActivityUserData::GetBaseAddress() const {
427319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski  // The |memory_| pointer advances as elements are written but the |header_|
428319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski  // value is always at the start of the block so just return that.
429319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski  return header_;
430319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski}
431319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski
432f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abevoid ActivityUserData::SetOwningProcessIdForTesting(int64_t pid,
433319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski                                                    int64_t stamp) {
434319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski  if (!header_)
435319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski    return;
436319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski  header_->owner.SetOwningProcessIdForTesting(pid, stamp);
437319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski}
438319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski
439319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski// static
440319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowskibool ActivityUserData::GetOwningProcessId(const void* memory,
441f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe                                          int64_t* out_id,
442319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski                                          int64_t* out_stamp) {
443319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski  const MemoryHeader* header = reinterpret_cast<const MemoryHeader*>(memory);
444319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski  return OwningProcess::GetOwningProcessId(&header->owner, out_id, out_stamp);
445319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski}
446319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski
44736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abevoid ActivityUserData::Set(StringPiece name,
44836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe                           ValueType type,
44936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe                           const void* memory,
45036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe                           size_t size) {
45136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  DCHECK_GE(std::numeric_limits<uint8_t>::max(), name.length());
45236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  size = std::min(std::numeric_limits<uint16_t>::max() - (kMemoryAlignment - 1),
45336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe                  size);
45436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe
45536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  // It's possible that no user data is being stored.
45636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  if (!memory_)
45736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    return;
45836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe
45936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  // The storage of a name is limited so use that limit during lookup.
46036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  if (name.length() > kMaxUserDataNameLength)
46136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    name.set(name.data(), kMaxUserDataNameLength);
46236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe
46336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  ValueInfo* info;
46436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  auto existing = values_.find(name);
46536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  if (existing != values_.end()) {
46636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    info = &existing->second;
46736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  } else {
46836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    // The name size is limited to what can be held in a single byte but
46936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    // because there are not alignment constraints on strings, it's set tight
47036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    // against the header. Its extent (the reserved space, even if it's not
47136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    // all used) is calculated so that, when pressed against the header, the
47236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    // following field will be aligned properly.
47336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    size_t name_size = name.length();
47436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    size_t name_extent =
475319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski        RoundUpToAlignment(sizeof(FieldHeader) + name_size, kMemoryAlignment) -
476319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski        sizeof(FieldHeader);
47736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    size_t value_extent = RoundUpToAlignment(size, kMemoryAlignment);
47836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe
47936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    // The "base size" is the size of the header and (padded) string key. Stop
48036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    // now if there's not room enough for even this.
481319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski    size_t base_size = sizeof(FieldHeader) + name_extent;
48236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    if (base_size > available_)
48336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe      return;
48436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe
48536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    // The "full size" is the size for storing the entire value.
48636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    size_t full_size = std::min(base_size + value_extent, available_);
48736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe
48836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    // If the value is actually a single byte, see if it can be stuffed at the
48936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    // end of the name extent rather than wasting kMemoryAlignment bytes.
49036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    if (size == 1 && name_extent > name_size) {
49136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe      full_size = base_size;
49236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe      --name_extent;
49336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe      --base_size;
49436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    }
49536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe
49636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    // Truncate the stored size to the amount of available memory. Stop now if
49736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    // there's not any room for even part of the value.
49836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    if (size != 0) {
49936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe      size = std::min(full_size - base_size, size);
50036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe      if (size == 0)
50136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe        return;
50236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    }
50336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe
50436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    // Allocate a chunk of memory.
505319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski    FieldHeader* header = reinterpret_cast<FieldHeader*>(memory_);
50636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    memory_ += full_size;
50736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    available_ -= full_size;
50836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe
50936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    // Datafill the header and name records. Memory must be zeroed. The |type|
51036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    // is written last, atomically, to release all the other values.
51136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    DCHECK_EQ(END_OF_VALUES, header->type.load(std::memory_order_relaxed));
51236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    DCHECK_EQ(0, header->value_size.load(std::memory_order_relaxed));
51336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    header->name_size = static_cast<uint8_t>(name_size);
51436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    header->record_size = full_size;
515319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski    char* name_memory = reinterpret_cast<char*>(header) + sizeof(FieldHeader);
51636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    void* value_memory =
517319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski        reinterpret_cast<char*>(header) + sizeof(FieldHeader) + name_extent;
51836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    memcpy(name_memory, name.data(), name_size);
51936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    header->type.store(type, std::memory_order_release);
52036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe
52136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    // Create an entry in |values_| so that this field can be found and changed
52236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    // later on without having to allocate new entries.
52336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    StringPiece persistent_name(name_memory, name_size);
52436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    auto inserted =
52536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe        values_.insert(std::make_pair(persistent_name, ValueInfo()));
52636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    DCHECK(inserted.second);  // True if inserted, false if existed.
52736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    info = &inserted.first->second;
52836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    info->name = persistent_name;
52936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    info->memory = value_memory;
53036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    info->size_ptr = &header->value_size;
531319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski    info->extent = full_size - sizeof(FieldHeader) - name_extent;
53236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    info->type = type;
53336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  }
53436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe
53536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  // Copy the value data to storage. The |size| is written last, atomically, to
53636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  // release the copied data. Until then, a parallel reader will just ignore
53736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  // records with a zero size.
53836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  DCHECK_EQ(type, info->type);
53936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  size = std::min(size, info->extent);
54036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  info->size_ptr->store(0, std::memory_order_seq_cst);
54136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  memcpy(info->memory, memory, size);
54236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  info->size_ptr->store(size, std::memory_order_release);
54336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe}
54436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe
54536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abevoid ActivityUserData::SetReference(StringPiece name,
54636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe                                    ValueType type,
54736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe                                    const void* memory,
54836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe                                    size_t size) {
54936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  ReferenceRecord rec;
55036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  rec.address = reinterpret_cast<uintptr_t>(memory);
55136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  rec.size = size;
55236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  Set(name, type, &rec, sizeof(rec));
55336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe}
55436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe
55536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abevoid ActivityUserData::ImportExistingData() const {
556f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe  // It's possible that no user data is being stored.
557f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe  if (!memory_)
558f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe    return;
559f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe
560319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski  while (available_ > sizeof(FieldHeader)) {
561319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski    FieldHeader* header = reinterpret_cast<FieldHeader*>(memory_);
56236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    ValueType type =
56336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe        static_cast<ValueType>(header->type.load(std::memory_order_acquire));
56436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    if (type == END_OF_VALUES)
56536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe      return;
56636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    if (header->record_size > available_)
56736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe      return;
56836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe
569319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski    size_t value_offset = RoundUpToAlignment(
570319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski        sizeof(FieldHeader) + header->name_size, kMemoryAlignment);
57136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    if (header->record_size == value_offset &&
57236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe        header->value_size.load(std::memory_order_relaxed) == 1) {
57336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe      value_offset -= 1;
57436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    }
57536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    if (value_offset + header->value_size > header->record_size)
57636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe      return;
57736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe
57836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    ValueInfo info;
579319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski    info.name = StringPiece(memory_ + sizeof(FieldHeader), header->name_size);
58036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    info.type = type;
58136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    info.memory = memory_ + value_offset;
58236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    info.size_ptr = &header->value_size;
58336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    info.extent = header->record_size - value_offset;
58436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe
58536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    StringPiece key(info.name);
58636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    values_.insert(std::make_pair(key, std::move(info)));
58736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe
58836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    memory_ += header->record_size;
58936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    available_ -= header->record_size;
59036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  }
591f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe
592f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe  // Check if memory has been completely reused.
593f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe  if (header_->owner.data_id.load(std::memory_order_acquire) != orig_data_id ||
594f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe      header_->owner.process_id != orig_process_id ||
595f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe      header_->owner.create_stamp != orig_create_stamp) {
596f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe    memory_ = nullptr;
597f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe    values_.clear();
598f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe  }
59970cd4fac31a9b0865dab6574540f70cc103337dcJakub Pawlowski}
60070cd4fac31a9b0865dab6574540f70cc103337dcJakub Pawlowski
60136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe// This information is kept for every thread that is tracked. It is filled
60236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe// the very first time the thread is seen. All fields must be of exact sizes
60336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe// so there is no issue moving between 32 and 64-bit builds.
60436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abestruct ThreadActivityTracker::Header {
60536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  // Defined in .h for analyzer access. Increment this if structure changes!
60636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  static constexpr uint32_t kPersistentTypeId =
60736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe      GlobalActivityTracker::kTypeIdActivityTracker;
60836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe
60936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  // Expected size for 32/64-bit check.
610319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski  static constexpr size_t kExpectedInstanceSize =
611319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski      OwningProcess::kExpectedInstanceSize + Activity::kExpectedInstanceSize +
612319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski      72;
61370cd4fac31a9b0865dab6574540f70cc103337dcJakub Pawlowski
614319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski  // This information uniquely identifies a process.
615319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski  OwningProcess owner;
61636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe
617319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski  // The thread-id (thread_ref.as_id) to which this data belongs. This number
618319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski  // is not guaranteed to mean anything but combined with the process-id from
619319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski  // OwningProcess is unique among all active trackers.
62036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  ThreadRef thread_ref;
62136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe
62236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  // The start-time and start-ticks when the data was created. Each activity
62336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  // record has a |time_internal| value that can be converted to a "wall time"
62436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  // with these two values.
62536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  int64_t start_time;
62636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  int64_t start_ticks;
62736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe
628319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski  // The number of Activity slots (spaces that can hold an Activity) that
629319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski  // immediately follow this structure in memory.
630319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski  uint32_t stack_slots;
631319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski
632319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski  // Some padding to keep everything 64-bit aligned.
633319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski  uint32_t padding;
634319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski
63536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  // The current depth of the stack. This may be greater than the number of
63636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  // slots. If the depth exceeds the number of slots, the newest entries
63736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  // won't be recorded.
63836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  std::atomic<uint32_t> current_depth;
63936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe
640319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski  // A memory location used to indicate if changes have been made to the data
64136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  // that would invalidate an in-progress read of its contents. The active
64236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  // tracker will zero the value whenever something gets popped from the
64336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  // stack. A monitoring tracker can write a non-zero value here, copy the
64436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  // stack contents, and read the value to know, if it is still non-zero, that
64536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  // the contents didn't change while being copied. This can handle concurrent
64636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  // snapshot operations only if each snapshot writes a different bit (which
64736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  // is not the current implementation so no parallel snapshots allowed).
648319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski  std::atomic<uint32_t> data_unchanged;
649319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski
650319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski  // The last "exception" activity. This can't be stored on the stack because
651319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski  // that could get popped as things unwind.
652319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski  Activity last_exception;
65336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe
65436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  // The name of the thread (up to a maximum length). Dynamic-length names
65536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  // are not practical since the memory has to come from the same persistent
65636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  // allocator that holds this structure and to which this object has no
65736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  // reference.
65836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  char thread_name[32];
65936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe};
66036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe
66136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko AbeThreadActivityTracker::Snapshot::Snapshot() {}
66236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko AbeThreadActivityTracker::Snapshot::~Snapshot() {}
66336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe
66436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko AbeThreadActivityTracker::ScopedActivity::ScopedActivity(
66536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    ThreadActivityTracker* tracker,
66636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    const void* program_counter,
66736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    const void* origin,
66836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    Activity::Type type,
66936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    const ActivityData& data)
67036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    : tracker_(tracker) {
67136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  if (tracker_)
67236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    activity_id_ = tracker_->PushActivity(program_counter, origin, type, data);
67336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe}
67436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe
67536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko AbeThreadActivityTracker::ScopedActivity::~ScopedActivity() {
67636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  if (tracker_)
67736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    tracker_->PopActivity(activity_id_);
67836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe}
67936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe
68036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abevoid ThreadActivityTracker::ScopedActivity::ChangeTypeAndData(
68136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    Activity::Type type,
68236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    const ActivityData& data) {
68336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  if (tracker_)
68436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    tracker_->ChangeActivity(activity_id_, type, data);
68536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe}
68636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe
68736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko AbeThreadActivityTracker::ThreadActivityTracker(void* base, size_t size)
68836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    : header_(static_cast<Header*>(base)),
68936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe      stack_(reinterpret_cast<Activity*>(reinterpret_cast<char*>(base) +
69036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe                                         sizeof(Header))),
69136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe      stack_slots_(
69236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe          static_cast<uint32_t>((size - sizeof(Header)) / sizeof(Activity))) {
69336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  DCHECK(thread_checker_.CalledOnValidThread());
69436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe
69536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  // Verify the parameters but fail gracefully if they're not valid so that
69636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  // production code based on external inputs will not crash.  IsValid() will
69736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  // return false in this case.
69836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  if (!base ||
69936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe      // Ensure there is enough space for the header and at least a few records.
70036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe      size < sizeof(Header) + kMinStackDepth * sizeof(Activity) ||
70136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe      // Ensure that the |stack_slots_| calculation didn't overflow.
70236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe      (size - sizeof(Header)) / sizeof(Activity) >
70336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe          std::numeric_limits<uint32_t>::max()) {
70436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    NOTREACHED();
70536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    return;
70636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  }
70736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe
70836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  // Ensure that the thread reference doesn't exceed the size of the ID number.
70936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  // This won't compile at the global scope because Header is a private struct.
71036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  static_assert(
71136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe      sizeof(header_->thread_ref) == sizeof(header_->thread_ref.as_id),
71236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe      "PlatformThreadHandle::Handle is too big to hold in 64-bit ID");
71336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe
71436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  // Ensure that the alignment of Activity.data is properly aligned to a
71536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  // 64-bit boundary so there are no interoperability-issues across cpu
71636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  // architectures.
71736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  static_assert(offsetof(Activity, data) % sizeof(uint64_t) == 0,
71836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe                "ActivityData.data is not 64-bit aligned");
71936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe
72036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  // Provided memory should either be completely initialized or all zeros.
721319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski  if (header_->owner.data_id.load(std::memory_order_relaxed) == 0) {
72236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    // This is a new file. Double-check other fields and then initialize.
723319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski    DCHECK_EQ(0, header_->owner.process_id);
724319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski    DCHECK_EQ(0, header_->owner.create_stamp);
72536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    DCHECK_EQ(0, header_->thread_ref.as_id);
72636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    DCHECK_EQ(0, header_->start_time);
72736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    DCHECK_EQ(0, header_->start_ticks);
72836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    DCHECK_EQ(0U, header_->stack_slots);
72936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    DCHECK_EQ(0U, header_->current_depth.load(std::memory_order_relaxed));
730319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski    DCHECK_EQ(0U, header_->data_unchanged.load(std::memory_order_relaxed));
73136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    DCHECK_EQ(0, stack_[0].time_internal);
73236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    DCHECK_EQ(0U, stack_[0].origin_address);
73336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    DCHECK_EQ(0U, stack_[0].call_stack[0]);
73436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    DCHECK_EQ(0U, stack_[0].data.task.sequence_id);
73536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe
73636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe#if defined(OS_WIN)
73736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    header_->thread_ref.as_tid = PlatformThread::CurrentId();
73836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe#elif defined(OS_POSIX)
73936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    header_->thread_ref.as_handle =
74036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe        PlatformThread::CurrentHandle().platform_handle();
74136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe#endif
74236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe
74336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    header_->start_time = base::Time::Now().ToInternalValue();
74436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    header_->start_ticks = base::TimeTicks::Now().ToInternalValue();
74536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    header_->stack_slots = stack_slots_;
74636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    strlcpy(header_->thread_name, PlatformThread::GetName(),
74736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe            sizeof(header_->thread_name));
74836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe
74936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    // This is done last so as to guarantee that everything above is "released"
75036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    // by the time this value gets written.
751319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski    header_->owner.Release_Initialize();
75236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe
75336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    valid_ = true;
75436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    DCHECK(IsValid());
75536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  } else {
75636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    // This is a file with existing data. Perform basic consistency checks.
75736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    valid_ = true;
75836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    valid_ = IsValid();
75936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  }
76036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe}
76136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe
76236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko AbeThreadActivityTracker::~ThreadActivityTracker() {}
76336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe
76436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko AbeThreadActivityTracker::ActivityId ThreadActivityTracker::PushActivity(
76536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    const void* program_counter,
76636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    const void* origin,
76736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    Activity::Type type,
76836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    const ActivityData& data) {
76936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  // A thread-checker creates a lock to check the thread-id which means
77036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  // re-entry into this code if lock acquisitions are being tracked.
77136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  DCHECK(type == Activity::ACT_LOCK_ACQUIRE ||
77236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe         thread_checker_.CalledOnValidThread());
77336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe
77436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  // Get the current depth of the stack. No access to other memory guarded
77536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  // by this variable is done here so a "relaxed" load is acceptable.
77636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  uint32_t depth = header_->current_depth.load(std::memory_order_relaxed);
77736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe
77836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  // Handle the case where the stack depth has exceeded the storage capacity.
77936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  // Extra entries will be lost leaving only the base of the stack.
78036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  if (depth >= stack_slots_) {
78136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    // Since no other threads modify the data, no compare/exchange is needed.
78236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    // Since no other memory is being modified, a "relaxed" store is acceptable.
78336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    header_->current_depth.store(depth + 1, std::memory_order_relaxed);
78436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    return depth;
78536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  }
78636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe
78736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  // Get a pointer to the next activity and load it. No atomicity is required
78836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  // here because the memory is known only to this thread. It will be made
78936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  // known to other threads once the depth is incremented.
79036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  Activity::FillFrom(&stack_[depth], program_counter, origin, type, data);
79136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe
79236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  // Save the incremented depth. Because this guards |activity| memory filled
79336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  // above that may be read by another thread once the recorded depth changes,
79436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  // a "release" store is required.
79536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  header_->current_depth.store(depth + 1, std::memory_order_release);
79636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe
79736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  // The current depth is used as the activity ID because it simply identifies
79836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  // an entry. Once an entry is pop'd, it's okay to reuse the ID.
79936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  return depth;
80036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe}
80136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe
80236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abevoid ThreadActivityTracker::ChangeActivity(ActivityId id,
80336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe                                           Activity::Type type,
80436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe                                           const ActivityData& data) {
80536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  DCHECK(thread_checker_.CalledOnValidThread());
80636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  DCHECK(type != Activity::ACT_NULL || &data != &kNullActivityData);
80736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  DCHECK_LT(id, header_->current_depth.load(std::memory_order_acquire));
80836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe
80936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  // Update the information if it is being recorded (i.e. within slot limit).
81036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  if (id < stack_slots_) {
81136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    Activity* activity = &stack_[id];
81236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe
81336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    if (type != Activity::ACT_NULL) {
81436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe      DCHECK_EQ(activity->activity_type & Activity::ACT_CATEGORY_MASK,
81536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe                type & Activity::ACT_CATEGORY_MASK);
81636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe      activity->activity_type = type;
81736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    }
81836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe
81936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    if (&data != &kNullActivityData)
82036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe      activity->data = data;
82136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  }
82236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe}
82336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe
82436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abevoid ThreadActivityTracker::PopActivity(ActivityId id) {
82536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  // Do an atomic decrement of the depth. No changes to stack entries guarded
82636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  // by this variable are done here so a "relaxed" operation is acceptable.
82736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  // |depth| will receive the value BEFORE it was modified which means the
82836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  // return value must also be decremented. The slot will be "free" after
82936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  // this call but since only a single thread can access this object, the
83036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  // data will remain valid until this method returns or calls outside.
83136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  uint32_t depth =
83236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe      header_->current_depth.fetch_sub(1, std::memory_order_relaxed) - 1;
83336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe
83436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  // Validate that everything is running correctly.
83536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  DCHECK_EQ(id, depth);
83636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe
83736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  // A thread-checker creates a lock to check the thread-id which means
83836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  // re-entry into this code if lock acquisitions are being tracked.
83936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  DCHECK(stack_[depth].activity_type == Activity::ACT_LOCK_ACQUIRE ||
84036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe         thread_checker_.CalledOnValidThread());
84136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe
84236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  // The stack has shrunk meaning that some other thread trying to copy the
84336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  // contents for reporting purposes could get bad data. That thread would
844319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski  // have written a non-zero value into |data_unchanged|; clearing it here
84536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  // will let that thread detect that something did change. This needs to
84636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  // happen after the atomic |depth| operation above so a "release" store
84736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  // is required.
848319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski  header_->data_unchanged.store(0, std::memory_order_release);
84936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe}
85036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe
85136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abestd::unique_ptr<ActivityUserData> ThreadActivityTracker::GetUserData(
85236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    ActivityId id,
85336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    ActivityTrackerMemoryAllocator* allocator) {
854319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski  // Don't allow user data for lock acquisition as recursion may occur.
855319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski  if (stack_[id].activity_type == Activity::ACT_LOCK_ACQUIRE) {
856319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski    NOTREACHED();
857319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski    return MakeUnique<ActivityUserData>();
8588abac493f652a1835c61e538919820aa77658a39Mathieu Chartier  }
859fe2f52931e8e50253d06329d7bf0a4164c7ba580Jakub Pawlowski
860319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski  // User-data is only stored for activities actually held in the stack.
861319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski  if (id >= stack_slots_)
862319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski    return MakeUnique<ActivityUserData>();
863319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski
864319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski  // Create and return a real UserData object.
865319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski  return CreateUserDataForActivity(&stack_[id], allocator);
86636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe}
86736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe
86836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abebool ThreadActivityTracker::HasUserData(ActivityId id) {
86936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  // User-data is only stored for activities actually held in the stack.
87036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  return (id < stack_slots_ && stack_[id].user_data_ref);
87136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe}
87236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe
87336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abevoid ThreadActivityTracker::ReleaseUserData(
87436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    ActivityId id,
87536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    ActivityTrackerMemoryAllocator* allocator) {
87636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  // User-data is only stored for activities actually held in the stack.
87736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  if (id < stack_slots_ && stack_[id].user_data_ref) {
87836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    allocator->ReleaseObjectReference(stack_[id].user_data_ref);
87936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    stack_[id].user_data_ref = 0;
88036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  }
88136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe}
88236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe
883319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowskivoid ThreadActivityTracker::RecordExceptionActivity(const void* program_counter,
884319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski                                                    const void* origin,
885319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski                                                    Activity::Type type,
886319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski                                                    const ActivityData& data) {
887319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski  // A thread-checker creates a lock to check the thread-id which means
888319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski  // re-entry into this code if lock acquisitions are being tracked.
889319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski  DCHECK(thread_checker_.CalledOnValidThread());
890319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski
891319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski  // Fill the reusable exception activity.
892319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski  Activity::FillFrom(&header_->last_exception, program_counter, origin, type,
893319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski                     data);
894319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski
895319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski  // The data has changed meaning that some other thread trying to copy the
896319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski  // contents for reporting purposes could get bad data.
897319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski  header_->data_unchanged.store(0, std::memory_order_relaxed);
898319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski}
899319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski
90036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abebool ThreadActivityTracker::IsValid() const {
901319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski  if (header_->owner.data_id.load(std::memory_order_acquire) == 0 ||
902319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski      header_->owner.process_id == 0 || header_->thread_ref.as_id == 0 ||
903319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski      header_->start_time == 0 || header_->start_ticks == 0 ||
90436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe      header_->stack_slots != stack_slots_ ||
90536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe      header_->thread_name[sizeof(header_->thread_name) - 1] != '\0') {
90636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    return false;
90736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  }
90836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe
90936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  return valid_;
91036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe}
91136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe
91236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abebool ThreadActivityTracker::CreateSnapshot(Snapshot* output_snapshot) const {
91336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  DCHECK(output_snapshot);
91436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe
91536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  // There is no "called on valid thread" check for this method as it can be
91636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  // called from other threads or even other processes. It is also the reason
91736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  // why atomic operations must be used in certain places above.
91836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe
91936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  // It's possible for the data to change while reading it in such a way that it
92036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  // invalidates the read. Make several attempts but don't try forever.
92136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  const int kMaxAttempts = 10;
92236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  uint32_t depth;
92336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe
92436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  // Stop here if the data isn't valid.
92536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  if (!IsValid())
92636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    return false;
92736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe
92836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  // Allocate the maximum size for the stack so it doesn't have to be done
92936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  // during the time-sensitive snapshot operation. It is shrunk once the
93036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  // actual size is known.
93136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  output_snapshot->activity_stack.reserve(stack_slots_);
93236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe
93336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  for (int attempt = 0; attempt < kMaxAttempts; ++attempt) {
934319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski    // Remember the data IDs to ensure nothing is replaced during the snapshot
935319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski    // operation. Use "acquire" so that all the non-atomic fields of the
936319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski    // structure are valid (at least at the current moment in time).
937319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski    const uint32_t starting_id =
938319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski        header_->owner.data_id.load(std::memory_order_acquire);
939f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe    const int64_t starting_create_stamp = header_->owner.create_stamp;
940319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski    const int64_t starting_process_id = header_->owner.process_id;
94136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    const int64_t starting_thread_id = header_->thread_ref.as_id;
94236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe
943319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski    // Write a non-zero value to |data_unchanged| so it's possible to detect
94436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    // at the end that nothing has changed since copying the data began. A
94536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    // "cst" operation is required to ensure it occurs before everything else.
94636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    // Using "cst" memory ordering is relatively expensive but this is only
94736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    // done during analysis so doesn't directly affect the worker threads.
948319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski    header_->data_unchanged.store(1, std::memory_order_seq_cst);
94936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe
95036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    // Fetching the current depth also "acquires" the contents of the stack.
95136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    depth = header_->current_depth.load(std::memory_order_acquire);
95236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    uint32_t count = std::min(depth, stack_slots_);
95336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    output_snapshot->activity_stack.resize(count);
95436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    if (count > 0) {
95536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe      // Copy the existing contents. Memcpy is used for speed.
95636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe      memcpy(&output_snapshot->activity_stack[0], stack_,
95736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe             count * sizeof(Activity));
95836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    }
95936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe
960319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski    // Capture the last exception.
961319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski    memcpy(&output_snapshot->last_exception, &header_->last_exception,
962319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski           sizeof(Activity));
963319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski
964319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski    // TODO(bcwhite): Snapshot other things here.
965319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski
96636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    // Retry if something changed during the copy. A "cst" operation ensures
96736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    // it must happen after all the above operations.
968319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski    if (!header_->data_unchanged.load(std::memory_order_seq_cst))
96936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe      continue;
97036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe
97136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    // Stack copied. Record it's full depth.
97236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    output_snapshot->activity_stack_depth = depth;
97336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe
974319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski    // Get the general thread information.
97536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    output_snapshot->thread_name =
97636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe        std::string(header_->thread_name, sizeof(header_->thread_name) - 1);
977f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe    output_snapshot->create_stamp = header_->owner.create_stamp;
97836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    output_snapshot->thread_id = header_->thread_ref.as_id;
979319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski    output_snapshot->process_id = header_->owner.process_id;
98036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe
98136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    // All characters of the thread-name buffer were copied so as to not break
98236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    // if the trailing NUL were missing. Now limit the length if the actual
98336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    // name is shorter.
98436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    output_snapshot->thread_name.resize(
98536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe        strlen(output_snapshot->thread_name.c_str()));
98636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe
987319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski    // If the data ID has changed then the tracker has exited and the memory
988319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski    // reused by a new one. Try again.
989319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski    if (header_->owner.data_id.load(std::memory_order_seq_cst) != starting_id ||
990f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe        output_snapshot->create_stamp != starting_create_stamp ||
991319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski        output_snapshot->process_id != starting_process_id ||
99236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe        output_snapshot->thread_id != starting_thread_id) {
99336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe      continue;
99436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    }
99536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe
99636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    // Only successful if the data is still valid once everything is done since
99736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    // it's possible for the thread to end somewhere in the middle and all its
99836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    // values become garbage.
99936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    if (!IsValid())
100036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe      return false;
100136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe
100236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    // Change all the timestamps in the activities from "ticks" to "wall" time.
100336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    const Time start_time = Time::FromInternalValue(header_->start_time);
100436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    const int64_t start_ticks = header_->start_ticks;
100536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    for (Activity& activity : output_snapshot->activity_stack) {
100636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe      activity.time_internal =
1007319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski          WallTimeFromTickTime(start_ticks, activity.time_internal, start_time)
100836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe              .ToInternalValue();
100936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    }
1010319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski    output_snapshot->last_exception.time_internal =
1011319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski        WallTimeFromTickTime(start_ticks,
1012319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski                             output_snapshot->last_exception.time_internal,
1013319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski                             start_time)
1014319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski            .ToInternalValue();
101536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe
101636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    // Success!
101736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    return true;
101836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  }
101936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe
102036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  // Too many attempts.
102136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  return false;
102236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe}
102336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe
1024319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowskiconst void* ThreadActivityTracker::GetBaseAddress() {
1025319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski  return header_;
1026319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski}
1027319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski
1028f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abevoid ThreadActivityTracker::SetOwningProcessIdForTesting(int64_t pid,
1029319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski                                                         int64_t stamp) {
1030319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski  header_->owner.SetOwningProcessIdForTesting(pid, stamp);
1031319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski}
1032319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski
1033319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski// static
1034319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowskibool ThreadActivityTracker::GetOwningProcessId(const void* memory,
1035f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe                                               int64_t* out_id,
1036319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski                                               int64_t* out_stamp) {
1037319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski  const Header* header = reinterpret_cast<const Header*>(memory);
1038319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski  return OwningProcess::GetOwningProcessId(&header->owner, out_id, out_stamp);
1039319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski}
1040319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski
104136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe// static
104236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abesize_t ThreadActivityTracker::SizeForStackDepth(int stack_depth) {
104336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  return static_cast<size_t>(stack_depth) * sizeof(Activity) + sizeof(Header);
104436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe}
104536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe
1046319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowskistd::unique_ptr<ActivityUserData>
1047319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub PawlowskiThreadActivityTracker::CreateUserDataForActivity(
1048319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski    Activity* activity,
1049319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski    ActivityTrackerMemoryAllocator* allocator) {
1050319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski  DCHECK_EQ(0U, activity->user_data_ref);
1051319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski
1052319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski  PersistentMemoryAllocator::Reference ref = allocator->GetObjectReference();
1053319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski  void* memory = allocator->GetAsArray<char>(ref, kUserDataSize);
1054319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski  if (memory) {
1055319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski    std::unique_ptr<ActivityUserData> user_data =
1056319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski        MakeUnique<ActivityUserData>(memory, kUserDataSize);
1057319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski    activity->user_data_ref = ref;
1058319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski    activity->user_data_id = user_data->id();
1059319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski    return user_data;
1060319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski  }
1061319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski
1062319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski  // Return a dummy object that will still accept (but ignore) Set() calls.
1063319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski  return MakeUnique<ActivityUserData>();
1064319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski}
1065319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski
106636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe// The instantiation of the GlobalActivityTracker object.
106736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe// The object held here will obviously not be destructed at process exit
106836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe// but that's best since PersistentMemoryAllocator objects (that underlie
106936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe// GlobalActivityTracker objects) are explicitly forbidden from doing anything
107036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe// essential at exit anyway due to the fact that they depend on data managed
107136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe// elsewhere and which could be destructed first. An AtomicWord is used instead
107236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe// of std::atomic because the latter can create global ctors and dtors.
107336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abesubtle::AtomicWord GlobalActivityTracker::g_tracker_ = 0;
107436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe
107536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko AbeGlobalActivityTracker::ModuleInfo::ModuleInfo() {}
107636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko AbeGlobalActivityTracker::ModuleInfo::ModuleInfo(ModuleInfo&& rhs) = default;
107736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko AbeGlobalActivityTracker::ModuleInfo::ModuleInfo(const ModuleInfo& rhs) = default;
107836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko AbeGlobalActivityTracker::ModuleInfo::~ModuleInfo() {}
107936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe
108036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko AbeGlobalActivityTracker::ModuleInfo& GlobalActivityTracker::ModuleInfo::operator=(
108136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    ModuleInfo&& rhs) = default;
108236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko AbeGlobalActivityTracker::ModuleInfo& GlobalActivityTracker::ModuleInfo::operator=(
108336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    const ModuleInfo& rhs) = default;
108436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe
108536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko AbeGlobalActivityTracker::ModuleInfoRecord::ModuleInfoRecord() {}
108636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko AbeGlobalActivityTracker::ModuleInfoRecord::~ModuleInfoRecord() {}
108736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe
108836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abebool GlobalActivityTracker::ModuleInfoRecord::DecodeTo(
108936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    GlobalActivityTracker::ModuleInfo* info,
109036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    size_t record_size) const {
109136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  // Get the current "changes" indicator, acquiring all the other values.
109236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  uint32_t current_changes = changes.load(std::memory_order_acquire);
109336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe
109436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  // Copy out the dynamic information.
109536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  info->is_loaded = loaded != 0;
109636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  info->address = static_cast<uintptr_t>(address);
109736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  info->load_time = load_time;
109836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe
109936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  // Check to make sure no information changed while being read. A "seq-cst"
110036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  // operation is expensive but is only done during analysis and it's the only
110136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  // way to ensure this occurs after all the accesses above. If changes did
110236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  // occur then return a "not loaded" result so that |size| and |address|
110336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  // aren't expected to be accurate.
110436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  if ((current_changes & kModuleInformationChanging) != 0 ||
110536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe      changes.load(std::memory_order_seq_cst) != current_changes) {
110636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    info->is_loaded = false;
110736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  }
110836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe
110936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  // Copy out the static information. These never change so don't have to be
111036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  // protected by the atomic |current_changes| operations.
111136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  info->size = static_cast<size_t>(size);
111236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  info->timestamp = timestamp;
111336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  info->age = age;
111436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  memcpy(info->identifier, identifier, sizeof(info->identifier));
111536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe
111636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  if (offsetof(ModuleInfoRecord, pickle) + pickle_size > record_size)
111736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    return false;
111836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  Pickle pickler(pickle, pickle_size);
111936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  PickleIterator iter(pickler);
112036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  return iter.ReadString(&info->file) && iter.ReadString(&info->debug_file);
112136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe}
112236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe
112336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abebool GlobalActivityTracker::ModuleInfoRecord::EncodeFrom(
112436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    const GlobalActivityTracker::ModuleInfo& info,
112536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    size_t record_size) {
112636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  Pickle pickler;
112736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  bool okay =
112836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe      pickler.WriteString(info.file) && pickler.WriteString(info.debug_file);
112936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  if (!okay) {
113036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    NOTREACHED();
113136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    return false;
113236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  }
113336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  if (offsetof(ModuleInfoRecord, pickle) + pickler.size() > record_size) {
113436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    NOTREACHED();
113536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    return false;
113636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  }
113736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe
113836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  // These fields never changes and are done before the record is made
113936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  // iterable so no thread protection is necessary.
114036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  size = info.size;
114136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  timestamp = info.timestamp;
114236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  age = info.age;
114336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  memcpy(identifier, info.identifier, sizeof(identifier));
114436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  memcpy(pickle, pickler.data(), pickler.size());
114536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  pickle_size = pickler.size();
114636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  changes.store(0, std::memory_order_relaxed);
114736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe
1148319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski  // Initialize the owner info.
1149319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski  owner.Release_Initialize();
1150319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski
115136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  // Now set those fields that can change.
115236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  return UpdateFrom(info);
115336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe}
115436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe
115536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abebool GlobalActivityTracker::ModuleInfoRecord::UpdateFrom(
115636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    const GlobalActivityTracker::ModuleInfo& info) {
115736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  // Updates can occur after the record is made visible so make changes atomic.
115836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  // A "strong" exchange ensures no false failures.
115936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  uint32_t old_changes = changes.load(std::memory_order_relaxed);
116036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  uint32_t new_changes = old_changes | kModuleInformationChanging;
116136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  if ((old_changes & kModuleInformationChanging) != 0 ||
116236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe      !changes.compare_exchange_strong(old_changes, new_changes,
116336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe                                       std::memory_order_acquire,
116436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe                                       std::memory_order_acquire)) {
116536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    NOTREACHED() << "Multiple sources are updating module information.";
116636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    return false;
116736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  }
116836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe
116936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  loaded = info.is_loaded ? 1 : 0;
117036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  address = info.address;
117136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  load_time = Time::Now().ToInternalValue();
117236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe
117336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  bool success = changes.compare_exchange_strong(new_changes, old_changes + 1,
117436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe                                                 std::memory_order_release,
117536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe                                                 std::memory_order_relaxed);
117636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  DCHECK(success);
117736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  return true;
117836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe}
117936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe
118036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe// static
118136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abesize_t GlobalActivityTracker::ModuleInfoRecord::EncodedSize(
118236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    const GlobalActivityTracker::ModuleInfo& info) {
118336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  PickleSizer sizer;
118436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  sizer.AddString(info.file);
118536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  sizer.AddString(info.debug_file);
118636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe
118736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  return offsetof(ModuleInfoRecord, pickle) + sizeof(Pickle::Header) +
118836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe         sizer.payload_size();
118936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe}
119036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe
119136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko AbeGlobalActivityTracker::ScopedThreadActivity::ScopedThreadActivity(
119236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    const void* program_counter,
119336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    const void* origin,
119436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    Activity::Type type,
119536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    const ActivityData& data,
119636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    bool lock_allowed)
119736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    : ThreadActivityTracker::ScopedActivity(GetOrCreateTracker(lock_allowed),
119836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe                                            program_counter,
119936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe                                            origin,
120036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe                                            type,
120136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe                                            data) {}
120236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe
120336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko AbeGlobalActivityTracker::ScopedThreadActivity::~ScopedThreadActivity() {
120436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  if (tracker_ && tracker_->HasUserData(activity_id_)) {
120536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    GlobalActivityTracker* global = GlobalActivityTracker::Get();
120636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    AutoLock lock(global->user_data_allocator_lock_);
120736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    tracker_->ReleaseUserData(activity_id_, &global->user_data_allocator_);
120836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  }
120936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe}
121036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe
121136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko AbeActivityUserData& GlobalActivityTracker::ScopedThreadActivity::user_data() {
121236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  if (!user_data_) {
121336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    if (tracker_) {
121436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe      GlobalActivityTracker* global = GlobalActivityTracker::Get();
121536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe      AutoLock lock(global->user_data_allocator_lock_);
121636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe      user_data_ =
121736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe          tracker_->GetUserData(activity_id_, &global->user_data_allocator_);
121836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    } else {
1219319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski      user_data_ = MakeUnique<ActivityUserData>();
122036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    }
122136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  }
122236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  return *user_data_;
122336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe}
122436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe
1225319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub PawlowskiGlobalActivityTracker::ThreadSafeUserData::ThreadSafeUserData(void* memory,
1226f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe                                                              size_t size,
1227f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe                                                              int64_t pid)
1228f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe    : ActivityUserData(memory, size, pid) {}
122936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe
1230319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub PawlowskiGlobalActivityTracker::ThreadSafeUserData::~ThreadSafeUserData() {}
123136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe
1232319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowskivoid GlobalActivityTracker::ThreadSafeUserData::Set(StringPiece name,
1233319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski                                                    ValueType type,
1234319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski                                                    const void* memory,
1235319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski                                                    size_t size) {
123636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  AutoLock lock(data_lock_);
123736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  ActivityUserData::Set(name, type, memory, size);
123836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe}
123936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe
124036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko AbeGlobalActivityTracker::ManagedActivityTracker::ManagedActivityTracker(
124136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    PersistentMemoryAllocator::Reference mem_reference,
124236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    void* base,
124336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    size_t size)
124436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    : ThreadActivityTracker(base, size),
124536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe      mem_reference_(mem_reference),
124636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe      mem_base_(base) {}
124736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe
124836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko AbeGlobalActivityTracker::ManagedActivityTracker::~ManagedActivityTracker() {
124936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  // The global |g_tracker_| must point to the owner of this class since all
125036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  // objects of this type must be destructed before |g_tracker_| can be changed
125136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  // (something that only occurs in tests).
125236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  DCHECK(g_tracker_);
125336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  GlobalActivityTracker::Get()->ReturnTrackerMemory(this);
125436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe}
125536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe
125636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abevoid GlobalActivityTracker::CreateWithAllocator(
125736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    std::unique_ptr<PersistentMemoryAllocator> allocator,
1258f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe    int stack_depth,
1259f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe    int64_t process_id) {
126036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  // There's no need to do anything with the result. It is self-managing.
126136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  GlobalActivityTracker* global_tracker =
1262f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe      new GlobalActivityTracker(std::move(allocator), stack_depth, process_id);
126336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  // Create a tracker for this thread since it is known.
126436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  global_tracker->CreateTrackerForCurrentThread();
126536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe}
126636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe
126736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe#if !defined(OS_NACL)
126836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe// static
126936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abevoid GlobalActivityTracker::CreateWithFile(const FilePath& file_path,
127036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe                                           size_t size,
127136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe                                           uint64_t id,
127236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe                                           StringPiece name,
127336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe                                           int stack_depth) {
127436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  DCHECK(!file_path.empty());
127536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  DCHECK_GE(static_cast<uint64_t>(std::numeric_limits<int64_t>::max()), size);
127636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe
127736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  // Create and map the file into memory and make it globally available.
127836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  std::unique_ptr<MemoryMappedFile> mapped_file(new MemoryMappedFile());
127936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  bool success =
128036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe      mapped_file->Initialize(File(file_path,
128136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe                                   File::FLAG_CREATE_ALWAYS | File::FLAG_READ |
128236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe                                   File::FLAG_WRITE | File::FLAG_SHARE_DELETE),
128336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe                              {0, static_cast<int64_t>(size)},
128436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe                              MemoryMappedFile::READ_WRITE_EXTEND);
128536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  DCHECK(success);
128636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  CreateWithAllocator(MakeUnique<FilePersistentMemoryAllocator>(
128736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe                          std::move(mapped_file), size, id, name, false),
1288f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe                      stack_depth, 0);
128936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe}
129036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe#endif  // !defined(OS_NACL)
129136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe
129236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe// static
129336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abevoid GlobalActivityTracker::CreateWithLocalMemory(size_t size,
129436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe                                                  uint64_t id,
129536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe                                                  StringPiece name,
1296f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe                                                  int stack_depth,
1297f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe                                                  int64_t process_id) {
129836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  CreateWithAllocator(
1299f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe      MakeUnique<LocalPersistentMemoryAllocator>(size, id, name), stack_depth,
1300f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe      process_id);
1301f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe}
1302f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe
1303f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe// static
1304f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abevoid GlobalActivityTracker::SetForTesting(
1305f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe    std::unique_ptr<GlobalActivityTracker> tracker) {
1306f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe  CHECK(!subtle::NoBarrier_Load(&g_tracker_));
1307f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe  subtle::Release_Store(&g_tracker_,
1308f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe                        reinterpret_cast<uintptr_t>(tracker.release()));
130936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe}
131036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe
1311f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe// static
1312f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abestd::unique_ptr<GlobalActivityTracker>
1313f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko AbeGlobalActivityTracker::ReleaseForTesting() {
1314f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe  GlobalActivityTracker* tracker = Get();
1315f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe  if (!tracker)
1316f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe    return nullptr;
1317f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe
1318f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe  // Thread trackers assume that the global tracker is present for some
1319f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe  // operations so ensure that there aren't any.
1320f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe  tracker->ReleaseTrackerForCurrentThreadForTesting();
1321f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe  DCHECK_EQ(0, tracker->thread_tracker_count_.load(std::memory_order_relaxed));
1322f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe
1323f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe  subtle::Release_Store(&g_tracker_, 0);
1324f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe  return WrapUnique(tracker);
1325f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe};
1326f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe
132736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko AbeThreadActivityTracker* GlobalActivityTracker::CreateTrackerForCurrentThread() {
132836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  DCHECK(!this_thread_tracker_.Get());
132936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe
133036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  PersistentMemoryAllocator::Reference mem_reference;
133136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe
133236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  {
133336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    base::AutoLock autolock(thread_tracker_allocator_lock_);
133436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    mem_reference = thread_tracker_allocator_.GetObjectReference();
133536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  }
133636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe
133736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  if (!mem_reference) {
133836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    // Failure. This shouldn't happen. But be graceful if it does, probably
133936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    // because the underlying allocator wasn't given enough memory to satisfy
134036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    // to all possible requests.
134136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    NOTREACHED();
134236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    // Report the thread-count at which the allocator was full so that the
134336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    // failure can be seen and underlying memory resized appropriately.
134436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    UMA_HISTOGRAM_COUNTS_1000(
134536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe        "ActivityTracker.ThreadTrackers.MemLimitTrackerCount",
134636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe        thread_tracker_count_.load(std::memory_order_relaxed));
134736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    // Return null, just as if tracking wasn't enabled.
134836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    return nullptr;
134936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  }
135036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe
135136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  // Convert the memory block found above into an actual memory address.
135236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  // Doing the conversion as a Header object enacts the 32/64-bit size
135336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  // consistency checks which would not otherwise be done. Unfortunately,
135436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  // some older compilers and MSVC don't have standard-conforming definitions
135536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  // of std::atomic which cause it not to be plain-old-data. Don't check on
135636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  // those platforms assuming that the checks on other platforms will be
135736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  // sufficient.
135836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  // TODO(bcwhite): Review this after major compiler releases.
135936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  DCHECK(mem_reference);
136036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  void* mem_base;
136136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  mem_base =
136236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe      allocator_->GetAsObject<ThreadActivityTracker::Header>(mem_reference);
136336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe
136436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  DCHECK(mem_base);
136536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  DCHECK_LE(stack_memory_size_, allocator_->GetAllocSize(mem_reference));
136636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe
136736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  // Create a tracker with the acquired memory and set it as the tracker
136836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  // for this particular thread in thread-local-storage.
136936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  ManagedActivityTracker* tracker =
137036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe      new ManagedActivityTracker(mem_reference, mem_base, stack_memory_size_);
137136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  DCHECK(tracker->IsValid());
137236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  this_thread_tracker_.Set(tracker);
137336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  int old_count = thread_tracker_count_.fetch_add(1, std::memory_order_relaxed);
137436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe
137536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  UMA_HISTOGRAM_ENUMERATION("ActivityTracker.ThreadTrackers.Count",
137636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe                            old_count + 1, kMaxThreadCount);
137736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  return tracker;
137836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe}
137936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe
138036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abevoid GlobalActivityTracker::ReleaseTrackerForCurrentThreadForTesting() {
138136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  ThreadActivityTracker* tracker =
138236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe      reinterpret_cast<ThreadActivityTracker*>(this_thread_tracker_.Get());
1383f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe  if (tracker) {
1384f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe    this_thread_tracker_.Set(nullptr);
138536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    delete tracker;
1386f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe  }
138736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe}
138836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe
1389319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowskivoid GlobalActivityTracker::SetBackgroundTaskRunner(
1390319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski    const scoped_refptr<TaskRunner>& runner) {
1391319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski  AutoLock lock(global_tracker_lock_);
1392319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski  background_task_runner_ = runner;
1393319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski}
1394319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski
1395319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowskivoid GlobalActivityTracker::SetProcessExitCallback(
1396319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski    ProcessExitCallback callback) {
1397319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski  AutoLock lock(global_tracker_lock_);
1398319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski  process_exit_callback_ = callback;
1399319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski}
1400319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski
1401319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowskivoid GlobalActivityTracker::RecordProcessLaunch(
1402319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski    ProcessId process_id,
1403319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski    const FilePath::StringType& cmd) {
1404f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe  const int64_t pid = process_id;
1405f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe  DCHECK_NE(GetProcessId(), pid);
1406f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe  DCHECK_NE(0, pid);
1407319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski
1408319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski  base::AutoLock lock(global_tracker_lock_);
1409f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe  if (base::ContainsKey(known_processes_, pid)) {
1410319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski    // TODO(bcwhite): Measure this in UMA.
1411319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski    NOTREACHED() << "Process #" << process_id
1412319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski                 << " was previously recorded as \"launched\""
1413319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski                 << " with no corresponding exit.";
1414f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe    known_processes_.erase(pid);
1415319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski  }
1416319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski
1417319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski#if defined(OS_WIN)
1418f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe  known_processes_.insert(std::make_pair(pid, UTF16ToUTF8(cmd)));
1419319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski#else
1420f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe  known_processes_.insert(std::make_pair(pid, cmd));
1421319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski#endif
1422319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski}
1423319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski
1424319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowskivoid GlobalActivityTracker::RecordProcessLaunch(
1425319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski    ProcessId process_id,
1426319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski    const FilePath::StringType& exe,
1427319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski    const FilePath::StringType& args) {
1428f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe  const int64_t pid = process_id;
1429319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski  if (exe.find(FILE_PATH_LITERAL(" "))) {
1430f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe    RecordProcessLaunch(pid, FilePath::StringType(FILE_PATH_LITERAL("\"")) +
1431f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe                                 exe + FILE_PATH_LITERAL("\" ") + args);
1432319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski  } else {
1433f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe    RecordProcessLaunch(pid, exe + FILE_PATH_LITERAL(' ') + args);
1434319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski  }
1435319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski}
1436319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski
1437319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowskivoid GlobalActivityTracker::RecordProcessExit(ProcessId process_id,
1438319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski                                              int exit_code) {
1439f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe  const int64_t pid = process_id;
1440f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe  DCHECK_NE(GetProcessId(), pid);
1441f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe  DCHECK_NE(0, pid);
1442319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski
1443319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski  scoped_refptr<TaskRunner> task_runner;
1444319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski  std::string command_line;
1445319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski  {
1446319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski    base::AutoLock lock(global_tracker_lock_);
1447319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski    task_runner = background_task_runner_;
1448f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe    auto found = known_processes_.find(pid);
1449319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski    if (found != known_processes_.end()) {
1450319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski      command_line = std::move(found->second);
1451319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski      known_processes_.erase(found);
1452319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski    } else {
1453319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski      DLOG(ERROR) << "Recording exit of unknown process #" << process_id;
1454319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski    }
1455319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski  }
1456319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski
1457319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski  // Use the current time to differentiate the process that just exited
1458319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski  // from any that might be created in the future with the same ID.
1459319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski  int64_t now_stamp = Time::Now().ToInternalValue();
1460319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski
1461319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski  // The persistent allocator is thread-safe so run the iteration and
1462319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski  // adjustments on a worker thread if one was provided.
1463319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski  if (task_runner && !task_runner->RunsTasksOnCurrentThread()) {
1464319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski    task_runner->PostTask(
1465319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski        FROM_HERE,
1466f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe        Bind(&GlobalActivityTracker::CleanupAfterProcess, Unretained(this), pid,
1467f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe             now_stamp, exit_code, Passed(&command_line)));
1468319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski    return;
1469319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski  }
1470319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski
1471f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe  CleanupAfterProcess(pid, now_stamp, exit_code, std::move(command_line));
1472319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski}
1473319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski
1474319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowskivoid GlobalActivityTracker::SetProcessPhase(ProcessPhase phase) {
1475319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski  process_data().SetInt(kProcessPhaseDataKey, phase);
1476319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski}
1477319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski
1478f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abevoid GlobalActivityTracker::CleanupAfterProcess(int64_t process_id,
1479319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski                                                int64_t exit_stamp,
1480319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski                                                int exit_code,
1481319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski                                                std::string&& command_line) {
1482319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski  // The process may not have exited cleanly so its necessary to go through
1483319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski  // all the data structures it may have allocated in the persistent memory
1484319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski  // segment and mark them as "released". This will allow them to be reused
1485319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski  // later on.
1486319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski
1487319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski  PersistentMemoryAllocator::Iterator iter(allocator_.get());
1488319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski  PersistentMemoryAllocator::Reference ref;
1489319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski
1490319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski  ProcessExitCallback process_exit_callback;
1491319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski  {
1492319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski    AutoLock lock(global_tracker_lock_);
1493319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski    process_exit_callback = process_exit_callback_;
1494319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski  }
1495319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski  if (process_exit_callback) {
1496319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski    // Find the processes user-data record so the process phase can be passed
1497319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski    // to the callback.
1498319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski    ActivityUserData::Snapshot process_data_snapshot;
1499319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski    while ((ref = iter.GetNextOfType(kTypeIdProcessDataRecord)) != 0) {
1500319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski      const void* memory = allocator_->GetAsArray<char>(
1501319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski          ref, kTypeIdProcessDataRecord, PersistentMemoryAllocator::kSizeAny);
1502f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe      int64_t found_id;
1503319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski      int64_t create_stamp;
1504319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski      if (ActivityUserData::GetOwningProcessId(memory, &found_id,
1505319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski                                               &create_stamp)) {
1506319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski        if (found_id == process_id && create_stamp < exit_stamp) {
1507319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski          const ActivityUserData process_data(const_cast<void*>(memory),
1508319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski                                              allocator_->GetAllocSize(ref));
1509319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski          process_data.CreateSnapshot(&process_data_snapshot);
1510319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski          break;  // No need to look for any others.
1511319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski        }
1512319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski      }
1513319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski    }
1514319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski    iter.Reset();  // So it starts anew when used below.
1515319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski
1516319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski    // Record the process's phase at exit so callback doesn't need to go
1517319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski    // searching based on a private key value.
1518319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski    ProcessPhase exit_phase = PROCESS_PHASE_UNKNOWN;
1519319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski    auto phase = process_data_snapshot.find(kProcessPhaseDataKey);
1520319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski    if (phase != process_data_snapshot.end())
1521319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski      exit_phase = static_cast<ProcessPhase>(phase->second.GetInt());
1522319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski
1523319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski    // Perform the callback.
1524319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski    process_exit_callback.Run(process_id, exit_stamp, exit_code, exit_phase,
1525319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski                              std::move(command_line),
1526319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski                              std::move(process_data_snapshot));
1527319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski  }
1528319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski
1529319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski  // Find all allocations associated with the exited process and free them.
1530319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski  uint32_t type;
1531319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski  while ((ref = iter.GetNext(&type)) != 0) {
1532319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski    switch (type) {
1533319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski      case kTypeIdActivityTracker:
1534319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski      case kTypeIdUserDataRecord:
1535319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski      case kTypeIdProcessDataRecord:
1536319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski      case ModuleInfoRecord::kPersistentTypeId: {
1537319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski        const void* memory = allocator_->GetAsArray<char>(
1538319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski            ref, type, PersistentMemoryAllocator::kSizeAny);
1539f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe        int64_t found_id;
1540319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski        int64_t create_stamp;
1541319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski
1542319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski        // By convention, the OwningProcess structure is always the first
1543319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski        // field of the structure so there's no need to handle all the
1544319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski        // cases separately.
1545319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski        if (OwningProcess::GetOwningProcessId(memory, &found_id,
1546319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski                                              &create_stamp)) {
1547319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski          // Only change the type to be "free" if the process ID matches and
1548319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski          // the creation time is before the exit time (so PID re-use doesn't
1549319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski          // cause the erasure of something that is in-use). Memory is cleared
1550319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski          // here, rather than when it's needed, so as to limit the impact at
1551319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski          // that critical time.
1552319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski          if (found_id == process_id && create_stamp < exit_stamp)
1553319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski            allocator_->ChangeType(ref, ~type, type, /*clear=*/true);
1554319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski        }
1555319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski      } break;
1556319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski    }
1557319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski  }
1558319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski}
1559319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski
156036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abevoid GlobalActivityTracker::RecordLogMessage(StringPiece message) {
156136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  // Allocate at least one extra byte so the string is NUL terminated. All
156236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  // memory returned by the allocator is guaranteed to be zeroed.
156336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  PersistentMemoryAllocator::Reference ref =
156436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe      allocator_->Allocate(message.size() + 1, kTypeIdGlobalLogMessage);
156536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  char* memory = allocator_->GetAsArray<char>(ref, kTypeIdGlobalLogMessage,
156636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe                                              message.size() + 1);
156736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  if (memory) {
156836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    memcpy(memory, message.data(), message.size());
156936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    allocator_->MakeIterable(ref);
157036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  }
157136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe}
157236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe
157336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abevoid GlobalActivityTracker::RecordModuleInfo(const ModuleInfo& info) {
157436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  AutoLock lock(modules_lock_);
157536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  auto found = modules_.find(info.file);
157636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  if (found != modules_.end()) {
157736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    ModuleInfoRecord* record = found->second;
157836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    DCHECK(record);
157936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe
158036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    // Update the basic state of module information that has been already
158136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    // recorded. It is assumed that the string information (identifier,
158236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    // version, etc.) remain unchanged which means that there's no need
158336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    // to create a new record to accommodate a possibly longer length.
158436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    record->UpdateFrom(info);
158536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    return;
158636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  }
158736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe
158836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  size_t required_size = ModuleInfoRecord::EncodedSize(info);
158936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  ModuleInfoRecord* record = allocator_->New<ModuleInfoRecord>(required_size);
159036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  if (!record)
159136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    return;
159236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe
159336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  bool success = record->EncodeFrom(info, required_size);
159436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  DCHECK(success);
159536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  allocator_->MakeIterable(record);
159636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  modules_.insert(std::make_pair(info.file, record));
159736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe}
159836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe
159936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abevoid GlobalActivityTracker::RecordFieldTrial(const std::string& trial_name,
160036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe                                             StringPiece group_name) {
160136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  const std::string key = std::string("FieldTrial.") + trial_name;
160236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  global_data_.SetString(key, group_name);
160336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe}
160436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe
160536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko AbeGlobalActivityTracker::GlobalActivityTracker(
160636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    std::unique_ptr<PersistentMemoryAllocator> allocator,
1607f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe    int stack_depth,
1608f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe    int64_t process_id)
160936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    : allocator_(std::move(allocator)),
161036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe      stack_memory_size_(ThreadActivityTracker::SizeForStackDepth(stack_depth)),
1611f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe      process_id_(process_id == 0 ? GetCurrentProcId() : process_id),
161236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe      this_thread_tracker_(&OnTLSDestroy),
161336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe      thread_tracker_count_(0),
161436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe      thread_tracker_allocator_(allocator_.get(),
161536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe                                kTypeIdActivityTracker,
161636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe                                kTypeIdActivityTrackerFree,
161736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe                                stack_memory_size_,
161836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe                                kCachedThreadMemories,
161936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe                                /*make_iterable=*/true),
162036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe      user_data_allocator_(allocator_.get(),
162136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe                           kTypeIdUserDataRecord,
162236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe                           kTypeIdUserDataRecordFree,
162336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe                           kUserDataSize,
162436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe                           kCachedUserDataMemories,
1625319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski                           /*make_iterable=*/true),
1626319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski      process_data_(allocator_->GetAsArray<char>(
1627319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski                        AllocateFrom(allocator_.get(),
1628319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski                                     kTypeIdProcessDataRecordFree,
1629319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski                                     kProcessDataSize,
1630319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski                                     kTypeIdProcessDataRecord),
1631319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski                        kTypeIdProcessDataRecord,
1632319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski                        kProcessDataSize),
1633f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe                    kProcessDataSize,
1634f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe                    process_id_),
163536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe      global_data_(
163636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe          allocator_->GetAsArray<char>(
163736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe              allocator_->Allocate(kGlobalDataSize, kTypeIdGlobalDataRecord),
163836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe              kTypeIdGlobalDataRecord,
1639319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski              kGlobalDataSize),
1640f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe          kGlobalDataSize,
1641f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe          process_id_) {
1642f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe  DCHECK_NE(0, process_id_);
164336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe
164436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  // Ensure that there is no other global object and then make this one such.
164536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  DCHECK(!g_tracker_);
164636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  subtle::Release_Store(&g_tracker_, reinterpret_cast<uintptr_t>(this));
164736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe
1648319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski  // The data records must be iterable in order to be found by an analyzer.
1649319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski  allocator_->MakeIterable(allocator_->GetAsReference(
1650319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski      process_data_.GetBaseAddress(), kTypeIdProcessDataRecord));
165136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  allocator_->MakeIterable(allocator_->GetAsReference(
165236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe      global_data_.GetBaseAddress(), kTypeIdGlobalDataRecord));
165336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe
1654319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski  // Note that this process has launched.
1655319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski  SetProcessPhase(PROCESS_LAUNCHED);
1656319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski
165736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  // Fetch and record all activated field trials.
165836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  FieldTrial::ActiveGroups active_groups;
165936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  FieldTrialList::GetActiveFieldTrialGroups(&active_groups);
166036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  for (auto& group : active_groups)
166136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    RecordFieldTrial(group.trial_name, group.group_name);
166236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe}
166336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe
166436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko AbeGlobalActivityTracker::~GlobalActivityTracker() {
1665f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe  DCHECK(Get() == nullptr || Get() == this);
166636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  DCHECK_EQ(0, thread_tracker_count_.load(std::memory_order_relaxed));
166736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  subtle::Release_Store(&g_tracker_, 0);
166836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe}
166936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe
167036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abevoid GlobalActivityTracker::ReturnTrackerMemory(
167136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    ManagedActivityTracker* tracker) {
167236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  PersistentMemoryAllocator::Reference mem_reference = tracker->mem_reference_;
167336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  void* mem_base = tracker->mem_base_;
167436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  DCHECK(mem_reference);
167536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  DCHECK(mem_base);
167636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe
167736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  // Remove the destructed tracker from the set of known ones.
167836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  DCHECK_LE(1, thread_tracker_count_.load(std::memory_order_relaxed));
167936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  thread_tracker_count_.fetch_sub(1, std::memory_order_relaxed);
168036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe
168136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  // Release this memory for re-use at a later time.
168236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  base::AutoLock autolock(thread_tracker_allocator_lock_);
168336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  thread_tracker_allocator_.ReleaseObjectReference(mem_reference);
168436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe}
168536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe
1686319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowskivoid GlobalActivityTracker::RecordExceptionImpl(const void* pc,
1687319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski                                                const void* origin,
1688319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski                                                uint32_t code) {
1689319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski  // Get an existing tracker for this thread. It's not possible to create
1690319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski  // one at this point because such would involve memory allocations and
1691319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski  // other potentially complex operations that can cause failures if done
1692319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski  // within an exception handler. In most cases various operations will
1693319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski  // have already created the tracker so this shouldn't generally be a
1694319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski  // problem.
1695319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski  ThreadActivityTracker* tracker = GetTrackerForCurrentThread();
1696319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski  if (!tracker)
1697319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski    return;
1698319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski
1699319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski  tracker->RecordExceptionActivity(pc, origin, Activity::ACT_EXCEPTION,
1700319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski                                   ActivityData::ForException(code));
1701319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski}
1702319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski
170336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe// static
170436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abevoid GlobalActivityTracker::OnTLSDestroy(void* value) {
170536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  delete reinterpret_cast<ManagedActivityTracker*>(value);
170636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe}
170736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe
170836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko AbeScopedActivity::ScopedActivity(const void* program_counter,
170936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe                               uint8_t action,
171036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe                               uint32_t id,
171136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe                               int32_t info)
171236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    : GlobalActivityTracker::ScopedThreadActivity(
171336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe          program_counter,
171436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe          nullptr,
171536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe          static_cast<Activity::Type>(Activity::ACT_GENERIC | action),
171636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe          ActivityData::ForGeneric(id, info),
171736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe          /*lock_allowed=*/true),
171836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe      id_(id) {
171936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  // The action must not affect the category bits of the activity type.
172036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  DCHECK_EQ(0, action & Activity::ACT_CATEGORY_MASK);
172136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe}
172236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe
172336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abevoid ScopedActivity::ChangeAction(uint8_t action) {
172436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  DCHECK_EQ(0, action & Activity::ACT_CATEGORY_MASK);
172536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  ChangeTypeAndData(static_cast<Activity::Type>(Activity::ACT_GENERIC | action),
172636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe                    kNullActivityData);
172736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe}
172836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe
172936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abevoid ScopedActivity::ChangeInfo(int32_t info) {
173036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  ChangeTypeAndData(Activity::ACT_NULL, ActivityData::ForGeneric(id_, info));
173136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe}
173236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe
173336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abevoid ScopedActivity::ChangeActionAndInfo(uint8_t action, int32_t info) {
173436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  DCHECK_EQ(0, action & Activity::ACT_CATEGORY_MASK);
173536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  ChangeTypeAndData(static_cast<Activity::Type>(Activity::ACT_GENERIC | action),
173636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe                    ActivityData::ForGeneric(id_, info));
173736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe}
173836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe
173936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko AbeScopedTaskRunActivity::ScopedTaskRunActivity(
174036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    const void* program_counter,
174136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    const base::PendingTask& task)
174236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    : GlobalActivityTracker::ScopedThreadActivity(
174336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe          program_counter,
174436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe          task.posted_from.program_counter(),
174536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe          Activity::ACT_TASK_RUN,
174636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe          ActivityData::ForTask(task.sequence_num),
174736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe          /*lock_allowed=*/true) {}
174836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe
174936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko AbeScopedLockAcquireActivity::ScopedLockAcquireActivity(
175036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    const void* program_counter,
175136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    const base::internal::LockImpl* lock)
175236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    : GlobalActivityTracker::ScopedThreadActivity(
175336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe          program_counter,
175436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe          nullptr,
175536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe          Activity::ACT_LOCK_ACQUIRE,
175636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe          ActivityData::ForLock(lock),
175736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe          /*lock_allowed=*/false) {}
175836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe
175936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko AbeScopedEventWaitActivity::ScopedEventWaitActivity(
176036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    const void* program_counter,
176136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    const base::WaitableEvent* event)
176236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    : GlobalActivityTracker::ScopedThreadActivity(
176336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe          program_counter,
176436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe          nullptr,
176536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe          Activity::ACT_EVENT_WAIT,
176636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe          ActivityData::ForEvent(event),
176736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe          /*lock_allowed=*/true) {}
176836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe
176936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko AbeScopedThreadJoinActivity::ScopedThreadJoinActivity(
177036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    const void* program_counter,
177136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    const base::PlatformThreadHandle* thread)
177236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    : GlobalActivityTracker::ScopedThreadActivity(
177336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe          program_counter,
177436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe          nullptr,
177536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe          Activity::ACT_THREAD_JOIN,
177636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe          ActivityData::ForThread(*thread),
177736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe          /*lock_allowed=*/true) {}
177836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe
177936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe#if !defined(OS_NACL) && !defined(OS_IOS)
178036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko AbeScopedProcessWaitActivity::ScopedProcessWaitActivity(
178136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    const void* program_counter,
178236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    const base::Process* process)
178336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    : GlobalActivityTracker::ScopedThreadActivity(
178436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe          program_counter,
178536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe          nullptr,
178636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe          Activity::ACT_PROCESS_WAIT,
178736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe          ActivityData::ForProcess(process->Pid()),
178836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe          /*lock_allowed=*/true) {}
178936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe#endif
179036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe
179136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe}  // namespace debug
179236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe}  // namespace base
1793