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