// 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"
#include "starboard/common/string.h"
#include "starboard/memory.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) && !defined(STARBOARD)
// 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;
}

#if !defined(STARBOARD)
// 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);
}
#endif

// 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);

#if !defined(STARBOARD)
  // 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);
#endif
}

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) && !defined(STARBOARD)
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
