// Copyright 2015 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/profiler/stack_sampling_profiler.h"

#include <algorithm>
#include <map>
#include <utility>

#include "base/atomic_sequence_num.h"
#include "base/atomicops.h"
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/callback.h"
#include "base/lazy_instance.h"
#include "base/location.h"
#include "base/macros.h"
#include "base/memory/ptr_util.h"
#include "base/memory/singleton.h"
#include "base/profiler/native_stack_sampler.h"
#include "base/synchronization/lock.h"
#include "base/threading/thread.h"
#include "base/threading/thread_restrictions.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/timer/elapsed_timer.h"

namespace base {

namespace {

// This value is used to initialize the WaitableEvent object. This MUST BE set
// to MANUAL for correct operation of the IsSignaled() call in Start(). See the
// comment there for why.
constexpr WaitableEvent::ResetPolicy kResetPolicy =
    WaitableEvent::ResetPolicy::MANUAL;

// This value is used when there is no collection in progress and thus no ID
// for referencing the active collection to the SamplingThread.
const int NULL_PROFILER_ID = -1;

void ChangeAtomicFlags(subtle::Atomic32* flags,
                       subtle::Atomic32 set,
                       subtle::Atomic32 clear) {
  DCHECK(set != 0 || clear != 0);
  DCHECK_EQ(0, set & clear);

  subtle::Atomic32 bits = subtle::NoBarrier_Load(flags);
  while (true) {
    subtle::Atomic32 existing =
        subtle::NoBarrier_CompareAndSwap(flags, bits, (bits | set) & ~clear);
    if (existing == bits)
      break;
    bits = existing;
  }
}

}  // namespace

// StackSamplingProfiler::Module ----------------------------------------------

StackSamplingProfiler::Module::Module() : base_address(0u) {}
StackSamplingProfiler::Module::Module(uintptr_t base_address,
                                      const std::string& id,
                                      const FilePath& filename)
    : base_address(base_address), id(id), filename(filename) {}

StackSamplingProfiler::Module::~Module() = default;

// StackSamplingProfiler::Frame -----------------------------------------------

StackSamplingProfiler::Frame::Frame(uintptr_t instruction_pointer,
                                    size_t module_index)
    : instruction_pointer(instruction_pointer), module_index(module_index) {}

StackSamplingProfiler::Frame::~Frame() = default;

StackSamplingProfiler::Frame::Frame()
    : instruction_pointer(0), module_index(kUnknownModuleIndex) {
}

// StackSamplingProfiler::Sample ----------------------------------------------

StackSamplingProfiler::Sample::Sample() = default;

StackSamplingProfiler::Sample::Sample(const Sample& sample) = default;

StackSamplingProfiler::Sample::~Sample() = default;

StackSamplingProfiler::Sample::Sample(const Frame& frame) {
  frames.push_back(std::move(frame));
}

StackSamplingProfiler::Sample::Sample(const std::vector<Frame>& frames)
    : frames(frames) {}

// StackSamplingProfiler::CallStackProfile ------------------------------------

StackSamplingProfiler::CallStackProfile::CallStackProfile() = default;

StackSamplingProfiler::CallStackProfile::CallStackProfile(
    CallStackProfile&& other) = default;

StackSamplingProfiler::CallStackProfile::~CallStackProfile() = default;

StackSamplingProfiler::CallStackProfile&
StackSamplingProfiler::CallStackProfile::operator=(CallStackProfile&& other) =
    default;

StackSamplingProfiler::CallStackProfile
StackSamplingProfiler::CallStackProfile::CopyForTesting() const {
  return CallStackProfile(*this);
}

StackSamplingProfiler::CallStackProfile::CallStackProfile(
    const CallStackProfile& other) = default;

// StackSamplingProfiler::SamplingThread --------------------------------------

class StackSamplingProfiler::SamplingThread : public Thread {
 public:
  class TestAPI {
   public:
    // Reset the existing sampler. This will unfortunately create the object
    // unnecessarily if it doesn't already exist but there's no way around that.
    static void Reset();

    // Disables inherent idle-shutdown behavior.
    static void DisableIdleShutdown();

