chromium/services/tracing/public/cpp/stack_sampling/loader_lock_sampling_thread_win.h

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

#ifndef SERVICES_TRACING_PUBLIC_CPP_STACK_SAMPLING_LOADER_LOCK_SAMPLING_THREAD_WIN_H_
#define SERVICES_TRACING_PUBLIC_CPP_STACK_SAMPLING_LOADER_LOCK_SAMPLING_THREAD_WIN_H_

#include "base/component_export.h"
#include "base/threading/sequence_bound.h"
#include "base/threading/thread.h"
#include "base/timer/timer.h"

namespace tracing {

class LoaderLockSampler;

// A thread that periodically samples the Windows loader lock to see if it is
// being held. This is a dedicated thread, instead of using the ThreadPool, so
// that there's never a chance of the lock being sampled from a thread that
// runs other code that takes the lock.
class COMPONENT_EXPORT(TRACING_CPP) LoaderLockSamplingThread final
    : public base::Thread {
 public:
  LoaderLockSamplingThread();
  ~LoaderLockSamplingThread() override;

  LoaderLockSamplingThread(const LoaderLockSamplingThread& other) = delete;
  LoaderLockSamplingThread& operator=(const LoaderLockSamplingThread& other) =
      delete;

  // The name of a trace event that will be recorded when the loader lock is
  // held. Exposed for testing.
  static const char kLoaderLockHeldEventName[];

  // Registers a mock LoaderLockSampler to be called during tests. |sampler| is
  // owned by the caller. It must be reset to |nullptr| at the end of the test,
  // which will cause the default ProbingLoaderLockSampler to be used.
  static void SetLoaderLockSamplerForTesting(LoaderLockSampler* sampler);

  // Begins periodic sampling. This can be called from any thread, and the
  // sampling will be performed on the LoaderLockSamplingThread.
  void StartSampling();

  // Stops periodic sampling. This can be called from any thread.
  void StopSampling();

 private:
  // Class that performs the sampling on the sampling thread.
  class LoaderLockTracker {
   public:
    LoaderLockTracker() = default;
    ~LoaderLockTracker() = default;

    LoaderLockTracker(const LoaderLockTracker& other) = delete;
    LoaderLockTracker& operator=(const LoaderLockTracker& other) = delete;

    void StartSampling();
    void StopSampling();

   private:
    void SampleLoaderLock();

    base::RepeatingTimer sample_timer_;
    bool loader_lock_is_held_ = false;
  };

  base::SequenceBound<LoaderLockTracker> tracker_;
};

}  // namespace tracing

#endif  // SERVICES_TRACING_PUBLIC_CPP_STACK_SAMPLING_LOADER_LOCK_SAMPLING_THREAD_WIN_H_