chromium/base/threading/hang_watcher.h

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

#ifndef BASE_THREADING_HANG_WATCHER_H_
#define BASE_THREADING_HANG_WATCHER_H_

#include <atomic>
#include <cstdint>
#include <memory>
#include <type_traits>
#include <vector>

#include "base/atomicops.h"
#include "base/auto_reset.h"
#include "base/base_export.h"
#include "base/bits.h"
#include "base/compiler_specific.h"
#include "base/dcheck_is_on.h"
#include "base/debug/crash_logging.h"
#include "base/functional/callback.h"
#include "base/functional/callback_forward.h"
#include "base/functional/callback_helpers.h"
#include "base/gtest_prod_util.h"
#include "base/memory/memory_pressure_listener.h"
#include "base/memory/raw_ptr.h"
#include "base/synchronization/lock.h"
#include "base/synchronization/waitable_event.h"
#include "base/thread_annotations.h"
#include "base/threading/platform_thread.h"
#include "base/threading/simple_thread.h"
#include "base/threading/thread_checker.h"
#include "base/time/tick_clock.h"
#include "base/time/time.h"
#include "build/build_config.h"

namespace base {
class WatchHangsInScope;
namespace internal {
class HangWatchState;
}  // namespace internal
}  // namespace base

namespace base {

// Instantiate a WatchHangsInScope in a code scope to register to be
// watched for hangs of more than |timeout| by the HangWatcher.
//
// Example usage:
//
//  void FooBar(){
//    WatchHangsInScope scope(base::Seconds(5));
//    DoWork();
//  }
//
// If DoWork() takes more than 5s to run and the HangWatcher
// inspects the thread state before Foobar returns a hang will be
// reported.
//
// WatchHangsInScopes are typically meant to live on the stack. In some
// cases it's necessary to keep a WatchHangsInScope instance as a class
// member but special care is required when doing so as a WatchHangsInScope
// that stays alive longer than intended will generate non-actionable hang
// reports.
class BASE_EXPORT [[maybe_unused, nodiscard]] WatchHangsInScope {};

// Monitors registered threads for hangs by inspecting their associated
// HangWatchStates for deadline overruns. This happens at a regular interval on
// a separate thread. Only one instance of HangWatcher can exist at a time
// within a single process. This instance must outlive all monitored threads.
class BASE_EXPORT HangWatcher : public DelegateSimpleThread::Delegate {};

// Classes here are exposed in the header only for testing. They are not
// intended to be used outside of base.
namespace internal {

// Threadsafe class that manages a deadline of type TimeTicks alongside hang
// watching specific flags. The flags are stored in the higher bits of the
// underlying TimeTicks deadline. This enables setting the flags on thread T1 in
// a way that's resilient to concurrent deadline or flag changes from thread T2.
// Flags can be queried separately from the deadline and users of this class
// should not have to care about them when doing so.
class BASE_EXPORT HangWatchDeadline {};

// Contains the information necessary for hang watching a specific
// thread. Instances of this class are accessed concurrently by the associated
// thread and the HangWatcher. The HangWatcher owns instances of this
// class and outside of it they are accessed through
// GetHangWatchStateForCurrentThread().
class BASE_EXPORT HangWatchState {};

}  // namespace internal
}  // namespace base

#endif  // BASE_THREADING_HANG_WATCHER_H_