    // Begins an idle shutdown as if the idle-timer had expired and wait for
    // it to execute. Since the timer would have only been started at a time
    // when the sampling thread actually was idle, this must be called only
    // when it is known that there are no active sampling threads. If
    // |simulate_intervening_add| is true then, when executed, the shutdown
    // task will believe that a new collection has been added since it was
    // posted.
    static void ShutdownAssumingIdle(bool simulate_intervening_add);

   private:
    // Calls the sampling threads ShutdownTask and then signals an event.
    static void ShutdownTaskAndSignalEvent(SamplingThread* sampler,
                                           int add_events,
                                           WaitableEvent* event);
  };

  struct CollectionContext {
    CollectionContext(int profiler_id,
                      PlatformThreadId target,
                      const SamplingParams& params,
                      const CompletedCallback& callback,
                      WaitableEvent* finished,
                      std::unique_ptr<NativeStackSampler> sampler)
        : profiler_id(profiler_id),
          target(target),
          params(params),
          callback(callback),
          finished(finished),
          native_sampler(std::move(sampler)) {}
    ~CollectionContext() = default;

    // An identifier for the profiler associated with this collection, used to
    // uniquely identify the collection to outside interests.
    const int profiler_id;

    const PlatformThreadId target;     // ID of The thread being sampled.
    const SamplingParams params;       // Information about how to sample.
    const CompletedCallback callback;  // Callback made when sampling complete.
    WaitableEvent* const finished;     // Signaled when all sampling complete.

    // Platform-specific module that does the actual sampling.
    std::unique_ptr<NativeStackSampler> native_sampler;

    // The absolute time for the next sample.
    Time next_sample_time;

    // The time that a profile was started, for calculating the total duration.
    Time profile_start_time;

    // Counters that indicate the current position along the acquisition.
    int burst = 0;
    int sample = 0;

    // The collected stack samples. The active profile is always at the back().
    CallStackProfiles profiles;

    // Sequence number for generating new profiler ids.
    static AtomicSequenceNumber next_profiler_id;
  };

  // Gets the single instance of this class.
  static SamplingThread* GetInstance();

  // Adds a new CollectionContext to the thread. This can be called externally
  // from any thread. This returns an ID that can later be used to stop
  // the sampling.
  int Add(std::unique_ptr<CollectionContext> collection);

  // Removes an active collection based on its ID, forcing it to run its
  // callback if any data has been collected. This can be called externally
  // from any thread.
  void Remove(int id);

 private:
  friend class TestAPI;
  friend struct DefaultSingletonTraits<SamplingThread>;

  // The different states in which the sampling-thread can be.
  enum ThreadExecutionState {
    // The thread is not running because it has never been started. It will be
    // started when a sampling request is received.
    NOT_STARTED,

    // The thread is running and processing tasks. This is the state when any
    // sampling requests are active and during the "idle" period afterward
    // before the thread is stopped.
    RUNNING,

    // Once all sampling requests have finished and the "idle" period has
    // expired, the thread will be set to this state and its shutdown
    // initiated. A call to Stop() must be made to ensure the previous thread
    // has completely exited before calling Start() and moving back to the
    // RUNNING state.
    EXITING,
  };

  SamplingThread();
  ~SamplingThread() override;

  // Get task runner that is usable from the outside.
  scoped_refptr<SingleThreadTaskRunner> GetOrCreateTaskRunnerForAdd();
  scoped_refptr<SingleThreadTaskRunner> GetTaskRunner(
      ThreadExecutionState* out_state);

  // Get task runner that is usable from the sampling thread itself.
  scoped_refptr<SingleThreadTaskRunner> GetTaskRunnerOnSamplingThread();

  // Finishes a collection and reports collected data via callback. The
  // collection's |finished| waitable event will be signalled. The |collection|
  // should already have been removed from |active_collections_| by the caller,
  // as this is needed to avoid flakyness in unit tests.
  void FinishCollection(CollectionContext* collection);

  // Records a single sample of a collection.
  void RecordSample(CollectionContext* collection);

