// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "base/debug/activity_tracker.h"

#include <algorithm>
#include <limits>
#include <utility>

#include "base/atomic_sequence_num.h"
#include "base/debug/stack_trace.h"
#include "base/files/file.h"
#include "base/files/file_path.h"
#include "base/files/memory_mapped_file.h"
#include "base/logging.h"
#include "base/memory/ptr_util.h"
#include "base/metrics/field_trial.h"
#include "base/metrics/histogram_macros.h"
#include "base/pending_task.h"
#include "base/pickle.h"
#include "base/process/process.h"
#include "base/process/process_handle.h"
#include "base/stl_util.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "base/threading/platform_thread.h"
#include "build/build_config.h"

namespace base {
namespace debug {

namespace {

// The minimum depth a stack should support.
const int kMinStackDepth = 2;

// The amount of memory set aside for holding arbitrary user data (key/value
// pairs) globally or associated with ActivityData entries.
const size_t kUserDataSize = 1 << 10;     // 1 KiB
const size_t kProcessDataSize = 4 << 10;  // 4 KiB
const size_t kMaxUserDataNameLength =
    static_cast<size_t>(std::numeric_limits<uint8_t>::max());

// A constant used to indicate that module information is changing.
const uint32_t kModuleInformationChanging = 0x80000000;

// The key used to record process information.
const char kProcessPhaseDataKey[] = "process-phase";

// An atomically incrementing number, used to check for recreations of objects
// in the same memory space.
AtomicSequenceNumber g_next_id;

// Gets the next non-zero identifier. It is only unique within a process.
uint32_t GetNextDataId() {
  uint32_t id;
  while ((id = g_next_id.GetNext()) == 0)
    ;
  return id;
}

// Gets the current process-id, either from the GlobalActivityTracker if it
// exists (where the PID can be defined for testing) or from the system if
// there isn't such.
int64_t GetProcessId() {
  GlobalActivityTracker* global = GlobalActivityTracker::Get();
  if (global)
    return global->process_id();
  return GetCurrentProcId();
}

// Finds and reuses a specific allocation or creates a new one.
PersistentMemoryAllocator::Reference AllocateFrom(
    PersistentMemoryAllocator* allocator,
    uint32_t from_type,
    size_t size,
    uint32_t to_type) {
  PersistentMemoryAllocator::Iterator iter(allocator);
  PersistentMemoryAllocator::Reference ref;
  while ((ref = iter.GetNextOfType(from_type)) != 0) {
    DCHECK_LE(size, allocator->GetAllocSize(ref));
    // This can fail if a another thread has just taken it. It is assumed that
    // the memory is cleared during the "free" operation.
    if (allocator->ChangeType(ref, to_type, from_type, /*clear=*/false))
      return ref;
  }

  return allocator->Allocate(size, to_type);
}

// Determines the previous aligned index.
size_t RoundDownToAlignment(size_t index, size_t alignment) {
  return index & (0 - alignment);
}

// Determines the next aligned index.
size_t RoundUpToAlignment(size_t index, size_t alignment) {
  return (index + (alignment - 1)) & (0 - alignment);
}

// Converts "tick" timing into wall time.
Time WallTimeFromTickTime(int64_t ticks_start, int64_t ticks, Time time_start) {
  return time_start + TimeDelta::FromInternalValue(ticks - ticks_start);
}

}  // namespace

union ThreadRef {
  int64_t as_id;
#if defined(OS_WIN)
  // On Windows, the handle itself is often a pseudo-handle with a common
  // value meaning "this thread" and so the thread-id is used. The former
  // can be converted to a thread-id with a system call.
  PlatformThreadId as_tid;
#elif defined(OS_POSIX) || defined(OS_FUCHSIA)
  // On Posix and Fuchsia, the handle is always a unique identifier so no
  // conversion needs to be done. However, its value is officially opaque so
  // there is no one correct way to convert it to a numerical identifier.
  PlatformThreadHandle::Handle as_handle;
#endif
};

OwningProcess::OwningProcess() = default;
OwningProcess::~OwningProcess() = default;

void OwningProcess::Release_Initialize(int64_t pid) {
  uint32_t old_id = data_id.load(std::memory_order_acquire);
  DCHECK_EQ(0U, old_id);
  process_id = pid != 0 ? pid : GetProcessId();
  create_stamp = Time::Now().ToInternalValue();
  data_id.store(GetNextDataId(), std::memory_order_release);
}

void OwningProcess::SetOwningProcessIdForTesting(int64_t pid, int64_t stamp) {
  DCHECK_NE(0U, data_id);
  process_id = pid;
  create_stamp = stamp;
}

// static
bool OwningProcess::GetOwningProcessId(const void* memory,
                                       int64_t* out_id,
                                       int64_t* out_stamp) {
  const OwningProcess* info = reinterpret_cast<const OwningProcess*>(memory);
  uint32_t id = info->data_id.load(std::memory_order_acquire);
  if (id == 0)
    return false;

  *out_id = info->process_id;
  *out_stamp = info->create_stamp;
  return id == info->data_id.load(std::memory_order_seq_cst);
}

// It doesn't matter what is contained in this (though it will be all zeros)
// as only the address of it is important.
const ActivityData kNullActivityData = {};

ActivityData ActivityData::ForThread(const PlatformThreadHandle& handle) {
  ThreadRef thread_ref;
  thread_ref.as_id = 0;  // Zero the union in case other is smaller.
#if defined(OS_WIN)
  thread_ref.as_tid = ::GetThreadId(handle.platform_handle());
#elif defined(OS_POSIX)
  thread_ref.as_handle = handle.platform_handle();
#endif
  return ForThread(thread_ref.as_id);
}

ActivityTrackerMemoryAllocator::ActivityTrackerMemoryAllocator(
    PersistentMemoryAllocator* allocator,
    uint32_t object_type,
    uint32_t object_free_type,
    size_t object_size,
    size_t cache_size,
    bool make_iterable)
    : allocator_(allocator),
      object_type_(object_type),
      object_free_type_(object_free_type),
      object_size_(object_size),
      cache_size_(cache_size),
      make_iterable_(make_iterable),
      iterator_(allocator),
      cache_values_(new Reference[cache_size]),
      cache_used_(0) {
  DCHECK(allocator);
}

ActivityTrackerMemoryAllocator::~ActivityTrackerMemoryAllocator() = default;

ActivityTrackerMemoryAllocator::Reference
ActivityTrackerMemoryAllocator::GetObjectReference() {
  // First see if there is a cached value that can be returned. This is much
  // faster than searching the memory system for free blocks.
  while (cache_used_ > 0) {
    Reference cached = cache_values_[--cache_used_];
    // Change the type of the cached object to the proper type and return it.
    // If the type-change fails that means another thread has taken this from
    // under us (via the search below) so ignore it and keep trying. Don't
    // clear the memory because that was done when the type was made "free".
    if (allocator_->ChangeType(cached, object_type_, object_free_type_, false))
      return cached;
  }

  // Fetch the next "free" object from persistent memory. Rather than restart
  // the iterator at the head each time and likely waste time going again
  // through objects that aren't relevant, the iterator continues from where
  // it last left off and is only reset when the end is reached. If the
  // returned reference matches |last|, then it has wrapped without finding
  // anything.
  const Reference last = iterator_.GetLast();
  while (true) {
    uint32_t type;
    Reference found = iterator_.GetNext(&type);
    if (found && type == object_free_type_) {
      // Found a free object. Change it to the proper type and return it. If
      // the type-change fails that means another thread has taken this from
      // under us so ignore it and keep trying.
      if (allocator_->ChangeType(found, object_type_, object_free_type_, false))
        return found;
    }
    if (found == last) {
      // Wrapped. No desired object was found.
      break;
    }
    if (!found) {
      // Reached end; start over at the beginning.
      iterator_.Reset();
    }
  }

  // No free block was found so instead allocate a new one.
  Reference allocated = allocator_->Allocate(object_size_, object_type_);
  if (allocated && make_iterable_)
    allocator_->MakeIterable(allocated);
  return allocated;
}

void ActivityTrackerMemoryAllocator::ReleaseObjectReference(Reference ref) {
  // Mark object as free.
  bool success = allocator_->ChangeType(ref, object_free_type_, object_type_,
                                        /*clear=*/true);
  DCHECK(success);

  // Add this reference to our "free" cache if there is space. If not, the type
  // has still been changed to indicate that it is free so this (or another)
  // thread can find it, albeit more slowly, using the iteration method above.
  if (cache_used_ < cache_size_)
    cache_values_[cache_used_++] = ref;
}

// static
void Activity::FillFrom(Activity* activity,
                        const void* program_counter,
                        const void* origin,
                        Type type,
                        const ActivityData& data) {
  activity->time_internal = base::TimeTicks::Now().ToInternalValue();
  activity->calling_address = reinterpret_cast<uintptr_t>(program_counter);
  activity->origin_address = reinterpret_cast<uintptr_t>(origin);
  activity->activity_type = type;
  activity->data = data;

#if (!defined(OS_NACL) && DCHECK_IS_ON()) || defined(ADDRESS_SANITIZER)
  // Create a stacktrace from the current location and get the addresses for
  // improved debuggability.
  StackTrace stack_trace;
  size_t stack_depth;
  const void* const* stack_addrs = stack_trace.Addresses(&stack_depth);
  // Copy the stack addresses, ignoring the first one (here).
  size_t i;
  for (i = 1; i < stack_depth && i < kActivityCallStackSize; ++i) {
    activity->call_stack[i - 1] = reinterpret_cast<uintptr_t>(stack_addrs[i]);
  }
  activity->call_stack[i - 1] = 0;
#else
  activity->call_stack[0] = 0;
#endif
}

ActivityUserData::TypedValue::TypedValue() = default;
ActivityUserData::TypedValue::TypedValue(const TypedValue& other) = default;
ActivityUserData::TypedValue::~TypedValue() = default;

StringPiece ActivityUserData::TypedValue::Get() const {
  DCHECK_EQ(RAW_VALUE, type_);
  return long_value_;
}

StringPiece ActivityUserData::TypedValue::GetString() const {
  DCHECK_EQ(STRING_VALUE, type_);
  return long_value_;
}

bool ActivityUserData::TypedValue::GetBool() const {
  DCHECK_EQ(BOOL_VALUE, type_);
  return short_value_ != 0;
}

char ActivityUserData::TypedValue::GetChar() const {
  DCHECK_EQ(CHAR_VALUE, type_);
  return static_cast<char>(short_value_);
}

int64_t ActivityUserData::TypedValue::GetInt() const {
  DCHECK_EQ(SIGNED_VALUE, type_);
  return static_cast<int64_t>(short_value_);
}

uint64_t ActivityUserData::TypedValue::GetUint() const {
  DCHECK_EQ(UNSIGNED_VALUE, type_);
  return static_cast<uint64_t>(short_value_);
}

StringPiece ActivityUserData::TypedValue::GetReference() const {
  DCHECK_EQ(RAW_VALUE_REFERENCE, type_);
  return ref_value_;
}

StringPiece ActivityUserData::TypedValue::GetStringReference() const {
  DCHECK_EQ(STRING_VALUE_REFERENCE, type_);
  return ref_value_;
}

// These are required because std::atomic is (currently) not a POD type and
// thus clang requires explicit out-of-line constructors and destructors even
// when they do nothing.
ActivityUserData::ValueInfo::ValueInfo() = default;
ActivityUserData::ValueInfo::ValueInfo(ValueInfo&&) = default;
ActivityUserData::ValueInfo::~ValueInfo() = default;
ActivityUserData::MemoryHeader::MemoryHeader() = default;
ActivityUserData::MemoryHeader::~MemoryHeader() = default;
ActivityUserData::FieldHeader::FieldHeader() = default;
ActivityUserData::FieldHeader::~FieldHeader() = default;

ActivityUserData::ActivityUserData() : ActivityUserData(nullptr, 0, -1) {}

ActivityUserData::ActivityUserData(void* memory, size_t size, int64_t pid)
    : memory_(reinterpret_cast<char*>(memory)),
      available_(RoundDownToAlignment(size, kMemoryAlignment)),
      header_(reinterpret_cast<MemoryHeader*>(memory)),
      orig_data_id(0),
      orig_process_id(0),
      orig_create_stamp(0) {
  // It's possible that no user data is being stored.
  if (!memory_)
    return;

  static_assert(0 == sizeof(MemoryHeader) % kMemoryAlignment, "invalid header");
  DCHECK_LT(sizeof(MemoryHeader), available_);
  if (header_->owner.data_id.load(std::memory_order_acquire) == 0)
    header_->owner.Release_Initialize(pid);
  memory_ += sizeof(MemoryHeader);
  available_ -= sizeof(MemoryHeader);

  // Make a copy of identifying information for later comparison.
  *const_cast<uint32_t*>(&orig_data_id) =
      header_->owner.data_id.load(std::memory_order_acquire);
  *const_cast<int64_t*>(&orig_process_id) = header_->owner.process_id;
  *const_cast<int64_t*>(&orig_create_stamp) = header_->owner.create_stamp;

  // If there is already data present, load that. This allows the same class
  // to be used for analysis through snapshots.
  ImportExistingData();
}

ActivityUserData::~ActivityUserData() = default;

bool ActivityUserData::CreateSnapshot(Snapshot* output_snapshot) const {
  DCHECK(output_snapshot);
  DCHECK(output_snapshot->empty());

  // Find any new data that may have been added by an active instance of this
  // class that is adding records.
  ImportExistingData();

  // Add all the values to the snapshot.
  for (const auto& entry : values_) {
    TypedValue value;
    const size_t size = entry.second.size_ptr->load(std::memory_order_acquire);
    value.type_ = entry.second.type;
    DCHECK_GE(entry.second.extent, size);

    switch (entry.second.type) {
      case RAW_VALUE:
      case STRING_VALUE:
        value.long_value_ =
            std::string(reinterpret_cast<char*>(entry.second.memory), size);
        break;
      case RAW_VALUE_REFERENCE:
      case STRING_VALUE_REFERENCE: {
        ReferenceRecord* ref =
            reinterpret_cast<ReferenceRecord*>(entry.second.memory);
        value.ref_value_ = StringPiece(
            reinterpret_cast<char*>(static_cast<uintptr_t>(ref->address)),
            static_cast<size_t>(ref->size));
      } break;
      case BOOL_VALUE:
      case CHAR_VALUE:
        value.short_value_ = *reinterpret_cast<char*>(entry.second.memory);
        break;
      case SIGNED_VALUE:
      case UNSIGNED_VALUE:
        value.short_value_ = *reinterpret_cast<uint64_t*>(entry.second.memory);
        break;
      case END_OF_VALUES:  // Included for completeness purposes.
        NOTREACHED();
    }
    auto inserted = output_snapshot->insert(
        std::make_pair(entry.second.name.as_string(), std::move(value)));
    DCHECK(inserted.second);  // True if inserted, false if existed.
  }

  // Another import attempt will validate that the underlying memory has not
  // been reused for another purpose. Entries added since the first import
  // will be ignored here but will be returned if another snapshot is created.
  ImportExistingData();
  if (!memory_) {
    output_snapshot->clear();
    return false;
  }

  // Successful snapshot.
  return true;
}

const void* ActivityUserData::GetBaseAddress() const {
  // The |memory_| pointer advances as elements are written but the |header_|
  // value is always at the start of the block so just return that.
  return header_;
}

void ActivityUserData::SetOwningProcessIdForTesting(int64_t pid,
                                                    int64_t stamp) {
  if (!header_)
    return;
  header_->owner.SetOwningProcessIdForTesting(pid, stamp);
}

// static
bool ActivityUserData::GetOwningProcessId(const void* memory,
                                          int64_t* out_id,
                                          int64_t* out_stamp) {
  const MemoryHeader* header = reinterpret_cast<const MemoryHeader*>(memory);
  return OwningProcess::GetOwningProcessId(&header->owner, out_id, out_stamp);
}

void ActivityUserData::Set(StringPiece name,
                           ValueType type,
                           const void* memory,
                           size_t size) {
  DCHECK_GE(std::numeric_limits<uint8_t>::max(), name.length());
  size = std::min(std::numeric_limits<uint16_t>::max() - (kMemoryAlignment - 1),
                  size);

  // It's possible that no user data is being stored.
  if (!memory_)
    return;

  // The storage of a name is limited so use that limit during lookup.
  if (name.length() > kMaxUserDataNameLength)
    name.set(name.data(), kMaxUserDataNameLength);

  ValueInfo* info;
  auto existing = values_.find(name);
  if (existing != values_.end()) {
    info = &existing->second;
  } else {
    // The name size is limited to what can be held in a single byte but
    // because there are not alignment constraints on strings, it's set tight
    // against the header. Its extent (the reserved space, even if it's not
    // all used) is calculated so that, when pressed against the header, the
    // following field will be aligned properly.
    size_t name_size = name.length();
    size_t name_extent =
        RoundUpToAlignment(sizeof(FieldHeader) + name_size, kMemoryAlignment) -
        sizeof(FieldHeader);
    size_t value_extent = RoundUpToAlignment(size, kMemoryAlignment);

    // The "base size" is the size of the header and (padded) string key. Stop
    // now if there's not room enough for even this.
    size_t base_size = sizeof(FieldHeader) + name_extent;
    if (base_size > available_)
      return;

    // The "full size" is the size for storing the entire value.
    size_t full_size = std::min(base_size + value_extent, available_);

    // If the value is actually a single byte, see if it can be stuffed at the
    // end of the name extent rather than wasting kMemoryAlignment bytes.
    if (size == 1 && name_extent > name_size) {
      full_size = base_size;
      --name_extent;
      --base_size;
    }

    // Truncate the stored size to the amount of available memory. Stop now if
    // there's not any room for even part of the value.
    if (size != 0) {
      size = std::min(full_size - base_size, size);
      if (size == 0)
        return;
    }

    // Allocate a chunk of memory.
    FieldHeader* header = reinterpret_cast<FieldHeader*>(memory_);
    memory_ += full_size;
    available_ -= full_size;

    // Datafill the header and name records. Memory must be zeroed. The |type|
    // is written last, atomically, to release all the other values.
    DCHECK_EQ(END_OF_VALUES, header->type.load(std::memory_order_relaxed));
    DCHECK_EQ(0, header->value_size.load(std::memory_order_relaxed));
    header->name_size = static_cast<uint8_t>(name_size);
    header->record_size = full_size;
    char* name_memory = reinterpret_cast<char*>(header) + sizeof(FieldHeader);
    void* value_memory =
        reinterpret_cast<char*>(header) + sizeof(FieldHeader) + name_extent;
    memcpy(name_memory, name.data(), name_size);
    header->type.store(type, std::memory_order_release);

    // Create an entry in |values_| so that this field can be found and changed
    // later on without having to allocate new entries.
    StringPiece persistent_name(name_memory, name_size);
    auto inserted =
        values_.insert(std::make_pair(persistent_name, ValueInfo()));
    DCHECK(inserted.second);  // True if inserted, false if existed.
    info = &inserted.first->second;
    info->name = persistent_name;
    info->memory = value_memory;
    info->size_ptr = &header->value_size;
    info->extent = full_size - sizeof(FieldHeader) - name_extent;
    info->type = type;
  }

  // Copy the value data to storage. The |size| is written last, atomically, to
  // release the copied data. Until then, a parallel reader will just ignore
  // records with a zero size.
  DCHECK_EQ(type, info->type);
  size = std::min(size, info->extent);
  info->size_ptr->store(0, std::memory_order_seq_cst);
  memcpy(info->memory, memory, size);
  info->size_ptr->store(size, std::memory_order_release);
}

void ActivityUserData::SetReference(StringPiece name,
                                    ValueType type,
                                    const void* memory,
                                    size_t size) {
  ReferenceRecord rec;
  rec.address = reinterpret_cast<uintptr_t>(memory);
  rec.size = size;
  Set(name, type, &rec, sizeof(rec));
}

void ActivityUserData::ImportExistingData() const {
  // It's possible that no user data is being stored.
  if (!memory_)
    return;

  while (available_ > sizeof(FieldHeader)) {
    FieldHeader* header = reinterpret_cast<FieldHeader*>(memory_);
    ValueType type =
        static_cast<ValueType>(header->type.load(std::memory_order_acquire));
    if (type == END_OF_VALUES)
      return;
    if (header->record_size > available_)
      return;

    size_t value_offset = RoundUpToAlignment(
        sizeof(FieldHeader) + header->name_size, kMemoryAlignment);
    if (header->record_size == value_offset &&
        header->value_size.load(std::memory_order_relaxed) == 1) {
      value_offset -= 1;
    }
    if (value_offset + header->value_size > header->record_size)
      return;

    ValueInfo info;
    info.name = StringPiece(memory_ + sizeof(FieldHeader), header->name_size);
    info.type = type;
    info.memory = memory_ + value_offset;
    info.size_ptr = &header->value_size;
    info.extent = header->record_size - value_offset;

    StringPiece key(info.name);
    values_.insert(std::make_pair(key, std::move(info)));

    memory_ += header->record_size;
    available_ -= header->record_size;
  }

  // Check if memory has been completely reused.
  if (header_->owner.data_id.load(std::memory_order_acquire) != orig_data_id ||
      header_->owner.process_id != orig_process_id ||
      header_->owner.create_stamp != orig_create_stamp) {
    memory_ = nullptr;
    values_.clear();
  }
}

// This information is kept for every thread that is tracked. It is filled
// the very first time the thread is seen. All fields must be of exact sizes
// so there is no issue moving between 32 and 64-bit builds.
struct ThreadActivityTracker::Header {
  // Defined in .h for analyzer access. Increment this if structure changes!
  static constexpr uint32_t kPersistentTypeId =
      GlobalActivityTracker::kTypeIdActivityTracker;

