xref: /freebsd/contrib/llvm-project/lldb/include/lldb/Target/ThreadPlanSingleThreadTimeout.h (revision 700637cbb5e582861067a11aaca4d053546871d2)
1 //===-- ThreadPlanSingleThreadTimeout.h -------------------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #ifndef LLDB_TARGET_THREADPLANSINGLETHREADTIMEOUT_H
10 #define LLDB_TARGET_THREADPLANSINGLETHREADTIMEOUT_H
11 
12 #include "lldb/Target/Thread.h"
13 #include "lldb/Target/ThreadPlan.h"
14 #include "lldb/Utility/Event.h"
15 #include "lldb/Utility/LLDBLog.h"
16 #include "lldb/Utility/State.h"
17 
18 #include <chrono>
19 #include <thread>
20 
21 namespace lldb_private {
22 
23 class ThreadPlanSingleThreadTimeout;
24 //
25 // Thread plan used by single thread execution to issue timeout. This is useful
26 // to detect potential deadlock in single thread execution. The timeout measures
27 // the elapsed time from the last internal stop and gets reset by each internal
28 // stop to ensure we are accurately detecting execution not moving forward.
29 // This means this thread plan may be created/destroyed multiple times by the
30 // parent execution plan.
31 //
32 // When a timeout happens, the thread plan resolves the potential deadlock by
33 // issuing a thread specific async interrupt to enter stop state, then execution
34 // is resumed with all threads running to resolve the potential deadlock
35 //
36 class ThreadPlanSingleThreadTimeout : public ThreadPlan {
37   enum class State {
38     WaitTimeout,    // Waiting for timeout.
39     AsyncInterrupt, // Async interrupt has been issued.
40     Done,           // Finished resume all threads.
41   };
42 
43 public:
44   // TODO: allow timeout to be set on per thread plan basis.
45   struct TimeoutInfo {
46     // Whether there is a ThreadPlanSingleThreadTimeout instance alive.
47     bool m_isAlive = false;
48     ThreadPlanSingleThreadTimeout::State m_last_state = State::WaitTimeout;
49   };
50   using TimeoutInfoSP =
51       std::shared_ptr<ThreadPlanSingleThreadTimeout::TimeoutInfo>;
52 
53   ~ThreadPlanSingleThreadTimeout() override;
54 
55   // If input \param thread is running in single thread mode, push a
56   // new ThreadPlanSingleThreadTimeout based on timeout setting from fresh new
57   // state. The reference of \param info is passed in so that when
58   // ThreadPlanSingleThreadTimeout got popped its last state can be stored
59   // in it for future resume.
60   static void PushNewWithTimeout(Thread &thread, TimeoutInfoSP &info);
61 
62   // Push a new ThreadPlanSingleThreadTimeout by restoring state from
63   // input \param info and resume execution.
64   static void ResumeFromPrevState(Thread &thread, TimeoutInfoSP &info);
65 
66   void GetDescription(Stream *s, lldb::DescriptionLevel level) override;
ValidatePlan(Stream * error)67   bool ValidatePlan(Stream *error) override { return true; }
68   bool WillStop() override;
69   void DidPop() override;
70 
IsLeafPlan()71   bool IsLeafPlan() override { return true; }
72   bool DoPlanExplainsStop(Event *event_ptr) override;
73 
74   lldb::StateType GetPlanRunState() override;
75   static void TimeoutThreadFunc(ThreadPlanSingleThreadTimeout *self);
76 
77   bool MischiefManaged() override;
78 
79   bool ShouldStop(Event *event_ptr) override;
80   void SetStopOthers(bool new_value) override;
81   bool StopOthers() override;
82 
83 private:
84   ThreadPlanSingleThreadTimeout(Thread &thread, TimeoutInfoSP &info);
85 
86   bool IsTimeoutAsyncInterrupt(Event *event_ptr);
87   bool HandleEvent(Event *event_ptr);
88   void HandleTimeout();
89   uint64_t GetRemainingTimeoutMilliSeconds();
90 
91   static std::string StateToString(State state);
92 
93   ThreadPlanSingleThreadTimeout(const ThreadPlanSingleThreadTimeout &) = delete;
94   const ThreadPlanSingleThreadTimeout &
95   operator=(const ThreadPlanSingleThreadTimeout &) = delete;
96 
97   TimeoutInfoSP m_info; // Reference to controlling ThreadPlan's TimeoutInfo.
98   State m_state;
99 
100   // Lock for m_wakeup_cv and m_exit_flag between thread plan thread and timer
101   // thread
102   std::mutex m_mutex;
103   std::condition_variable m_wakeup_cv;
104   std::thread m_timer_thread;
105   std::chrono::steady_clock::time_point m_timeout_start;
106 };
107 
108 } // namespace lldb_private
109 
110 #endif // LLDB_TARGET_THREADPLANSINGLETHREADTIMEOUT_H
111