  // Check if the sampling thread is idle and begin a shutdown if it is.
  void ScheduleShutdownIfIdle();

  // These methods are tasks that get posted to the internal message queue.
  void AddCollectionTask(std::unique_ptr<CollectionContext> collection);
  void RemoveCollectionTask(int id);
  void PerformCollectionTask(int id);
  void ShutdownTask(int add_events);

  // Updates the |next_sample_time| time based on configured parameters.
  // Returns true if there is a next sample or false if sampling is complete.
  bool UpdateNextSampleTime(CollectionContext* collection);

  // Thread:
  void CleanUp() override;

  // A stack-buffer used by the native sampler for its work. This buffer can
  // be re-used for multiple native sampler objects so long as the API calls
  // that take it are not called concurrently.
  std::unique_ptr<NativeStackSampler::StackBuffer> stack_buffer_;

  // A map of IDs to collection contexts. Because this class is a singleton
  // that is never destroyed, context objects will never be destructed except
  // by explicit action. Thus, it's acceptable to pass unretained pointers
  // to these objects when posting tasks.
  std::map<int, std::unique_ptr<CollectionContext>> active_collections_;

  // State maintained about the current execution (or non-execution) of
  // the thread. This state must always be accessed while holding the
  // lock. A copy of the task-runner is maintained here for use by any
  // calling thread; this is necessary because Thread's accessor for it is
  // not itself thread-safe. The lock is also used to order calls to the
  // Thread API (Start, Stop, StopSoon, & DetachFromSequence) so that
  // multiple threads may make those calls.
  Lock thread_execution_state_lock_;  // Protects all thread_execution_state_*
  ThreadExecutionState thread_execution_state_ = NOT_STARTED;
  scoped_refptr<SingleThreadTaskRunner> thread_execution_state_task_runner_;
  bool thread_execution_state_disable_idle_shutdown_for_testing_ = false;

  // A counter that notes adds of new collection requests. It is incremented
  // when changes occur so that delayed shutdown tasks are able to detect if
  // samething new has happened while it was waiting. Like all "execution_state"
  // vars, this must be accessed while holding |thread_execution_state_lock_|.
  int thread_execution_state_add_events_ = 0;