  // Expected size for 32/64-bit check.
  static constexpr size_t kExpectedInstanceSize =
      OwningProcess::kExpectedInstanceSize + Activity::kExpectedInstanceSize +
      72;

  // This information uniquely identifies a process.
  OwningProcess owner;

  // The thread-id (thread_ref.as_id) to which this data belongs. This number
  // is not guaranteed to mean anything but combined with the process-id from
  // OwningProcess is unique among all active trackers.
  ThreadRef thread_ref;

  // The start-time and start-ticks when the data was created. Each activity
  // record has a |time_internal| value that can be converted to a "wall time"
  // with these two values.
  int64_t start_time;
  int64_t start_ticks;

  // The number of Activity slots (spaces that can hold an Activity) that
  // immediately follow this structure in memory.
  uint32_t stack_slots;

  // Some padding to keep everything 64-bit aligned.
  uint32_t padding;

  // The current depth of the stack. This may be greater than the number of
  // slots. If the depth exceeds the number of slots, the newest entries
  // won't be recorded.
  std::atomic<uint32_t> current_depth;

  // A memory location used to indicate if changes have been made to the data
  // that would invalidate an in-progress read of its contents. The active
  // tracker will increment the value whenever something gets popped from the
  // stack. A monitoring tracker can check the value before and after access
  // to know, if it's still the same, that the contents didn't change while
  // being copied.
  std::atomic<uint32_t> data_version;

