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