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