• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
IsStarted()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.
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.
thread_type()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_
690