  // The last "exception" activity. This can't be stored on the stack because
  // that could get popped as things unwind.
  Activity last_exception;

  // The name of the thread (up to a maximum length). Dynamic-length names
  // are not practical since the memory has to come from the same persistent
  // allocator that holds this structure and to which this object has no
  // reference.
  char thread_name[32];
};

ThreadActivityTracker::Snapshot::Snapshot() = default;
ThreadActivityTracker::Snapshot::~Snapshot() = default;

ThreadActivityTracker::ScopedActivity::ScopedActivity(
    ThreadActivityTracker* tracker,
    const void* program_counter,
    const void* origin,
    Activity::Type type,
    const ActivityData& data)
    : tracker_(tracker) {
  if (tracker_)
    activity_id_ = tracker_->PushActivity(program_counter, origin, type, data);
}

ThreadActivityTracker::ScopedActivity::~ScopedActivity() {
  if (tracker_)
    tracker_->PopActivity(activity_id_);
}

void ThreadActivityTracker::ScopedActivity::ChangeTypeAndData(
    Activity::Type type,
    const ActivityData& data) {
  if (tracker_)
    tracker_->ChangeActivity(activity_id_, type, data);
}

ThreadActivityTracker::ThreadActivityTracker(void* base, size_t size)
    : header_(static_cast<Header*>(base)),
      stack_(reinterpret_cast<Activity*>(reinterpret_cast<char*>(base) +
                                         sizeof(Header))),
#if DCHECK_IS_ON()
      thread_id_(PlatformThreadRef()),
#endif
      stack_slots_(
          static_cast<uint32_t>((size - sizeof(Header)) / sizeof(Activity))) {

  // Verify the parameters but fail gracefully if they're not valid so that
  // production code based on external inputs will not crash.  IsValid() will
  // return false in this case.
  if (!base ||
      // Ensure there is enough space for the header and at least a few records.
      size < sizeof(Header) + kMinStackDepth * sizeof(Activity) ||
      // Ensure that the |stack_slots_| calculation didn't overflow.
      (size - sizeof(Header)) / sizeof(Activity) >
          std::numeric_limits<uint32_t>::max()) {
    NOTREACHED();
    return;
  }

  // Ensure that the thread reference doesn't exceed the size of the ID number.
  // This won't compile at the global scope because Header is a private struct.
  static_assert(
      sizeof(header_->thread_ref) == sizeof(header_->thread_ref.as_id),
      "PlatformThreadHandle::Handle is too big to hold in 64-bit ID");

  // Ensure that the alignment of Activity.data is properly aligned to a
  // 64-bit boundary so there are no interoperability-issues across cpu
  // architectures.
  static_assert(offsetof(Activity, data) % sizeof(uint64_t) == 0,
                "ActivityData.data is not 64-bit aligned");

  // Provided memory should either be completely initialized or all zeros.
  if (header_->owner.data_id.load(std::memory_order_relaxed) == 0) {
    // This is a new file. Double-check other fields and then initialize.
    DCHECK_EQ(0, header_->owner.process_id);
    DCHECK_EQ(0, header_->owner.create_stamp);
    DCHECK_EQ(0, header_->thread_ref.as_id);
    DCHECK_EQ(0, header_->start_time);
    DCHECK_EQ(0, header_->start_ticks);
    DCHECK_EQ(0U, header_->stack_slots);
    DCHECK_EQ(0U, header_->current_depth.load(std::memory_order_relaxed));
    DCHECK_EQ(0U, header_->data_version.load(std::memory_order_relaxed));
    DCHECK_EQ(0, stack_[0].time_internal);
    DCHECK_EQ(0U, stack_[0].origin_address);
    DCHECK_EQ(0U, stack_[0].call_stack[0]);
    DCHECK_EQ(0U, stack_[0].data.task.sequence_id);

#if defined(OS_WIN)
    header_->thread_ref.as_tid = PlatformThread::CurrentId();
#elif defined(OS_POSIX) || defined(OS_FUCHSIA)
    header_->thread_ref.as_handle =
        PlatformThread::CurrentHandle().platform_handle();
#endif

    header_->start_time = base::Time::Now().ToInternalValue();
    header_->start_ticks = base::TimeTicks::Now().ToInternalValue();
    header_->stack_slots = stack_slots_;
    strlcpy(header_->thread_name, PlatformThread::GetName(),
            sizeof(header_->thread_name));

    // This is done last so as to guarantee that everything above is "released"
    // by the time this value gets written.
    header_->owner.Release_Initialize();

    valid_ = true;
    DCHECK(IsValid());
  } else {
    // This is a file with existing data. Perform basic consistency checks.
    valid_ = true;
    valid_ = IsValid();
  }
}

ThreadActivityTracker::~ThreadActivityTracker() = default;

ThreadActivityTracker::ActivityId ThreadActivityTracker::PushActivity(
    const void* program_counter,
    const void* origin,
    Activity::Type type,
    const ActivityData& data) {
  // A thread-checker creates a lock to check the thread-id which means
  // re-entry into this code if lock acquisitions are being tracked.
  DCHECK(type == Activity::ACT_LOCK_ACQUIRE || CalledOnValidThread());

  // Get the current depth of the stack. No access to other memory guarded
  // by this variable is done here so a "relaxed" load is acceptable.
  uint32_t depth = header_->current_depth.load(std::memory_order_relaxed);

  // Handle the case where the stack depth has exceeded the storage capacity.
  // Extra entries will be lost leaving only the base of the stack.
  if (depth >= stack_slots_) {
    // Since no other threads modify the data, no compare/exchange is needed.
    // Since no other memory is being modified, a "relaxed" store is acceptable.
    header_->current_depth.store(depth + 1, std::memory_order_relaxed);
    return depth;
  }

  // Get a pointer to the next activity and load it. No atomicity is required
  // here because the memory is known only to this thread. It will be made
  // known to other threads once the depth is incremented.
  Activity::FillFrom(&stack_[depth], program_counter, origin, type, data);

  // Save the incremented depth. Because this guards |activity| memory filled
  // above that may be read by another thread once the recorded depth changes,
  // a "release" store is required.
  header_->current_depth.store(depth + 1, std::memory_order_release);

  // The current depth is used as the activity ID because it simply identifies
  // an entry. Once an entry is pop'd, it's okay to reuse the ID.
  return depth;
}

void ThreadActivityTracker::ChangeActivity(ActivityId id,
                                           Activity::Type type,
                                           const ActivityData& data) {
  DCHECK(CalledOnValidThread());
  DCHECK(type != Activity::ACT_NULL || &data != &kNullActivityData);
  DCHECK_LT(id, header_->current_depth.load(std::memory_order_acquire));

  // Update the information if it is being recorded (i.e. within slot limit).
  if (id < stack_slots_) {
    Activity* activity = &stack_[id];

    if (type != Activity::ACT_NULL) {
      DCHECK_EQ(activity->activity_type & Activity::ACT_CATEGORY_MASK,
                type & Activity::ACT_CATEGORY_MASK);
      activity->activity_type = type;
    }

    if (&data != &kNullActivityData)
      activity->data = data;
  }
}

void ThreadActivityTracker::PopActivity(ActivityId id) {
  // Do an atomic decrement of the depth. No changes to stack entries guarded
  // by this variable are done here so a "relaxed" operation is acceptable.
  // |depth| will receive the value BEFORE it was modified which means the
  // return value must also be decremented. The slot will be "free" after
  // this call but since only a single thread can access this object, the
  // data will remain valid until this method returns or calls outside.
  uint32_t depth =
      header_->current_depth.fetch_sub(1, std::memory_order_relaxed) - 1;

  // Validate that everything is running correctly.
  DCHECK_EQ(id, depth);

  // A thread-checker creates a lock to check the thread-id which means
  // re-entry into this code if lock acquisitions are being tracked.
  DCHECK(stack_[depth].activity_type == Activity::ACT_LOCK_ACQUIRE ||
         CalledOnValidThread());

  // The stack has shrunk meaning that some other thread trying to copy the
  // contents for reporting purposes could get bad data. Increment the data
  // version so that it con tell that things have changed. This needs to
  // happen after the atomic |depth| operation above so a "release" store
  // is required.
  header_->data_version.fetch_add(1, std::memory_order_release);
}

std::unique_ptr<ActivityUserData> ThreadActivityTracker::GetUserData(
    ActivityId id,
    ActivityTrackerMemoryAllocator* allocator) {
  // Don't allow user data for lock acquisition as recursion may occur.
  if (stack_[id].activity_type == Activity::ACT_LOCK_ACQUIRE) {
    NOTREACHED();
    return std::make_unique<ActivityUserData>();
  }

  // User-data is only stored for activities actually held in the stack.
  if (id >= stack_slots_)
    return std::make_unique<ActivityUserData>();

  // Create and return a real UserData object.
  return CreateUserDataForActivity(&stack_[id], allocator);
}

bool ThreadActivityTracker::HasUserData(ActivityId id) {
  // User-data is only stored for activities actually held in the stack.
  return (id < stack_slots_ && stack_[id].user_data_ref);
}

void ThreadActivityTracker::ReleaseUserData(
    ActivityId id,
    ActivityTrackerMemoryAllocator* allocator) {
  // User-data is only stored for activities actually held in the stack.
  if (id < stack_slots_ && stack_[id].user_data_ref) {
    allocator->ReleaseObjectReference(stack_[id].user_data_ref);
    stack_[id].user_data_ref = 0;
  }
}

void ThreadActivityTracker::RecordExceptionActivity(const void* program_counter,
                                                    const void* origin,
                                                    Activity::Type type,
                                                    const ActivityData& data) {
  // A thread-checker creates a lock to check the thread-id which means
  // re-entry into this code if lock acquisitions are being tracked.
  DCHECK(CalledOnValidThread());

  // Fill the reusable exception activity.
  Activity::FillFrom(&header_->last_exception, program_counter, origin, type,
                     data);

  // The data has changed meaning that some other thread trying to copy the
  // contents for reporting purposes could get bad data.
  header_->data_version.fetch_add(1, std::memory_order_relaxed);
}

bool ThreadActivityTracker::IsValid() const {
  if (header_->owner.data_id.load(std::memory_order_acquire) == 0 ||
      header_->owner.process_id == 0 || header_->thread_ref.as_id == 0 ||
      header_->start_time == 0 || header_->start_ticks == 0 ||
      header_->stack_slots != stack_slots_ ||
      header_->thread_name[sizeof(header_->thread_name) - 1] != '\0') {
    return false;
  }

  return valid_;
}

bool ThreadActivityTracker::CreateSnapshot(Snapshot* output_snapshot) const {
  DCHECK(output_snapshot);

  // There is no "called on valid thread" check for this method as it can be
  // called from other threads or even other processes. It is also the reason
  // why atomic operations must be used in certain places above.

  // It's possible for the data to change while reading it in such a way that it
  // invalidates the read. Make several attempts but don't try forever.
  const int kMaxAttempts = 10;
  uint32_t depth;

  // Stop here if the data isn't valid.
  if (!IsValid())
    return false;

  // Allocate the maximum size for the stack so it doesn't have to be done
  // during the time-sensitive snapshot operation. It is shrunk once the
  // actual size is known.
  output_snapshot->activity_stack.reserve(stack_slots_);

  for (int attempt = 0; attempt < kMaxAttempts; ++attempt) {
    // Remember the data IDs to ensure nothing is replaced during the snapshot
    // operation. Use "acquire" so that all the non-atomic fields of the
    // structure are valid (at least at the current moment in time).
    const uint32_t starting_id =
        header_->owner.data_id.load(std::memory_order_acquire);
    const int64_t starting_create_stamp = header_->owner.create_stamp;
    const int64_t starting_process_id = header_->owner.process_id;
    const int64_t starting_thread_id = header_->thread_ref.as_id;

    // Note the current |data_version| so it's possible to detect at the end
    // that nothing has changed since copying the data began. A "cst" operation
    // is required to ensure it occurs before everything else. Using "cst"
    // memory ordering is relatively expensive but this is only done during
    // analysis so doesn't directly affect the worker threads.
    const uint32_t pre_version =
        header_->data_version.load(std::memory_order_seq_cst);

    // Fetching the current depth also "acquires" the contents of the stack.
    depth = header_->current_depth.load(std::memory_order_acquire);
    uint32_t count = std::min(depth, stack_slots_);
    output_snapshot->activity_stack.resize(count);
    if (count > 0) {
      // Copy the existing contents. Memcpy is used for speed.
      memcpy(&output_snapshot->activity_stack[0], stack_,
             count * sizeof(Activity));
    }

    // Capture the last exception.
    memcpy(&output_snapshot->last_exception, &header_->last_exception,
           sizeof(Activity));

    // TODO(bcwhite): Snapshot other things here.

    // Retry if something changed during the copy. A "cst" operation ensures
    // it must happen after all the above operations.
    if (header_->data_version.load(std::memory_order_seq_cst) != pre_version)
      continue;

    // Stack copied. Record it's full depth.
    output_snapshot->activity_stack_depth = depth;

    // Get the general thread information.
    output_snapshot->thread_name =
        std::string(header_->thread_name, sizeof(header_->thread_name) - 1);
    output_snapshot->create_stamp = header_->owner.create_stamp;
    output_snapshot->thread_id = header_->thread_ref.as_id;
    output_snapshot->process_id = header_->owner.process_id;

    // All characters of the thread-name buffer were copied so as to not break
    // if the trailing NUL were missing. Now limit the length if the actual
    // name is shorter.
    output_snapshot->thread_name.resize(
        strlen(output_snapshot->thread_name.c_str()));

    // If the data ID has changed then the tracker has exited and the memory
    // reused by a new one. Try again.
    if (header_->owner.data_id.load(std::memory_order_seq_cst) != starting_id ||
        output_snapshot->create_stamp != starting_create_stamp ||
        output_snapshot->process_id != starting_process_id ||
        output_snapshot->thread_id != starting_thread_id) {
      continue;
    }

    // Only successful if the data is still valid once everything is done since
    // it's possible for the thread to end somewhere in the middle and all its
    // values become garbage.
    if (!IsValid())
      return false;

    // Change all the timestamps in the activities from "ticks" to "wall" time.
    const Time start_time = Time::FromInternalValue(header_->start_time);
    const int64_t start_ticks = header_->start_ticks;
    for (Activity& activity : output_snapshot->activity_stack) {
      activity.time_internal =
          WallTimeFromTickTime(start_ticks, activity.time_internal, start_time)
              .ToInternalValue();
    }
    output_snapshot->last_exception.time_internal =
        WallTimeFromTickTime(start_ticks,
                             output_snapshot->last_exception.time_internal,
                             start_time)
            .ToInternalValue();

    // Success!
    return true;
  }

  // Too many attempts.
  return false;
}

const void* ThreadActivityTracker::GetBaseAddress() {
  return header_;
}

uint32_t ThreadActivityTracker::GetDataVersionForTesting() {
  return header_->data_version.load(std::memory_order_relaxed);
}

void ThreadActivityTracker::SetOwningProcessIdForTesting(int64_t pid,
                                                         int64_t stamp) {
  header_->owner.SetOwningProcessIdForTesting(pid, stamp);
}

// static
bool ThreadActivityTracker::GetOwningProcessId(const void* memory,
                                               int64_t* out_id,
                                               int64_t* out_stamp) {
  const Header* header = reinterpret_cast<const Header*>(memory);
  return OwningProcess::GetOwningProcessId(&header->owner, out_id, out_stamp);
}

// static
size_t ThreadActivityTracker::SizeForStackDepth(int stack_depth) {
  return static_cast<size_t>(stack_depth) * sizeof(Activity) + sizeof(Header);
}

bool ThreadActivityTracker::CalledOnValidThread() {
#if DCHECK_IS_ON()
  return thread_id_ == PlatformThreadRef();
#else
  return true;
#endif
}

std::unique_ptr<ActivityUserData>
ThreadActivityTracker::CreateUserDataForActivity(
    Activity* activity,
    ActivityTrackerMemoryAllocator* allocator) {
  DCHECK_EQ(0U, activity->user_data_ref);

  PersistentMemoryAllocator::Reference ref = allocator->GetObjectReference();
  void* memory = allocator->GetAsArray<char>(ref, kUserDataSize);
  if (memory) {
    std::unique_ptr<ActivityUserData> user_data =
        std::make_unique<ActivityUserData>(memory, kUserDataSize);
    activity->user_data_ref = ref;
    activity->user_data_id = user_data->id();
    return user_data;
  }

  // Return a dummy object that will still accept (but ignore) Set() calls.
  return std::make_unique<ActivityUserData>();
}

// The instantiation of the GlobalActivityTracker object.
// The object held here will obviously not be destructed at process exit
// but that's best since PersistentMemoryAllocator objects (that underlie
// GlobalActivityTracker objects) are explicitly forbidden from doing anything
// essential at exit anyway due to the fact that they depend on data managed
// elsewhere and which could be destructed first. An AtomicWord is used instead
// of std::atomic because the latter can create global ctors and dtors.
subtle::AtomicWord GlobalActivityTracker::g_tracker_ = 0;

GlobalActivityTracker::ModuleInfo::ModuleInfo() = default;
GlobalActivityTracker::ModuleInfo::ModuleInfo(ModuleInfo&& rhs) = default;
GlobalActivityTracker::ModuleInfo::ModuleInfo(const ModuleInfo& rhs) = default;
GlobalActivityTracker::ModuleInfo::~ModuleInfo() = default;

GlobalActivityTracker::ModuleInfo& GlobalActivityTracker::ModuleInfo::operator=(
    ModuleInfo&& rhs) = default;
GlobalActivityTracker::ModuleInfo& GlobalActivityTracker::ModuleInfo::operator=(
    const ModuleInfo& rhs) = default;

GlobalActivityTracker::ModuleInfoRecord::ModuleInfoRecord() = default;
GlobalActivityTracker::ModuleInfoRecord::~ModuleInfoRecord() = default;

bool GlobalActivityTracker::ModuleInfoRecord::DecodeTo(
    GlobalActivityTracker::ModuleInfo* info,
    size_t record_size) const {
  // Get the current "changes" indicator, acquiring all the other values.
  uint32_t current_changes = changes.load(std::memory_order_acquire);

  // Copy out the dynamic information.
  info->is_loaded = loaded != 0;
  info->address = static_cast<uintptr_t>(address);
  info->load_time = load_time;

  // Check to make sure no information changed while being read. A "seq-cst"
  // operation is expensive but is only done during analysis and it's the only
  // way to ensure this occurs after all the accesses above. If changes did
  // occur then return a "not loaded" result so that |size| and |address|
  // aren't expected to be accurate.
  if ((current_changes & kModuleInformationChanging) != 0 ||
      changes.load(std::memory_order_seq_cst) != current_changes) {
    info->is_loaded = false;
  }

  // Copy out the static information. These never change so don't have to be
  // protected by the atomic |current_changes| operations.
  info->size = static_cast<size_t>(size);
  info->timestamp = timestamp;
  info->age = age;
  memcpy(info->identifier, identifier, sizeof(info->identifier));

  if (offsetof(ModuleInfoRecord, pickle) + pickle_size > record_size)
    return false;
  Pickle pickler(pickle, pickle_size);
  PickleIterator iter(pickler);
  return iter.ReadString(&info->file) && iter.ReadString(&info->debug_file);
}

GlobalActivityTracker::ModuleInfoRecord*
GlobalActivityTracker::ModuleInfoRecord::CreateFrom(
    const GlobalActivityTracker::ModuleInfo& info,
    PersistentMemoryAllocator* allocator) {
  Pickle pickler;
  pickler.WriteString(info.file);
  pickler.WriteString(info.debug_file);
  size_t required_size = offsetof(ModuleInfoRecord, pickle) + pickler.size();
  ModuleInfoRecord* record = allocator->New<ModuleInfoRecord>(required_size);
  if (!record)
    return nullptr;

  // These fields never changes and are done before the record is made
  // iterable so no thread protection is necessary.
  record->size = info.size;
  record->timestamp = info.timestamp;
  record->age = info.age;
  memcpy(record->identifier, info.identifier, sizeof(identifier));
  memcpy(record->pickle, pickler.data(), pickler.size());
  record->pickle_size = pickler.size();
  record->changes.store(0, std::memory_order_relaxed);

  // Initialize the owner info.
  record->owner.Release_Initialize();

  // Now set those fields that can change.
  bool success = record->UpdateFrom(info);
  DCHECK(success);
  return record;
}

bool GlobalActivityTracker::ModuleInfoRecord::UpdateFrom(
    const GlobalActivityTracker::ModuleInfo& info) {
  // Updates can occur after the record is made visible so make changes atomic.
  // A "strong" exchange ensures no false failures.
  uint32_t old_changes = changes.load(std::memory_order_relaxed);
  uint32_t new_changes = old_changes | kModuleInformationChanging;
  if ((old_changes & kModuleInformationChanging) != 0 ||
      !changes.compare_exchange_strong(old_changes, new_changes,
                                       std::memory_order_acquire,
                                       std::memory_order_acquire)) {
    NOTREACHED() << "Multiple sources are updating module information.";
    return false;
  }

  loaded = info.is_loaded ? 1 : 0;
  address = info.address;
  load_time = Time::Now().ToInternalValue();

  bool success = changes.compare_exchange_strong(new_changes, old_changes + 1,
                                                 std::memory_order_release,
                                                 std::memory_order_relaxed);
  DCHECK(success);
  return true;
}

GlobalActivityTracker::ScopedThreadActivity::ScopedThreadActivity(
    const void* program_counter,
    const void* origin,
    Activity::Type type,
    const ActivityData& data,
    bool lock_allowed)
    : ThreadActivityTracker::ScopedActivity(GetOrCreateTracker(lock_allowed),
                                            program_counter,
                                            origin,
                                            type,
                                            data) {}

GlobalActivityTracker::ScopedThreadActivity::~ScopedThreadActivity() {
  if (tracker_ && tracker_->HasUserData(activity_id_)) {
    GlobalActivityTracker* global = GlobalActivityTracker::Get();
    AutoLock lock(global->user_data_allocator_lock_);
    tracker_->ReleaseUserData(activity_id_, &global->user_data_allocator_);
  }
}

ActivityUserData& GlobalActivityTracker::ScopedThreadActivity::user_data() {
  if (!user_data_) {
    if (tracker_) {
      GlobalActivityTracker* global = GlobalActivityTracker::Get();
      AutoLock lock(global->user_data_allocator_lock_);
      user_data_ =
          tracker_->GetUserData(activity_id_, &global->user_data_allocator_);
    } else {
      user_data_ = std::make_unique<ActivityUserData>();
    }
  }
  return *user_data_;
}

GlobalActivityTracker::ThreadSafeUserData::ThreadSafeUserData(void* memory,
                                                              size_t size,
                                                              int64_t pid)
    : ActivityUserData(memory, size, pid) {}

GlobalActivityTracker::ThreadSafeUserData::~ThreadSafeUserData() = default;

void GlobalActivityTracker::ThreadSafeUserData::Set(StringPiece name,
                                                    ValueType type,
                                                    const void* memory,
                                                    size_t size) {
  AutoLock lock(data_lock_);
  ActivityUserData::Set(name, type, memory, size);
}

GlobalActivityTracker::ManagedActivityTracker::ManagedActivityTracker(
    PersistentMemoryAllocator::Reference mem_reference,
    void* base,
    size_t size)
    : ThreadActivityTracker(base, size),
      mem_reference_(mem_reference),
      mem_base_(base) {}

GlobalActivityTracker::ManagedActivityTracker::~ManagedActivityTracker() {
  // The global |g_tracker_| must point to the owner of this class since all
  // objects of this type must be destructed before |g_tracker_| can be changed
  // (something that only occurs in tests).
  DCHECK(g_tracker_);
  GlobalActivityTracker::Get()->ReturnTrackerMemory(this);
}

void GlobalActivityTracker::CreateWithAllocator(
    std::unique_ptr<PersistentMemoryAllocator> allocator,
    int stack_depth,
    int64_t process_id) {
  // There's no need to do anything with the result. It is self-managing.
  GlobalActivityTracker* global_tracker =
      new GlobalActivityTracker(std::move(allocator), stack_depth, process_id);
  // Create a tracker for this thread since it is known.
  global_tracker->CreateTrackerForCurrentThread();
}

#if !defined(OS_NACL)
// static
bool GlobalActivityTracker::CreateWithFile(const FilePath& file_path,
                                           size_t size,
                                           uint64_t id,
                                           StringPiece name,
                                           int stack_depth) {
  DCHECK(!file_path.empty());
  DCHECK_GE(static_cast<uint64_t>(std::numeric_limits<int64_t>::max()), size);

  // Create and map the file into memory and make it globally available.
  std::unique_ptr<MemoryMappedFile> mapped_file(new MemoryMappedFile());
  bool success = mapped_file->Initialize(
      File(file_path, File::FLAG_CREATE_ALWAYS | File::FLAG_READ |
                          File::FLAG_WRITE | File::FLAG_SHARE_DELETE),
      {0, size}, MemoryMappedFile::READ_WRITE_EXTEND);
  if (!success)
    return false;
  if (!FilePersistentMemoryAllocator::IsFileAcceptable(*mapped_file, false))
    return false;
  CreateWithAllocator(std::make_unique<FilePersistentMemoryAllocator>(
                          std::move(mapped_file), size, id, name, false),
                      stack_depth, 0);
  return true;
}
#endif  // !defined(OS_NACL)

// static
bool GlobalActivityTracker::CreateWithLocalMemory(size_t size,
                                                  uint64_t id,
                                                  StringPiece name,
                                                  int stack_depth,
                                                  int64_t process_id) {
  CreateWithAllocator(
      std::make_unique<LocalPersistentMemoryAllocator>(size, id, name),
      stack_depth, process_id);
  return true;
}

// static
bool GlobalActivityTracker::CreateWithSharedMemory(
    std::unique_ptr<SharedMemory> shm,
    uint64_t id,
    StringPiece name,
    int stack_depth) {
  if (shm->mapped_size() == 0 ||
      !SharedPersistentMemoryAllocator::IsSharedMemoryAcceptable(*shm)) {
    return false;
  }
  CreateWithAllocator(std::make_unique<SharedPersistentMemoryAllocator>(
                          std::move(shm), id, name, false),
                      stack_depth, 0);
  return true;
}

// static
bool GlobalActivityTracker::CreateWithSharedMemoryHandle(
    const SharedMemoryHandle& handle,
    size_t size,
    uint64_t id,
    StringPiece name,
    int stack_depth) {
  std::unique_ptr<SharedMemory> shm(
      new SharedMemory(handle, /*readonly=*/false));
  if (!shm->Map(size))
    return false;
  return CreateWithSharedMemory(std::move(shm), id, name, stack_depth);
}

// static
void GlobalActivityTracker::SetForTesting(
    std::unique_ptr<GlobalActivityTracker> tracker) {
  CHECK(!subtle::NoBarrier_Load(&g_tracker_));
  subtle::Release_Store(&g_tracker_,
                        reinterpret_cast<uintptr_t>(tracker.release()));
}

// static
std::unique_ptr<GlobalActivityTracker>
GlobalActivityTracker::ReleaseForTesting() {
  GlobalActivityTracker* tracker = Get();
  if (!tracker)
    return nullptr;

  // Thread trackers assume that the global tracker is present for some
  // operations so ensure that there aren't any.
  tracker->ReleaseTrackerForCurrentThreadForTesting();
  DCHECK_EQ(0, tracker->thread_tracker_count_.load(std::memory_order_relaxed));

  subtle::Release_Store(&g_tracker_, 0);
  return WrapUnique(tracker);
}

ThreadActivityTracker* GlobalActivityTracker::CreateTrackerForCurrentThread() {
  // It is not safe to use TLS once TLS has been destroyed.
  if (base::ThreadLocalStorage::HasBeenDestroyed())
    return nullptr;

  DCHECK(!this_thread_tracker_.Get());

  PersistentMemoryAllocator::Reference mem_reference;

  {
    base::AutoLock autolock(thread_tracker_allocator_lock_);
    mem_reference = thread_tracker_allocator_.GetObjectReference();
  }

  if (!mem_reference) {
    // Failure. This shouldn't happen. But be graceful if it does, probably
    // because the underlying allocator wasn't given enough memory to satisfy
    // to all possible requests.
    NOTREACHED();
    // Report the thread-count at which the allocator was full so that the
    // failure can be seen and underlying memory resized appropriately.
    UMA_HISTOGRAM_COUNTS_1000(
        "ActivityTracker.ThreadTrackers.MemLimitTrackerCount",
        thread_tracker_count_.load(std::memory_order_relaxed));
    // Return null, just as if tracking wasn't enabled.
    return nullptr;
  }

  // Convert the memory block found above into an actual memory address.
  // Doing the conversion as a Header object enacts the 32/64-bit size
  // consistency checks which would not otherwise be done. Unfortunately,
  // some older compilers and MSVC don't have standard-conforming definitions
  // of std::atomic which cause it not to be plain-old-data. Don't check on
  // those platforms assuming that the checks on other platforms will be
  // sufficient.
  // TODO(bcwhite): Review this after major compiler releases.
  DCHECK(mem_reference);
  void* mem_base;
  mem_base =
      allocator_->GetAsObject<ThreadActivityTracker::Header>(mem_reference);

  DCHECK(mem_base);
  DCHECK_LE(stack_memory_size_, allocator_->GetAllocSize(mem_reference));

  // Create a tracker with the acquired memory and set it as the tracker
  // for this particular thread in thread-local-storage.
  ManagedActivityTracker* tracker =
      new ManagedActivityTracker(mem_reference, mem_base, stack_memory_size_);
  DCHECK(tracker->IsValid());
  this_thread_tracker_.Set(tracker);
  int old_count = thread_tracker_count_.fetch_add(1, std::memory_order_relaxed);

  UMA_HISTOGRAM_EXACT_LINEAR("ActivityTracker.ThreadTrackers.Count",
                             old_count + 1, static_cast<int>(kMaxThreadCount));
  return tracker;
}

void GlobalActivityTracker::ReleaseTrackerForCurrentThreadForTesting() {
  ThreadActivityTracker* tracker =
      reinterpret_cast<ThreadActivityTracker*>(this_thread_tracker_.Get());
  if (tracker) {
    this_thread_tracker_.Set(nullptr);
    delete tracker;
  }
}

void GlobalActivityTracker::SetBackgroundTaskRunner(
    const scoped_refptr<TaskRunner>& runner) {
  AutoLock lock(global_tracker_lock_);
  background_task_runner_ = runner;
}

void GlobalActivityTracker::SetProcessExitCallback(
    ProcessExitCallback callback) {
  AutoLock lock(global_tracker_lock_);
  process_exit_callback_ = callback;
}

void GlobalActivityTracker::RecordProcessLaunch(
    ProcessId process_id,
    const FilePath::StringType& cmd) {
  const int64_t pid = process_id;
  DCHECK_NE(GetProcessId(), pid);
  DCHECK_NE(0, pid);

  base::AutoLock lock(global_tracker_lock_);
  if (base::ContainsKey(known_processes_, pid)) {
    // TODO(bcwhite): Measure this in UMA.
    NOTREACHED() << "Process #" << process_id
                 << " was previously recorded as \"launched\""
                 << " with no corresponding exit.\n"
                 << known_processes_[pid];
    known_processes_.erase(pid);
  }

#if defined(OS_WIN)
  known_processes_.insert(std::make_pair(pid, UTF16ToUTF8(cmd)));
#else
  known_processes_.insert(std::make_pair(pid, cmd));
#endif
}

void GlobalActivityTracker::RecordProcessLaunch(
    ProcessId process_id,
    const FilePath::StringType& exe,
    const FilePath::StringType& args) {
  if (exe.find(FILE_PATH_LITERAL(" "))) {
    RecordProcessLaunch(process_id,
                        FilePath::StringType(FILE_PATH_LITERAL("\"")) + exe +
                            FILE_PATH_LITERAL("\" ") + args);
  } else {
    RecordProcessLaunch(process_id, exe + FILE_PATH_LITERAL(' ') + args);
  }
}

void GlobalActivityTracker::RecordProcessExit(ProcessId process_id,
                                              int exit_code) {
  const int64_t pid = process_id;
  DCHECK_NE(GetProcessId(), pid);
  DCHECK_NE(0, pid);

  scoped_refptr<TaskRunner> task_runner;
  std::string command_line;
  {
    base::AutoLock lock(global_tracker_lock_);
    task_runner = background_task_runner_;
    auto found = known_processes_.find(pid);
    if (found != known_processes_.end()) {
      command_line = std::move(found->second);
      known_processes_.erase(found);
    } else {
      DLOG(ERROR) << "Recording exit of unknown process #" << process_id;
    }
  }

  // Use the current time to differentiate the process that just exited
  // from any that might be created in the future with the same ID.
  int64_t now_stamp = Time::Now().ToInternalValue();

  // The persistent allocator is thread-safe so run the iteration and
  // adjustments on a worker thread if one was provided.
  if (task_runner && !task_runner->RunsTasksInCurrentSequence()) {
    task_runner->PostTask(
        FROM_HERE,
        BindOnce(&GlobalActivityTracker::CleanupAfterProcess, Unretained(this),
                 pid, now_stamp, exit_code, std::move(command_line)));
    return;
  }

  CleanupAfterProcess(pid, now_stamp, exit_code, std::move(command_line));
}

void GlobalActivityTracker::SetProcessPhase(ProcessPhase phase) {
  process_data().SetInt(kProcessPhaseDataKey, phase);
}

void GlobalActivityTracker::CleanupAfterProcess(int64_t process_id,
                                                int64_t exit_stamp,
                                                int exit_code,
                                                std::string&& command_line) {
  // The process may not have exited cleanly so its necessary to go through
  // all the data structures it may have allocated in the persistent memory
  // segment and mark them as "released". This will allow them to be reused
  // later on.

  PersistentMemoryAllocator::Iterator iter(allocator_.get());
  PersistentMemoryAllocator::Reference ref;

  ProcessExitCallback process_exit_callback;
  {
    AutoLock lock(global_tracker_lock_);
    process_exit_callback = process_exit_callback_;
  }
  if (process_exit_callback) {
    // Find the processes user-data record so the process phase can be passed
    // to the callback.
    ActivityUserData::Snapshot process_data_snapshot;
    while ((ref = iter.GetNextOfType(kTypeIdProcessDataRecord)) != 0) {
      const void* memory = allocator_->GetAsArray<char>(
          ref, kTypeIdProcessDataRecord, PersistentMemoryAllocator::kSizeAny);
      if (!memory)
        continue;
      int64_t found_id;
      int64_t create_stamp;
      if (ActivityUserData::GetOwningProcessId(memory, &found_id,
                                               &create_stamp)) {
        if (found_id == process_id && create_stamp < exit_stamp) {
          const ActivityUserData process_data(const_cast<void*>(memory),
                                              allocator_->GetAllocSize(ref));
          process_data.CreateSnapshot(&process_data_snapshot);
          break;  // No need to look for any others.
        }
      }
    }
    iter.Reset();  // So it starts anew when used below.

    // Record the process's phase at exit so callback doesn't need to go
    // searching based on a private key value.
    ProcessPhase exit_phase = PROCESS_PHASE_UNKNOWN;
    auto phase = process_data_snapshot.find(kProcessPhaseDataKey);
    if (phase != process_data_snapshot.end())
      exit_phase = static_cast<ProcessPhase>(phase->second.GetInt());

    // Perform the callback.
    process_exit_callback.Run(process_id, exit_stamp, exit_code, exit_phase,
                              std::move(command_line),
                              std::move(process_data_snapshot));
  }

  // Find all allocations associated with the exited process and free them.
  uint32_t type;
  while ((ref = iter.GetNext(&type)) != 0) {
    switch (type) {
      case kTypeIdActivityTracker:
      case kTypeIdUserDataRecord:
      case kTypeIdProcessDataRecord:
      case ModuleInfoRecord::kPersistentTypeId: {
        const void* memory = allocator_->GetAsArray<char>(
            ref, type, PersistentMemoryAllocator::kSizeAny);
        if (!memory)
          continue;
        int64_t found_id;
        int64_t create_stamp;

        // By convention, the OwningProcess structure is always the first
        // field of the structure so there's no need to handle all the
        // cases separately.
        if (OwningProcess::GetOwningProcessId(memory, &found_id,
                                              &create_stamp)) {
          // Only change the type to be "free" if the process ID matches and
          // the creation time is before the exit time (so PID re-use doesn't
          // cause the erasure of something that is in-use). Memory is cleared
          // here, rather than when it's needed, so as to limit the impact at
          // that critical time.
          if (found_id == process_id && create_stamp < exit_stamp)
            allocator_->ChangeType(ref, ~type, type, /*clear=*/true);
        }
      } break;
    }
  }
}

void GlobalActivityTracker::RecordLogMessage(StringPiece message) {
  // Allocate at least one extra byte so the string is NUL terminated. All
  // memory returned by the allocator is guaranteed to be zeroed.
  PersistentMemoryAllocator::Reference ref =
      allocator_->Allocate(message.size() + 1, kTypeIdGlobalLogMessage);
  char* memory = allocator_->GetAsArray<char>(ref, kTypeIdGlobalLogMessage,
                                              message.size() + 1);
  if (memory) {
    memcpy(memory, message.data(), message.size());
    allocator_->MakeIterable(ref);
  }
}

void GlobalActivityTracker::RecordModuleInfo(const ModuleInfo& info) {
  AutoLock lock(modules_lock_);
  auto found = modules_.find(info.file);
  if (found != modules_.end()) {
    ModuleInfoRecord* record = found->second;
    DCHECK(record);

    // Update the basic state of module information that has been already
    // recorded. It is assumed that the string information (identifier,
    // version, etc.) remain unchanged which means that there's no need
    // to create a new record to accommodate a possibly longer length.
    record->UpdateFrom(info);
    return;
  }

  ModuleInfoRecord* record =
      ModuleInfoRecord::CreateFrom(info, allocator_.get());
  if (!record)
    return;
  allocator_->MakeIterable(record);
  modules_.emplace(info.file, record);
}

void GlobalActivityTracker::RecordFieldTrial(const std::string& trial_name,
                                             StringPiece group_name) {
  const std::string key = std::string("FieldTrial.") + trial_name;
  process_data_.SetString(key, group_name);
}

void GlobalActivityTracker::RecordException(const void* pc,
                                            const void* origin,
                                            uint32_t code) {
  RecordExceptionImpl(pc, origin, code);
}

void GlobalActivityTracker::MarkDeleted() {
  allocator_->SetMemoryState(PersistentMemoryAllocator::MEMORY_DELETED);
}

GlobalActivityTracker::GlobalActivityTracker(
    std::unique_ptr<PersistentMemoryAllocator> allocator,
    int stack_depth,
    int64_t process_id)
    : allocator_(std::move(allocator)),
      stack_memory_size_(ThreadActivityTracker::SizeForStackDepth(stack_depth)),
      process_id_(process_id == 0 ? GetCurrentProcId() : process_id),
      this_thread_tracker_(&OnTLSDestroy),
      thread_tracker_count_(0),
      thread_tracker_allocator_(allocator_.get(),
                                kTypeIdActivityTracker,
                                kTypeIdActivityTrackerFree,
                                stack_memory_size_,
                                kCachedThreadMemories,
                                /*make_iterable=*/true),
      user_data_allocator_(allocator_.get(),
                           kTypeIdUserDataRecord,
                           kTypeIdUserDataRecordFree,
                           kUserDataSize,
                           kCachedUserDataMemories,
                           /*make_iterable=*/true),
      process_data_(allocator_->GetAsArray<char>(
                        AllocateFrom(allocator_.get(),
                                     kTypeIdProcessDataRecordFree,
                                     kProcessDataSize,
                                     kTypeIdProcessDataRecord),
                        kTypeIdProcessDataRecord,
                        kProcessDataSize),
                    kProcessDataSize,
                    process_id_) {
  DCHECK_NE(0, process_id_);

  // Ensure that there is no other global object and then make this one such.
  DCHECK(!g_tracker_);
  subtle::Release_Store(&g_tracker_, reinterpret_cast<uintptr_t>(this));

  // The data records must be iterable in order to be found by an analyzer.
  allocator_->MakeIterable(allocator_->GetAsReference(
      process_data_.GetBaseAddress(), kTypeIdProcessDataRecord));

  // Note that this process has launched.
  SetProcessPhase(PROCESS_LAUNCHED);

  // Fetch and record all activated field trials.
  FieldTrial::ActiveGroups active_groups;
  FieldTrialList::GetActiveFieldTrialGroups(&active_groups);
  for (auto& group : active_groups)
    RecordFieldTrial(group.trial_name, group.group_name);
}

GlobalActivityTracker::~GlobalActivityTracker() {
  DCHECK(Get() == nullptr || Get() == this);
  DCHECK_EQ(0, thread_tracker_count_.load(std::memory_order_relaxed));
  subtle::Release_Store(&g_tracker_, 0);
}

void GlobalActivityTracker::ReturnTrackerMemory(
    ManagedActivityTracker* tracker) {
  PersistentMemoryAllocator::Reference mem_reference = tracker->mem_reference_;
  void* mem_base = tracker->mem_base_;
  DCHECK(mem_reference);
  DCHECK(mem_base);

  // Remove the destructed tracker from the set of known ones.
  DCHECK_LE(1, thread_tracker_count_.load(std::memory_order_relaxed));
  thread_tracker_count_.fetch_sub(1, std::memory_order_relaxed);

  // Release this memory for re-use at a later time.
  base::AutoLock autolock(thread_tracker_allocator_lock_);
  thread_tracker_allocator_.ReleaseObjectReference(mem_reference);
}

void GlobalActivityTracker::RecordExceptionImpl(const void* pc,
                                                const void* origin,
                                                uint32_t code) {
  // Get an existing tracker for this thread. It's not possible to create
  // one at this point because such would involve memory allocations and
  // other potentially complex operations that can cause failures if done
  // within an exception handler. In most cases various operations will
  // have already created the tracker so this shouldn't generally be a
  // problem.
  ThreadActivityTracker* tracker = GetTrackerForCurrentThread();
  if (!tracker)
    return;

  tracker->RecordExceptionActivity(pc, origin, Activity::ACT_EXCEPTION,
                                   ActivityData::ForException(code));
}

// static
void GlobalActivityTracker::OnTLSDestroy(void* value) {
  delete reinterpret_cast<ManagedActivityTracker*>(value);
}

ScopedActivity::ScopedActivity(const void* program_counter,
                               uint8_t action,
                               uint32_t id,
                               int32_t info)
    : GlobalActivityTracker::ScopedThreadActivity(
          program_counter,
          nullptr,
          static_cast<Activity::Type>(Activity::ACT_GENERIC | action),
          ActivityData::ForGeneric(id, info),
          /*lock_allowed=*/true),
      id_(id) {
  // The action must not affect the category bits of the activity type.
  DCHECK_EQ(0, action & Activity::ACT_CATEGORY_MASK);
}

void ScopedActivity::ChangeAction(uint8_t action) {
  DCHECK_EQ(0, action & Activity::ACT_CATEGORY_MASK);
  ChangeTypeAndData(static_cast<Activity::Type>(Activity::ACT_GENERIC | action),
                    kNullActivityData);
}

void ScopedActivity::ChangeInfo(int32_t info) {
  ChangeTypeAndData(Activity::ACT_NULL, ActivityData::ForGeneric(id_, info));
}

void ScopedActivity::ChangeActionAndInfo(uint8_t action, int32_t info) {
  DCHECK_EQ(0, action & Activity::ACT_CATEGORY_MASK);
  ChangeTypeAndData(static_cast<Activity::Type>(Activity::ACT_GENERIC | action),
                    ActivityData::ForGeneric(id_, info));
}

ScopedTaskRunActivity::ScopedTaskRunActivity(
    const void* program_counter,
    const base::PendingTask& task)
    : GlobalActivityTracker::ScopedThreadActivity(
          program_counter,
          task.posted_from.program_counter(),
          Activity::ACT_TASK_RUN,
          ActivityData::ForTask(task.sequence_num),
          /*lock_allowed=*/true) {}

ScopedLockAcquireActivity::ScopedLockAcquireActivity(
    const void* program_counter,
    const base::internal::LockImpl* lock)
    : GlobalActivityTracker::ScopedThreadActivity(
          program_counter,
          nullptr,
          Activity::ACT_LOCK_ACQUIRE,
          ActivityData::ForLock(lock),
          /*lock_allowed=*/false) {}

ScopedEventWaitActivity::ScopedEventWaitActivity(
    const void* program_counter,
    const base::WaitableEvent* event)
    : GlobalActivityTracker::ScopedThreadActivity(
          program_counter,
          nullptr,
          Activity::ACT_EVENT_WAIT,
          ActivityData::ForEvent(event),
          /*lock_allowed=*/true) {}

ScopedThreadJoinActivity::ScopedThreadJoinActivity(
    const void* program_counter,
    const base::PlatformThreadHandle* thread)
    : GlobalActivityTracker::ScopedThreadActivity(
          program_counter,
          nullptr,
          Activity::ACT_THREAD_JOIN,
          ActivityData::ForThread(*thread),
          /*lock_allowed=*/true) {}

#if !defined(OS_NACL) && !defined(OS_IOS)
ScopedProcessWaitActivity::ScopedProcessWaitActivity(
    const void* program_counter,
    const base::Process* process)
    : GlobalActivityTracker::ScopedThreadActivity(
          program_counter,
          nullptr,
          Activity::ACT_PROCESS_WAIT,
          ActivityData::ForProcess(process->Pid()),
          /*lock_allowed=*/true) {}
#endif

}  // namespace debug
}  // namespace base
