tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

hang_watcher.h (27774B)


      1 // Copyright 2020 The Chromium Authors
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #ifndef BASE_THREADING_HANG_WATCHER_H_
      6 #define BASE_THREADING_HANG_WATCHER_H_
      7 
      8 #include <atomic>
      9 #include <cstdint>
     10 #include <memory>
     11 #include <type_traits>
     12 #include <vector>
     13 
     14 #include "base/atomicops.h"
     15 #include "base/auto_reset.h"
     16 #include "base/base_export.h"
     17 #include "base/bits.h"
     18 #include "base/compiler_specific.h"
     19 #include "base/dcheck_is_on.h"
     20 #include "base/debug/crash_logging.h"
     21 #include "base/functional/callback.h"
     22 #include "base/functional/callback_forward.h"
     23 #include "base/functional/callback_helpers.h"
     24 #include "base/gtest_prod_util.h"
     25 #include "base/memory/memory_pressure_listener.h"
     26 #include "base/memory/raw_ptr.h"
     27 #include "base/synchronization/lock.h"
     28 #include "base/synchronization/waitable_event.h"
     29 #include "base/template_util.h"
     30 #include "base/thread_annotations.h"
     31 #include "base/threading/platform_thread.h"
     32 #include "base/threading/simple_thread.h"
     33 #include "base/threading/thread_checker.h"
     34 #include "base/time/tick_clock.h"
     35 #include "base/time/time.h"
     36 #include "build/build_config.h"
     37 
     38 namespace base {
     39 class WatchHangsInScope;
     40 namespace internal {
     41 class HangWatchState;
     42 }  // namespace internal
     43 }  // namespace base
     44 
     45 namespace base {
     46 
     47 // Instantiate a WatchHangsInScope in a code scope to register to be
     48 // watched for hangs of more than |timeout| by the HangWatcher.
     49 //
     50 // Example usage:
     51 //
     52 //  void FooBar(){
     53 //    WatchHangsInScope scope(base::Seconds(5));
     54 //    DoWork();
     55 //  }
     56 //
     57 // If DoWork() takes more than 5s to run and the HangWatcher
     58 // inspects the thread state before Foobar returns a hang will be
     59 // reported.
     60 //
     61 // WatchHangsInScopes are typically meant to live on the stack. In some
     62 // cases it's necessary to keep a WatchHangsInScope instance as a class
     63 // member but special care is required when doing so as a WatchHangsInScope
     64 // that stays alive longer than intended will generate non-actionable hang
     65 // reports.
     66 class BASE_EXPORT [[maybe_unused, nodiscard]] WatchHangsInScope {
     67 public:
     68  // A good default value needs to be large enough to represent a significant
     69  // hang and avoid noise while being small enough to not exclude too many
     70  // hangs. The nature of the work that gets executed on the thread is also
     71  // important. We can be much stricter when monitoring a UI thread compared to
     72  // a ThreadPool thread for example.
     73  static constexpr base::TimeDelta kDefaultHangWatchTime = base::Seconds(10);
     74 
     75  // Constructing/destructing thread must be the same thread.
     76  explicit WatchHangsInScope(TimeDelta timeout = kDefaultHangWatchTime);
     77  ~WatchHangsInScope();
     78 
     79  WatchHangsInScope(const WatchHangsInScope&) = delete;
     80  WatchHangsInScope& operator=(const WatchHangsInScope&) = delete;
     81 
     82 private:
     83  // Will be true if the object actually set a deadline and false if not.
     84  bool took_effect_ = true;
     85 
     86  // This object should always be constructed and destructed on the same thread.
     87  THREAD_CHECKER(thread_checker_);
     88 
     89  // The deadline set by the previous WatchHangsInScope created on this
     90  // thread. Stored so it can be restored when this WatchHangsInScope is
     91  // destroyed.
     92  TimeTicks previous_deadline_;
     93 
     94  // Indicates whether the kIgnoreCurrentWatchHangsInScope flag must be set upon
     95  // exiting this WatchHangsInScope if a call to InvalidateActiveExpectations()
     96  // previously suspended hang watching.
     97  bool set_hangs_ignored_on_exit_ = false;
     98 
     99 #if DCHECK_IS_ON()
    100  // The previous WatchHangsInScope created on this thread.
    101  raw_ptr<WatchHangsInScope> previous_watch_hangs_in_scope_;
    102 #endif
    103 };
    104 
    105 // Monitors registered threads for hangs by inspecting their associated
    106 // HangWatchStates for deadline overruns. This happens at a regular interval on
    107 // a separate thread. Only one instance of HangWatcher can exist at a time
    108 // within a single process. This instance must outlive all monitored threads.
    109 class BASE_EXPORT HangWatcher : public DelegateSimpleThread::Delegate {
    110 public:
    111  // Describes the type of a process for logging purposes.
    112  enum class ProcessType {
    113    kUnknownProcess = 0,
    114    kBrowserProcess = 1,
    115    kGPUProcess = 2,
    116    kRendererProcess = 3,
    117    kUtilityProcess = 4,
    118    kMax = kUtilityProcess
    119  };
    120 
    121  // Describes the type of a thread for logging purposes.
    122  enum class ThreadType {
    123    kIOThread = 0,
    124    kMainThread = 1,
    125    kThreadPoolThread = 2,
    126    kMax = kThreadPoolThread
    127  };
    128 
    129  // Notes on lifetime:
    130  //   1) The first invocation of the constructor will set the global instance
    131  //      accessible through GetInstance().
    132  //   2) In production HangWatcher is always purposefuly leaked.
    133  //   3) If not leaked HangWatcher is always constructed and destructed from
    134  //      the same thread.
    135  //   4) There can never be more than one instance of HangWatcher at a time.
    136  //      The class is not base::Singleton derived because it needs to destroyed
    137  //      in tests.
    138  HangWatcher();
    139 
    140  // Clears the global instance for the class.
    141  ~HangWatcher() override;
    142 
    143  HangWatcher(const HangWatcher&) = delete;
    144  HangWatcher& operator=(const HangWatcher&) = delete;
    145 
    146  static void CreateHangWatcherInstance();
    147 
    148  // Returns a non-owning pointer to the global HangWatcher instance.
    149  static HangWatcher* GetInstance();
    150 
    151  // Initializes HangWatcher. Must be called once on the main thread during
    152  // startup while single-threaded.
    153  static void InitializeOnMainThread(ProcessType process_type,
    154                                     bool is_zygote_child);
    155 
    156  // Returns the values that were set through InitializeOnMainThread() to their
    157  // default value. Used for testing since in prod initialization should happen
    158  // only once.
    159  static void UnitializeOnMainThreadForTesting();
    160 
    161  // Thread safe functions to verify if hang watching is activated. If called
    162  // before InitializeOnMainThread returns the default value which is false.
    163  static bool IsEnabled();
    164  static bool IsThreadPoolHangWatchingEnabled();
    165  static bool IsIOThreadHangWatchingEnabled();
    166 
    167  // Returns true if crash dump reporting is configured for any thread type.
    168  static bool IsCrashReportingEnabled();
    169 
    170  // Use to avoid capturing hangs for operations known to take unbounded time
    171  // like waiting for user input. WatchHangsInScope objects created after this
    172  // call will take effect. To resume watching for hangs create a new
    173  // WatchHangsInScope after the unbounded operation finishes.
    174  //
    175  // Example usage:
    176  //  {
    177  //    WatchHangsInScope scope_1;
    178  //    {
    179  //      WatchHangsInScope scope_2;
    180  //      InvalidateActiveExpectations();
    181  //      WaitForUserInput();
    182  //    }
    183  //
    184  //    WatchHangsInScope scope_4;
    185  //  }
    186  //
    187  // WatchHangsInScope scope_5;
    188  //
    189  // In this example hang watching is disabled for WatchHangsInScopes 1 and 2
    190  // since they were both active at the time of the invalidation.
    191  // WatchHangsInScopes 4 and 5 are unaffected since they were created after the
    192  // end of the WatchHangsInScope that was current at the time of invalidation.
    193  //
    194  static void InvalidateActiveExpectations();
    195 
    196  // Sets up the calling thread to be monitored for threads. Returns a
    197  // ScopedClosureRunner that unregisters the thread. This closure has to be
    198  // called from the registered thread before it's joined. Returns a null
    199  // closure in the case where there is no HangWatcher instance to register the
    200  // thread with.
    201  [[nodiscard]] static ScopedClosureRunner RegisterThread(
    202      ThreadType thread_type);
    203 
    204  // Choose a closure to be run at the end of each call to Monitor(). Use only
    205  // for testing. Reentering the HangWatcher in the closure must be done with
    206  // care. It should only be done through certain testing functions because
    207  // deadlocks are possible.
    208  void SetAfterMonitorClosureForTesting(base::RepeatingClosure closure);
    209 
    210  // Choose a closure to be run instead of recording the hang. Used to test
    211  // that certain conditions hold true at the time of recording. Use only
    212  // for testing. Reentering the HangWatcher in the closure must be done with
    213  // care. It should only be done through certain testing functions because
    214  // deadlocks are possible.
    215  void SetOnHangClosureForTesting(base::RepeatingClosure closure);
    216 
    217  // Set a monitoring period other than the default. Use only for
    218  // testing.
    219  void SetMonitoringPeriodForTesting(base::TimeDelta period);
    220 
    221  // Choose a callback to invoke right after waiting to monitor in Wait(). Use
    222  // only for testing.
    223  void SetAfterWaitCallbackForTesting(
    224      RepeatingCallback<void(TimeTicks)> callback);
    225 
    226  // Force the monitoring loop to resume and evaluate whether to continue.
    227  // This can trigger a call to Monitor() or not depending on why the
    228  // HangWatcher thread is sleeping. Use only for testing.
    229  void SignalMonitorEventForTesting();
    230 
    231  // Call to make sure no more monitoring takes place. The
    232  // function is thread-safe and can be called at anytime but won't stop
    233  // monitoring that is currently taking place. Use only for testing.
    234  static void StopMonitoringForTesting();
    235 
    236  // Replace the clock used when calculating time spent
    237  // sleeping. Use only for testing.
    238  void SetTickClockForTesting(const base::TickClock* tick_clock);
    239 
    240  // Use to block until the hang is recorded. Allows the caller to halt
    241  // execution so it does not overshoot the hang watch target and result in a
    242  // non-actionable stack trace in the crash recorded.
    243  void BlockIfCaptureInProgress();
    244 
    245  // Begin executing the monitoring loop on the HangWatcher thread.
    246  void Start();
    247 
    248  // Returns true if Start() has been called and Stop() has not been called
    249  // since.
    250  bool IsStarted() const { return thread_started_; }
    251 
    252  // Returns the value of the crash key with the time since last system power
    253  // resume.
    254  std::string GetTimeSinceLastSystemPowerResumeCrashKeyValue() const;
    255 
    256 private:
    257  // See comment of ::RegisterThread() for details.
    258  [[nodiscard]] ScopedClosureRunner RegisterThreadInternal(
    259      ThreadType thread_type) LOCKS_EXCLUDED(watch_state_lock_);
    260 
    261  // Use to assert that functions are called on the monitoring thread.
    262  THREAD_CHECKER(hang_watcher_thread_checker_);
    263 
    264  // Use to assert that functions are called on the constructing thread.
    265  THREAD_CHECKER(constructing_thread_checker_);
    266 
    267  // Invoked on memory pressure signal.
    268  void OnMemoryPressure(
    269      base::MemoryPressureListener::MemoryPressureLevel memory_pressure_level);
    270 
    271 #if !BUILDFLAG(IS_NACL)
    272  // Returns a ScopedCrashKeyString that sets the crash key with the time since
    273  // last critical memory pressure signal.
    274  [[nodiscard]] debug::ScopedCrashKeyString
    275  GetTimeSinceLastCriticalMemoryPressureCrashKey();
    276 #endif
    277 
    278  // Invoke base::debug::DumpWithoutCrashing() insuring that the stack frame
    279  // right under it in the trace belongs to HangWatcher for easier attribution.
    280  NOINLINE static void RecordHang();
    281 
    282  using HangWatchStates =
    283      std::vector<std::unique_ptr<internal::HangWatchState>>;
    284 
    285  // Used to save a snapshots of the state of hang watching during capture.
    286  // Only the state of hung threads is retained.
    287  class BASE_EXPORT WatchStateSnapShot {
    288   public:
    289    struct WatchStateCopy {
    290      base::TimeTicks deadline;
    291      base::PlatformThreadId thread_id;
    292    };
    293 
    294    WatchStateSnapShot();
    295    WatchStateSnapShot(const WatchStateSnapShot& other);
    296    ~WatchStateSnapShot();
    297 
    298    // Initialize the snapshot from provided data. |snapshot_time| can be
    299    // different than now() to be coherent with other operations recently done
    300    // on |watch_states|. |hung_watch_state_copies_| can be empty after
    301    // initialization for a number of reasons:
    302    // 1. If any deadline in |watch_states| is before
    303    // |deadline_ignore_threshold|.
    304    // 2. If some of the hung threads could not be marked as blocking on
    305    // capture.
    306    // 3. If none of the hung threads are of a type configured to trigger a
    307    // crash dump.
    308    //
    309    // This function cannot be called more than once without an associated call
    310    // to Clear().
    311    void Init(const HangWatchStates& watch_states,
    312              base::TimeTicks deadline_ignore_threshold);
    313 
    314    // Reset the snapshot object to be reused. Can only be called after Init().
    315    void Clear();
    316 
    317    // Returns a string that contains the ids of the hung threads separated by a
    318    // '|'. The size of the string is capped at debug::CrashKeySize::Size256. If
    319    // no threads are hung returns an empty string. Can only be invoked if
    320    // IsActionable(). Can only be called after Init().
    321    std::string PrepareHungThreadListCrashKey() const;
    322 
    323    // Return the highest deadline included in this snapshot. Can only be called
    324    // if IsActionable(). Can only be called after Init().
    325    base::TimeTicks GetHighestDeadline() const;
    326 
    327    // Returns true if the snapshot can be used to record an actionable hang
    328    // report and false if not. Can only be called after Init().
    329    bool IsActionable() const;
    330 
    331   private:
    332    bool initialized_ = false;
    333    std::vector<WatchStateCopy> hung_watch_state_copies_;
    334  };
    335 
    336  // Return a watch state snapshot taken Now() to be inspected in tests.
    337  // NO_THREAD_SAFETY_ANALYSIS is needed because the analyzer can't figure out
    338  // that calls to this function done from |on_hang_closure_| are properly
    339  // locked.
    340  WatchStateSnapShot GrabWatchStateSnapshotForTesting() const
    341      NO_THREAD_SAFETY_ANALYSIS;
    342 
    343  // Inspects the state of all registered threads to check if they are hung and
    344  // invokes the appropriate closure if so.
    345  void Monitor() LOCKS_EXCLUDED(watch_state_lock_);
    346 
    347  // Record the hang crash dump and perform the necessary housekeeping before
    348  // and after.
    349  void DoDumpWithoutCrashing(const WatchStateSnapShot& watch_state_snapshot)
    350      EXCLUSIVE_LOCKS_REQUIRED(watch_state_lock_) LOCKS_EXCLUDED(capture_lock_);
    351 
    352  // Stop all monitoring and join the HangWatcher thread.
    353  void Stop();
    354 
    355  // Wait until it's time to monitor.
    356  void Wait();
    357 
    358  // Run the loop that periodically monitors the registered thread at a
    359  // set time interval.
    360  void Run() override;
    361 
    362  base::TimeDelta monitor_period_;
    363 
    364  // Use to make the HangWatcher thread wake or sleep to schedule the
    365  // appropriate monitoring frequency.
    366  WaitableEvent should_monitor_;
    367 
    368  bool IsWatchListEmpty() LOCKS_EXCLUDED(watch_state_lock_);
    369 
    370  // Stops hang watching on the calling thread by removing the entry from the
    371  // watch list.
    372  void UnregisterThread() LOCKS_EXCLUDED(watch_state_lock_);
    373 
    374  Lock watch_state_lock_;
    375 
    376  std::vector<std::unique_ptr<internal::HangWatchState>> watch_states_
    377      GUARDED_BY(watch_state_lock_);
    378 
    379  // Snapshot to be reused across hang captures. The point of keeping it
    380  // around is reducing allocations during capture.
    381  WatchStateSnapShot watch_state_snapshot_
    382      GUARDED_BY_CONTEXT(hang_watcher_thread_checker_);
    383 
    384  base::DelegateSimpleThread thread_;
    385  bool thread_started_ = false;
    386 
    387  RepeatingClosure after_monitor_closure_for_testing_;
    388  RepeatingClosure on_hang_closure_for_testing_;
    389  RepeatingCallback<void(TimeTicks)> after_wait_callback_;
    390 
    391  base::Lock capture_lock_ ACQUIRED_AFTER(watch_state_lock_);
    392  std::atomic<bool> capture_in_progress_{false};
    393 
    394  raw_ptr<const base::TickClock> tick_clock_;
    395 
    396  // Registration to receive memory pressure signals.
    397  base::MemoryPressureListener memory_pressure_listener_;
    398 
    399  // The last time at which a critical memory pressure signal was received, or
    400  // null if no signal was ever received. Atomic because it's set and read from
    401  // different threads.
    402  std::atomic<base::TimeTicks> last_critical_memory_pressure_{
    403      base::TimeTicks()};
    404 
    405  // The time after which all deadlines in |watch_states_| need to be for a hang
    406  // to be reported.
    407  base::TimeTicks deadline_ignore_threshold_;
    408 
    409  FRIEND_TEST_ALL_PREFIXES(HangWatcherTest, NestedScopes);
    410  FRIEND_TEST_ALL_PREFIXES(HangWatcherSnapshotTest, HungThreadIDs);
    411  FRIEND_TEST_ALL_PREFIXES(HangWatcherSnapshotTest, NonActionableReport);
    412 };
    413 
    414 // Classes here are exposed in the header only for testing. They are not
    415 // intended to be used outside of base.
    416 namespace internal {
    417 
    418 // Threadsafe class that manages a deadline of type TimeTicks alongside hang
    419 // watching specific flags. The flags are stored in the higher bits of the
    420 // underlying TimeTicks deadline. This enables setting the flags on thread T1 in
    421 // a way that's resilient to concurrent deadline or flag changes from thread T2.
    422 // Flags can be queried separately from the deadline and users of this class
    423 // should not have to care about them when doing so.
    424 class BASE_EXPORT HangWatchDeadline {
    425 public:
    426  // Masks to set flags by flipping a single bit in the TimeTicks value. There
    427  // are two types of flags. Persistent flags remain set through a deadline
    428  // change and non-persistent flags are cleared when the deadline changes.
    429  enum class Flag : uint64_t {
    430    // Minimum value for validation purposes. Not currently used.
    431    kMinValue = bits::LeftmostBit<uint64_t>() >> 7,
    432    // Persistent because if hang detection is disabled on a thread it should
    433    // be re-enabled manually.
    434    kIgnoreCurrentWatchHangsInScope = bits::LeftmostBit<uint64_t>() >> 1,
    435    // Non-persistent because a new value means a new WatchHangsInScope started
    436    // after the beginning of capture. It can't be implicated in the hang so we
    437    // don't want it to block.
    438    kShouldBlockOnHang = bits::LeftmostBit<uint64_t>() >> 0,
    439    kMaxValue = kShouldBlockOnHang
    440  };
    441 
    442  HangWatchDeadline();
    443  ~HangWatchDeadline();
    444 
    445  // HangWatchDeadline should never be copied. To keep a copy of the deadline or
    446  // flags use the appropriate accessors.
    447  HangWatchDeadline(const HangWatchDeadline&) = delete;
    448  HangWatchDeadline& operator=(const HangWatchDeadline&) = delete;
    449 
    450  // Returns the underlying TimeTicks deadline. WARNING: The deadline and flags
    451  // can change concurrently. To inspect both, use GetFlagsAndDeadline() to get
    452  // a coherent race-free view of the state.
    453  TimeTicks GetDeadline() const;
    454 
    455  // Returns a mask containing the flags and the deadline as a pair. Use to
    456  // inspect the flags and deadline and then optionally call
    457  // SetShouldBlockOnHang() .
    458  std::pair<uint64_t, TimeTicks> GetFlagsAndDeadline() const;
    459 
    460  // Returns true if the flag is set and false if not. WARNING: The deadline and
    461  // flags can change concurrently. To inspect both, use GetFlagsAndDeadline()
    462  // to get a coherent race-free view of the state.
    463  bool IsFlagSet(Flag flag) const;
    464 
    465  // Returns true if a flag is set in |flags| and false if not. Use to inspect
    466  // the flags mask returned by GetFlagsAndDeadline(). WARNING: The deadline and
    467  // flags can change concurrently. If you need to inspect both you need to use
    468  // GetFlagsAndDeadline() to get a coherent race-free view of the state.
    469  static bool IsFlagSet(Flag flag, uint64_t flags);
    470 
    471  // Replace the deadline value. |new_value| needs to be within [0,
    472  // Max()]. This function can never fail.
    473  void SetDeadline(TimeTicks new_value);
    474 
    475  // Sets the kShouldBlockOnHang flag and returns true if current flags and
    476  // deadline are still equal to |old_flags| and  |old_deadline|. Otherwise does
    477  // not set the flag and returns false.
    478  bool SetShouldBlockOnHang(uint64_t old_flags, TimeTicks old_deadline);
    479 
    480  // Sets the kIgnoreCurrentWatchHangsInScope flag.
    481  void SetIgnoreCurrentWatchHangsInScope();
    482 
    483  // Clears the kIgnoreCurrentWatchHangsInScope flag.
    484  void UnsetIgnoreCurrentWatchHangsInScope();
    485 
    486  // Use to simulate the value of |bits_| changing between the calling a
    487  // Set* function and the moment of atomically switching the values. The
    488  // callback should return a value containing the desired flags and deadline
    489  // bits. The flags that are already set will be preserved upon applying. Use
    490  // only for testing.
    491  void SetSwitchBitsClosureForTesting(
    492      RepeatingCallback<uint64_t(void)> closure);
    493 
    494  // Remove the deadline modification callback for when testing is done. Use
    495  // only for testing.
    496  void ResetSwitchBitsClosureForTesting();
    497 
    498 private:
    499  using TimeTicksInternalRepresentation =
    500      std::invoke_result<decltype(&TimeTicks::ToInternalValue),
    501                         TimeTicks>::type;
    502  static_assert(std::is_same_v<TimeTicksInternalRepresentation, int64_t>,
    503                "Bit manipulations made by HangWatchDeadline need to be"
    504                "adapted if internal representation of TimeTicks changes.");
    505 
    506  // Replace the bits with the ones provided through the callback. Preserves the
    507  // flags that were already set. Returns the switched in bits. Only call if
    508  // |switch_bits_callback_for_testing_| is installed.
    509  uint64_t SwitchBitsForTesting();
    510 
    511  // Atomically sets persitent flag |flag|. Cannot fail.
    512  void SetPersistentFlag(Flag flag);
    513 
    514  // Atomically clears persitent flag |flag|. Cannot fail.
    515  void ClearPersistentFlag(Flag flag);
    516 
    517  // Converts bits to TimeTicks with some sanity checks. Use to return the
    518  // deadline outside of this class.
    519  static TimeTicks DeadlineFromBits(uint64_t bits);
    520 
    521  // Returns the largest representable deadline.
    522  static TimeTicks Max();
    523 
    524  // Extract the flag bits from |bits|.
    525  static uint64_t ExtractFlags(uint64_t bits);
    526 
    527  // Extract the deadline bits from |bits|.
    528  static uint64_t ExtractDeadline(uint64_t bits);
    529 
    530  // BitsType is uint64_t. This type is chosen for having
    531  // std::atomic<BitsType>{}.is_lock_free() true on many platforms and having no
    532  // undefined behaviors with regards to bit shift operations. Throughout this
    533  // class this is the only type that is used to store, retrieve and manipulate
    534  // the bits. When returning a TimeTicks value outside this class it's
    535  // necessary to run the proper checks to insure correctness of the conversion
    536  // that has to go through int_64t. (See DeadlineFromBits()).
    537  using BitsType = uint64_t;
    538  static_assert(std::is_same_v<std::underlying_type<Flag>::type, BitsType>,
    539                "Flag should have the same underlying type as bits_ to "
    540                "simplify thinking about bit operations");
    541 
    542  // Holds the bits of both the flags and the TimeTicks deadline.
    543  // TimeTicks values represent a count of microseconds since boot which may or
    544  // may not include suspend time depending on the platform. Using the seven
    545  // highest order bits and the sign bit to store flags still enables the
    546  // storing of TimeTicks values that can represent up to ~1142 years of uptime
    547  // in the remaining bits. Should never be directly accessed from outside the
    548  // class. Starts out at Max() to provide a base-line deadline that will not be
    549  // reached during normal execution.
    550  //
    551  // Binary format: 0xFFDDDDDDDDDDDDDDDD
    552  // F = Flags
    553  // D = Deadline
    554  std::atomic<BitsType> bits_{static_cast<uint64_t>(Max().ToInternalValue())};
    555 
    556  RepeatingCallback<uint64_t(void)> switch_bits_callback_for_testing_;
    557 
    558  THREAD_CHECKER(thread_checker_);
    559 
    560  FRIEND_TEST_ALL_PREFIXES(HangWatchDeadlineTest, BitsPreservedThroughExtract);
    561 };
    562 
    563 // Contains the information necessary for hang watching a specific
    564 // thread. Instances of this class are accessed concurrently by the associated
    565 // thread and the HangWatcher. The HangWatcher owns instances of this
    566 // class and outside of it they are accessed through
    567 // GetHangWatchStateForCurrentThread().
    568 class BASE_EXPORT HangWatchState {
    569 public:
    570  // |thread_type| is the type of thread the watch state will
    571  // be associated with. It's the responsibility of the creating
    572  // code to choose the correct type.
    573  explicit HangWatchState(HangWatcher::ThreadType thread_type);
    574  ~HangWatchState();
    575 
    576  HangWatchState(const HangWatchState&) = delete;
    577  HangWatchState& operator=(const HangWatchState&) = delete;
    578 
    579  // Allocates a new state object bound to the calling thread and returns an
    580  // owning pointer to it.
    581  static std::unique_ptr<HangWatchState> CreateHangWatchStateForCurrentThread(
    582      HangWatcher::ThreadType thread_type);
    583 
    584  // Retrieves the hang watch state associated with the calling thread.
    585  // Returns nullptr if no HangWatchState exists for the current thread (see
    586  // CreateHangWatchStateForCurrentThread()).
    587  static HangWatchState* GetHangWatchStateForCurrentThread();
    588 
    589  // Returns the current deadline. Use this function if you need to
    590  // store the value. To test if the deadline has expired use IsOverDeadline().
    591  // WARNING: The deadline and flags can change concurrently. If you need to
    592  // inspect both you need to use GetFlagsAndDeadline() to get a coherent
    593  // race-free view of the state.
    594  TimeTicks GetDeadline() const;
    595 
    596  // Returns a mask containing the hang watching flags and the value as a pair.
    597  // Use to inspect the flags and deadline and optionally call
    598  // SetShouldBlockOnHang(flags, deadline).
    599  std::pair<uint64_t, TimeTicks> GetFlagsAndDeadline() const;
    600 
    601  // Sets the deadline to a new value.
    602  void SetDeadline(TimeTicks deadline);
    603 
    604  // Mark this thread as ignored for hang watching. This means existing
    605  // WatchHangsInScope will not trigger hangs.
    606  void SetIgnoreCurrentWatchHangsInScope();
    607 
    608  // Reactivate hang watching on this thread. Should be called when all
    609  // WatchHangsInScope instances that were ignored have completed.
    610  void UnsetIgnoreCurrentWatchHangsInScope();
    611 
    612  // Mark the current state as having to block in its destruction until hang
    613  // capture completes.
    614  bool SetShouldBlockOnHang(uint64_t old_flags, TimeTicks old_deadline);
    615 
    616  // Returns true if |flag| is set and false if not. WARNING: The deadline and
    617  // flags can change concurrently. If you need to inspect both you need to use
    618  // GetFlagsAndDeadline() to get a coherent race-free view of the state.
    619  bool IsFlagSet(HangWatchDeadline::Flag flag);
    620 
    621  // Tests whether the associated thread's execution has gone over the deadline.
    622  bool IsOverDeadline() const;
    623 
    624 #if DCHECK_IS_ON()
    625  // Saves the supplied WatchHangsInScope as the currently active
    626  // WatchHangsInScope.
    627  void SetCurrentWatchHangsInScope(WatchHangsInScope* scope);
    628 
    629  // Retrieve the currently active scope.
    630  WatchHangsInScope* GetCurrentWatchHangsInScope();
    631 #endif
    632 
    633  PlatformThreadId GetThreadID() const;
    634 
    635  // Retrieve the current hang watch deadline directly. For testing only.
    636  HangWatchDeadline* GetHangWatchDeadlineForTesting();
    637 
    638  // Returns the current nesting level.
    639  int nesting_level() { return nesting_level_; }
    640 
    641  // Increase the nesting level by 1;
    642  void IncrementNestingLevel();
    643 
    644  // Reduce the nesting level by 1;
    645  void DecrementNestingLevel();
    646 
    647  // Returns the type of the thread under watch.
    648  HangWatcher::ThreadType thread_type() const { return thread_type_; }
    649 
    650 private:
    651  // The thread that creates the instance should be the class that updates
    652  // the deadline.
    653  THREAD_CHECKER(thread_checker_);
    654 
    655  const AutoReset<HangWatchState*> resetter_;
    656 
    657  // If the deadline fails to be updated before TimeTicks::Now() ever
    658  // reaches the value contained in it this constistutes a hang.
    659  HangWatchDeadline deadline_;
    660 
    661  // A unique ID of the thread under watch. Used for logging in crash reports
    662  // only.
    663  PlatformThreadId thread_id_;
    664 
    665  // Number of active HangWatchScopeEnables on this thread.
    666  int nesting_level_ = 0;
    667 
    668  // The type of the thread under watch.
    669  const HangWatcher::ThreadType thread_type_;
    670 
    671 #if DCHECK_IS_ON()
    672  // Used to keep track of the current WatchHangsInScope and detect improper
    673  // usage. Scopes should always be destructed in reverse order from the one
    674  // they were constructed in. Example of improper use:
    675  //
    676  // {
    677  //   std::unique_ptr<Scope> scope = std::make_unique<Scope>(...);
    678  //   Scope other_scope;
    679  //   |scope| gets deallocated first, violating reverse destruction order.
    680  //   scope.reset();
    681  // }
    682  raw_ptr<WatchHangsInScope> current_watch_hangs_in_scope_{nullptr};
    683 #endif
    684 };
    685 
    686 }  // namespace internal
    687 }  // namespace base
    688 
    689 #endif  // BASE_THREADING_HANG_WATCHER_H_