  DISALLOW_COPY_AND_ASSIGN(SamplingThread);
};

// static
void StackSamplingProfiler::SamplingThread::TestAPI::Reset() {
  SamplingThread* sampler = SamplingThread::GetInstance();

  ThreadExecutionState state;
  {
    AutoLock lock(sampler->thread_execution_state_lock_);
    state = sampler->thread_execution_state_;
    DCHECK(sampler->active_collections_.empty());
  }

  // Stop the thread and wait for it to exit. This has to be done through by
  // the thread itself because it has taken ownership of its own lifetime.
  if (state == RUNNING) {
    ShutdownAssumingIdle(false);
    state = EXITING;
  }
  // Make sure thread is cleaned up since state will be reset to NOT_STARTED.
  if (state == EXITING)
    sampler->Stop();

  // Reset internal variables to the just-initialized state.
  {
    AutoLock lock(sampler->thread_execution_state_lock_);
    sampler->thread_execution_state_ = NOT_STARTED;
    sampler->thread_execution_state_task_runner_ = nullptr;
    sampler->thread_execution_state_disable_idle_shutdown_for_testing_ = false;
    sampler->thread_execution_state_add_events_ = 0;
  }
}

// static
void StackSamplingProfiler::SamplingThread::TestAPI::DisableIdleShutdown() {
  SamplingThread* sampler = SamplingThread::GetInstance();

  {
    AutoLock lock(sampler->thread_execution_state_lock_);
    sampler->thread_execution_state_disable_idle_shutdown_for_testing_ = true;
  }
}

// static
void StackSamplingProfiler::SamplingThread::TestAPI::ShutdownAssumingIdle(
    bool simulate_intervening_add) {
  SamplingThread* sampler = SamplingThread::GetInstance();

  ThreadExecutionState state;
  scoped_refptr<SingleThreadTaskRunner> task_runner =
      sampler->GetTaskRunner(&state);
  DCHECK_EQ(RUNNING, state);
  DCHECK(task_runner);

  int add_events;
  {
    AutoLock lock(sampler->thread_execution_state_lock_);
    add_events = sampler->thread_execution_state_add_events_;
    if (simulate_intervening_add)
      ++sampler->thread_execution_state_add_events_;
  }

  WaitableEvent executed(WaitableEvent::ResetPolicy::MANUAL,
                         WaitableEvent::InitialState::NOT_SIGNALED);
  // PostTaskAndReply won't work because thread and associated message-loop may
  // be shut down.
  task_runner->PostTask(
      FROM_HERE, BindOnce(&ShutdownTaskAndSignalEvent, Unretained(sampler),
                          add_events, Unretained(&executed)));
  executed.Wait();
}

// static
void StackSamplingProfiler::SamplingThread::TestAPI::ShutdownTaskAndSignalEvent(
    SamplingThread* sampler,
    int add_events,
    WaitableEvent* event) {
  sampler->ShutdownTask(add_events);
  event->Signal();
}

AtomicSequenceNumber
    StackSamplingProfiler::SamplingThread::CollectionContext::next_profiler_id;

StackSamplingProfiler::SamplingThread::SamplingThread()
    : Thread("StackSamplingProfiler") {}

StackSamplingProfiler::SamplingThread::~SamplingThread() = default;

StackSamplingProfiler::SamplingThread*
StackSamplingProfiler::SamplingThread::GetInstance() {
  return Singleton<SamplingThread, LeakySingletonTraits<SamplingThread>>::get();
}

int StackSamplingProfiler::SamplingThread::Add(
    std::unique_ptr<CollectionContext> collection) {
  // This is not to be run on the sampling thread.

  int id = collection->profiler_id;
  scoped_refptr<SingleThreadTaskRunner> task_runner =
      GetOrCreateTaskRunnerForAdd();

  task_runner->PostTask(
      FROM_HERE, BindOnce(&SamplingThread::AddCollectionTask, Unretained(this),
                          std::move(collection)));

  return id;
}

void StackSamplingProfiler::SamplingThread::Remove(int id) {
  // This is not to be run on the sampling thread.

  ThreadExecutionState state;
  scoped_refptr<SingleThreadTaskRunner> task_runner = GetTaskRunner(&state);
  if (state != RUNNING)
    return;
  DCHECK(task_runner);

  // This can fail if the thread were to exit between acquisition of the task
  // runner above and the call below. In that case, however, everything has
  // stopped so there's no need to try to stop it.
  task_runner->PostTask(
      FROM_HERE,
      BindOnce(&SamplingThread::RemoveCollectionTask, Unretained(this), id));
}

scoped_refptr<SingleThreadTaskRunner>
StackSamplingProfiler::SamplingThread::GetOrCreateTaskRunnerForAdd() {
  AutoLock lock(thread_execution_state_lock_);

  // The increment of the "add events" count is why this method is to be only
  // called from "add".
  ++thread_execution_state_add_events_;

  if (thread_execution_state_ == RUNNING) {
    DCHECK(thread_execution_state_task_runner_);
    // This shouldn't be called from the sampling thread as it's inefficient.
    // Use GetTaskRunnerOnSamplingThread() instead.
    DCHECK_NE(GetThreadId(), PlatformThread::CurrentId());
    return thread_execution_state_task_runner_;
  }

  if (thread_execution_state_ == EXITING) {
    // StopSoon() was previously called to shut down the thread
    // asynchonously. Stop() must now be called before calling Start() again to
    // reset the thread state.
    //
    // We must allow blocking here to satisfy the Thread implementation, but in
    // practice the Stop() call is unlikely to actually block. For this to
    // happen a new profiling request would have to be made within the narrow
    // window between StopSoon() and thread exit following the end of the 60
    // second idle period.
    ScopedAllowBlocking allow_blocking;
    Stop();
  }

  DCHECK(!stack_buffer_);
  stack_buffer_ = NativeStackSampler::CreateStackBuffer();

  // The thread is not running. Start it and get associated runner. The task-
  // runner has to be saved for future use because though it can be used from
  // any thread, it can be acquired via task_runner() only on the created
  // thread and the thread that creates it (i.e. this thread) for thread-safety
  // reasons which are alleviated in SamplingThread by gating access to it with
  // the |thread_execution_state_lock_|.
  Start();
  thread_execution_state_ = RUNNING;
  thread_execution_state_task_runner_ = Thread::task_runner();

  // Detach the sampling thread from the "sequence" (i.e. thread) that
  // started it so that it can be self-managed or stopped by another thread.
  DetachFromSequence();

  return thread_execution_state_task_runner_;
}

scoped_refptr<SingleThreadTaskRunner>
StackSamplingProfiler::SamplingThread::GetTaskRunner(
    ThreadExecutionState* out_state) {
  AutoLock lock(thread_execution_state_lock_);
  if (out_state)
    *out_state = thread_execution_state_;
  if (thread_execution_state_ == RUNNING) {
    // This shouldn't be called from the sampling thread as it's inefficient.
    // Use GetTaskRunnerOnSamplingThread() instead.
    DCHECK_NE(GetThreadId(), PlatformThread::CurrentId());
    DCHECK(thread_execution_state_task_runner_);
  } else {
    DCHECK(!thread_execution_state_task_runner_);
  }

  return thread_execution_state_task_runner_;
}

scoped_refptr<SingleThreadTaskRunner>
StackSamplingProfiler::SamplingThread::GetTaskRunnerOnSamplingThread() {
  // This should be called only from the sampling thread as it has limited
  // accessibility.
  DCHECK_EQ(GetThreadId(), PlatformThread::CurrentId());

  return Thread::task_runner();
}

void StackSamplingProfiler::SamplingThread::FinishCollection(
    CollectionContext* collection) {
  DCHECK_EQ(GetThreadId(), PlatformThread::CurrentId());
  DCHECK_EQ(0u, active_collections_.count(collection->profiler_id));

  // If there is no duration for the final profile (because it was stopped),
  // calculate it now.
  if (!collection->profiles.empty() &&
      collection->profiles.back().profile_duration == TimeDelta()) {
    collection->profiles.back().profile_duration =
        Time::Now() - collection->profile_start_time +
        collection->params.sampling_interval;
  }

  // Extract some information so callback and event-signalling can still be
  // done after the collection has been removed from the list of "active" ones.
  // This allows the the controlling object (and tests using it) to be confident
  // that collection is fully finished when those things occur.
  const CompletedCallback callback = collection->callback;
  CallStackProfiles profiles = std::move(collection->profiles);
  WaitableEvent* finished = collection->finished;

  // Run the associated callback, passing the collected profiles.
  callback.Run(std::move(profiles));

  // Signal that this collection is finished.
  finished->Signal();
}

void StackSamplingProfiler::SamplingThread::RecordSample(
    CollectionContext* collection) {
  DCHECK_EQ(GetThreadId(), PlatformThread::CurrentId());
  DCHECK(collection->native_sampler);

  // If this is the first sample of a burst, a new Profile needs to be created
  // and filled.
  if (collection->sample == 0) {
    collection->profiles.push_back(CallStackProfile());
    CallStackProfile& profile = collection->profiles.back();
    profile.sampling_period = collection->params.sampling_interval;
    collection->profile_start_time = Time::Now();
    collection->native_sampler->ProfileRecordingStarting(&profile.modules);
  }

  // The currently active profile being captured.
  CallStackProfile& profile = collection->profiles.back();

  // Record a single sample.
  profile.samples.push_back(Sample());
  collection->native_sampler->RecordStackSample(stack_buffer_.get(),
                                                &profile.samples.back());

  // If this is the last sample of a burst, record the total time.
  if (collection->sample == collection->params.samples_per_burst - 1) {
    profile.profile_duration = Time::Now() - collection->profile_start_time +
                               collection->params.sampling_interval;
    collection->native_sampler->ProfileRecordingStopped(stack_buffer_.get());
  }
}

void StackSamplingProfiler::SamplingThread::ScheduleShutdownIfIdle() {
  DCHECK_EQ(GetThreadId(), PlatformThread::CurrentId());

  if (!active_collections_.empty())
    return;

  int add_events;
  {
    AutoLock lock(thread_execution_state_lock_);
    if (thread_execution_state_disable_idle_shutdown_for_testing_)
      return;
    add_events = thread_execution_state_add_events_;
  }

  GetTaskRunnerOnSamplingThread()->PostDelayedTask(
      FROM_HERE,
      BindOnce(&SamplingThread::ShutdownTask, Unretained(this), add_events),
      TimeDelta::FromSeconds(60));
}

void StackSamplingProfiler::SamplingThread::AddCollectionTask(
    std::unique_ptr<CollectionContext> collection) {
  DCHECK_EQ(GetThreadId(), PlatformThread::CurrentId());

  const int profiler_id = collection->profiler_id;
  const TimeDelta initial_delay = collection->params.initial_delay;

  active_collections_.insert(
      std::make_pair(profiler_id, std::move(collection)));

  GetTaskRunnerOnSamplingThread()->PostDelayedTask(
      FROM_HERE,
      BindOnce(&SamplingThread::PerformCollectionTask, Unretained(this),
               profiler_id),
      initial_delay);

  // Another increment of "add events" serves to invalidate any pending
  // shutdown tasks that may have been initiated between the Add() and this
  // task running.
  {
    AutoLock lock(thread_execution_state_lock_);
    ++thread_execution_state_add_events_;
  }
}

void StackSamplingProfiler::SamplingThread::RemoveCollectionTask(int id) {
  DCHECK_EQ(GetThreadId(), PlatformThread::CurrentId());

  auto found = active_collections_.find(id);
  if (found == active_collections_.end())
    return;

  // Remove |collection| from |active_collections_|.
  std::unique_ptr<CollectionContext> collection = std::move(found->second);
  size_t count = active_collections_.erase(id);
  DCHECK_EQ(1U, count);

  FinishCollection(collection.get());
  ScheduleShutdownIfIdle();
}

void StackSamplingProfiler::SamplingThread::PerformCollectionTask(int id) {
  DCHECK_EQ(GetThreadId(), PlatformThread::CurrentId());

  auto found = active_collections_.find(id);

  // The task won't be found if it has been stopped.
  if (found == active_collections_.end())
    return;

  CollectionContext* collection = found->second.get();

  // Handle first-run with no "next time".
  if (collection->next_sample_time == Time())
    collection->next_sample_time = Time::Now();

  // Do the collection of a single sample.
  RecordSample(collection);

  // Update the time of the next sample recording.
  const bool collection_finished = !UpdateNextSampleTime(collection);
  if (!collection_finished) {
    bool success = GetTaskRunnerOnSamplingThread()->PostDelayedTask(
        FROM_HERE,
        BindOnce(&SamplingThread::PerformCollectionTask, Unretained(this), id),
        std::max(collection->next_sample_time - Time::Now(), TimeDelta()));
    DCHECK(success);
    return;
  }

  // Take ownership of |collection| and remove it from the map. If collection is
  // to be restarted, a new collection task will be added below.
  std::unique_ptr<CollectionContext> owned_collection =
      std::move(found->second);
  size_t count = active_collections_.erase(id);
  DCHECK_EQ(1U, count);

  // All capturing has completed so finish the collection.
  FinishCollection(collection);
  ScheduleShutdownIfIdle();
}

void StackSamplingProfiler::SamplingThread::ShutdownTask(int add_events) {
  DCHECK_EQ(GetThreadId(), PlatformThread::CurrentId());

  // Holding this lock ensures that any attempt to start another job will
  // get postponed until |thread_execution_state_| is updated, thus eliminating
  // the race in starting a new thread while the previous one is exiting.
  AutoLock lock(thread_execution_state_lock_);

  // If the current count of creation requests doesn't match the passed count
  // then other tasks have been created since this was posted. Abort shutdown.
  if (thread_execution_state_add_events_ != add_events)
    return;

  // There can be no new AddCollectionTasks at this point because creating
  // those always increments "add events". There may be other requests, like
  // Remove, but it's okay to schedule the thread to stop once they've been
  // executed (i.e. "soon").
  DCHECK(active_collections_.empty());
  StopSoon();

  // StopSoon will have set the owning sequence (again) so it must be detached
  // (again) in order for Stop/Start to be called (again) should more work
  // come in. Holding the |thread_execution_state_lock_| ensures the necessary
  // happens-after with regard to this detach and future Thread API calls.
  DetachFromSequence();

  // Set the thread_state variable so the thread will be restarted when new
  // work comes in. Remove the |thread_execution_state_task_runner_| to avoid
  // confusion.
  thread_execution_state_ = EXITING;
  thread_execution_state_task_runner_ = nullptr;
  stack_buffer_.reset();
}

bool StackSamplingProfiler::SamplingThread::UpdateNextSampleTime(
    CollectionContext* collection) {
  // This will keep a consistent average interval between samples but will
  // result in constant series of acquisitions, thus nearly locking out the
  // target thread, if the interval is smaller than the time it takes to
  // actually acquire the sample. Anything sampling that quickly is going
  // to be a problem anyway so don't worry about it.
  if (++collection->sample < collection->params.samples_per_burst) {
    collection->next_sample_time += collection->params.sampling_interval;
    return true;
  }

  if (++collection->burst < collection->params.bursts) {
    collection->sample = 0;
    collection->next_sample_time += collection->params.burst_interval;
    return true;
  }

  return false;
}

void StackSamplingProfiler::SamplingThread::CleanUp() {
  DCHECK_EQ(GetThreadId(), PlatformThread::CurrentId());

  // There should be no collections remaining when the thread stops.
  DCHECK(active_collections_.empty());

  // Let the parent clean up.
  Thread::CleanUp();
}

// StackSamplingProfiler ------------------------------------------------------

// static
void StackSamplingProfiler::TestAPI::Reset() {
  SamplingThread::TestAPI::Reset();
  ResetAnnotations();
}

// static
void StackSamplingProfiler::TestAPI::ResetAnnotations() {
  subtle::NoBarrier_Store(&process_milestones_, 0u);
}

// static
bool StackSamplingProfiler::TestAPI::IsSamplingThreadRunning() {
  return SamplingThread::GetInstance()->IsRunning();
}

// static
void StackSamplingProfiler::TestAPI::DisableIdleShutdown() {
  SamplingThread::TestAPI::DisableIdleShutdown();
}

// static
void StackSamplingProfiler::TestAPI::PerformSamplingThreadIdleShutdown(
    bool simulate_intervening_start) {
  SamplingThread::TestAPI::ShutdownAssumingIdle(simulate_intervening_start);
}

subtle::Atomic32 StackSamplingProfiler::process_milestones_ = 0;

StackSamplingProfiler::StackSamplingProfiler(
    const SamplingParams& params,
    const CompletedCallback& callback,
    NativeStackSamplerTestDelegate* test_delegate)
    : StackSamplingProfiler(base::PlatformThread::CurrentId(),
                            params,
                            callback,
                            test_delegate) {}

StackSamplingProfiler::StackSamplingProfiler(
    PlatformThreadId thread_id,
    const SamplingParams& params,
    const CompletedCallback& callback,
    NativeStackSamplerTestDelegate* test_delegate)
    : thread_id_(thread_id),
      params_(params),
      completed_callback_(callback),
      // The event starts "signaled" so code knows it's safe to start thread
      // and "manual" so that it can be waited in multiple places.
      profiling_inactive_(kResetPolicy, WaitableEvent::InitialState::SIGNALED),
      profiler_id_(NULL_PROFILER_ID),
      test_delegate_(test_delegate) {}

StackSamplingProfiler::~StackSamplingProfiler() {
  // Stop returns immediately but the shutdown runs asynchronously. There is a
  // non-zero probability that one more sample will be taken after this call
  // returns.
  Stop();

  // The behavior of sampling a thread that has exited is undefined and could
  // cause Bad Things(tm) to occur. The safety model provided by this class is
  // that an instance of this object is expected to live at least as long as
  // the thread it is sampling. However, because the sampling is performed
  // asynchronously by the SamplingThread, there is no way to guarantee this
  // is true without waiting for it to signal that it has finished.
  //
  // The wait time should, at most, be only as long as it takes to collect one
  // sample (~200us) or none at all if sampling has already completed.
  ThreadRestrictions::ScopedAllowWait allow_wait;
  profiling_inactive_.Wait();
}

void StackSamplingProfiler::Start() {
  if (completed_callback_.is_null())
    return;

  std::unique_ptr<NativeStackSampler> native_sampler =
      NativeStackSampler::Create(thread_id_, &RecordAnnotations,
                                 test_delegate_);

  if (!native_sampler)
    return;

  // The IsSignaled() check below requires that the WaitableEvent be manually
  // reset, to avoid signaling the event in IsSignaled() itself.
  static_assert(kResetPolicy == WaitableEvent::ResetPolicy::MANUAL,
                "The reset policy must be set to MANUAL");

  // If a previous profiling phase is still winding down, wait for it to
  // complete. We can't use task posting for this coordination because the
  // thread owning the profiler may not have a message loop.
  if (!profiling_inactive_.IsSignaled())
    profiling_inactive_.Wait();
  profiling_inactive_.Reset();

  DCHECK_EQ(NULL_PROFILER_ID, profiler_id_);
  profiler_id_ = SamplingThread::GetInstance()->Add(
      std::make_unique<SamplingThread::CollectionContext>(
          SamplingThread::CollectionContext::next_profiler_id.GetNext(),
          thread_id_, params_, completed_callback_, &profiling_inactive_,
          std::move(native_sampler)));
  DCHECK_NE(NULL_PROFILER_ID, profiler_id_);
}

void StackSamplingProfiler::Stop() {
  SamplingThread::GetInstance()->Remove(profiler_id_);
  profiler_id_ = NULL_PROFILER_ID;
}

// static
void StackSamplingProfiler::SetProcessMilestone(int milestone) {
  DCHECK_LE(0, milestone);
  DCHECK_GT(static_cast<int>(sizeof(process_milestones_) * 8), milestone);
  DCHECK_EQ(0, subtle::NoBarrier_Load(&process_milestones_) & (1 << milestone));
  ChangeAtomicFlags(&process_milestones_, 1 << milestone, 0);
}

// static
void StackSamplingProfiler::RecordAnnotations(Sample* sample) {
  // The code inside this method must not do anything that could acquire a
  // mutex, including allocating memory (which includes LOG messages) because
  // that mutex could be held by a stopped thread, thus resulting in deadlock.
  sample->process_milestones = subtle::NoBarrier_Load(&process_milestones_);
}

// StackSamplingProfiler::Frame global functions ------------------------------

bool operator==(const StackSamplingProfiler::Module& a,
                const StackSamplingProfiler::Module& b) {
  return a.base_address == b.base_address && a.id == b.id &&
      a.filename == b.filename;
}

bool operator==(const StackSamplingProfiler::Sample& a,
                const StackSamplingProfiler::Sample& b) {
  return a.process_milestones == b.process_milestones && a.frames == b.frames;
}

bool operator!=(const StackSamplingProfiler::Sample& a,
                const StackSamplingProfiler::Sample& b) {
  return !(a == b);
}

bool operator<(const StackSamplingProfiler::Sample& a,
               const StackSamplingProfiler::Sample& b) {
  if (a.process_milestones < b.process_milestones)
    return true;
  if (a.process_milestones > b.process_milestones)
    return false;

  return a.frames < b.frames;
}

bool operator==(const StackSamplingProfiler::Frame &a,
                const StackSamplingProfiler::Frame &b) {
  return a.instruction_pointer == b.instruction_pointer &&
      a.module_index == b.module_index;
}

bool operator<(const StackSamplingProfiler::Frame &a,
               const StackSamplingProfiler::Frame &b) {
  return (a.module_index < b.module_index) ||
      (a.module_index == b.module_index &&
       a.instruction_pointer < b.instruction_pointer);
}

}  // namespace base
