Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-10 08:42:56

0001 //===-- ThreadPlanSingleThreadTimeout.h -------------------------*- C++ -*-===//
0002 //
0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0004 // See https://llvm.org/LICENSE.txt for license information.
0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0006 //
0007 //===----------------------------------------------------------------------===//
0008 
0009 #ifndef LLDB_TARGET_THREADPLANSINGLETHREADTIMEOUT_H
0010 #define LLDB_TARGET_THREADPLANSINGLETHREADTIMEOUT_H
0011 
0012 #include "lldb/Target/Thread.h"
0013 #include "lldb/Target/ThreadPlan.h"
0014 #include "lldb/Utility/Event.h"
0015 #include "lldb/Utility/LLDBLog.h"
0016 #include "lldb/Utility/State.h"
0017 
0018 #include <chrono>
0019 #include <thread>
0020 
0021 namespace lldb_private {
0022 
0023 class ThreadPlanSingleThreadTimeout;
0024 //
0025 // Thread plan used by single thread execution to issue timeout. This is useful
0026 // to detect potential deadlock in single thread execution. The timeout measures
0027 // the elapsed time from the last internal stop and gets reset by each internal
0028 // stop to ensure we are accurately detecting execution not moving forward.
0029 // This means this thread plan may be created/destroyed multiple times by the
0030 // parent execution plan.
0031 //
0032 // When a timeout happens, the thread plan resolves the potential deadlock by
0033 // issuing a thread specific async interrupt to enter stop state, then execution
0034 // is resumed with all threads running to resolve the potential deadlock
0035 //
0036 class ThreadPlanSingleThreadTimeout : public ThreadPlan {
0037   enum class State {
0038     WaitTimeout,    // Waiting for timeout.
0039     AsyncInterrupt, // Async interrupt has been issued.
0040     Done,           // Finished resume all threads.
0041   };
0042 
0043 public:
0044   // TODO: allow timeout to be set on per thread plan basis.
0045   struct TimeoutInfo {
0046     // Whether there is a ThreadPlanSingleThreadTimeout instance alive.
0047     bool m_isAlive = false;
0048     ThreadPlanSingleThreadTimeout::State m_last_state = State::WaitTimeout;
0049   };
0050   using TimeoutInfoSP =
0051       std::shared_ptr<ThreadPlanSingleThreadTimeout::TimeoutInfo>;
0052 
0053   ~ThreadPlanSingleThreadTimeout() override;
0054 
0055   // If input \param thread is running in single thread mode, push a
0056   // new ThreadPlanSingleThreadTimeout based on timeout setting from fresh new
0057   // state. The reference of \param info is passed in so that when
0058   // ThreadPlanSingleThreadTimeout got popped its last state can be stored
0059   // in it for future resume.
0060   static void PushNewWithTimeout(Thread &thread, TimeoutInfoSP &info);
0061 
0062   // Push a new ThreadPlanSingleThreadTimeout by restoring state from
0063   // input \param info and resume execution.
0064   static void ResumeFromPrevState(Thread &thread, TimeoutInfoSP &info);
0065 
0066   void GetDescription(Stream *s, lldb::DescriptionLevel level) override;
0067   bool ValidatePlan(Stream *error) override { return true; }
0068   bool WillStop() override;
0069   void DidPop() override;
0070 
0071   bool IsLeafPlan() override { return true; }
0072   bool DoPlanExplainsStop(Event *event_ptr) override;
0073 
0074   lldb::StateType GetPlanRunState() override;
0075   static void TimeoutThreadFunc(ThreadPlanSingleThreadTimeout *self);
0076 
0077   bool MischiefManaged() override;
0078 
0079   bool ShouldStop(Event *event_ptr) override;
0080   void SetStopOthers(bool new_value) override;
0081   bool StopOthers() override;
0082 
0083 private:
0084   ThreadPlanSingleThreadTimeout(Thread &thread, TimeoutInfoSP &info);
0085 
0086   bool IsTimeoutAsyncInterrupt(Event *event_ptr);
0087   bool HandleEvent(Event *event_ptr);
0088   void HandleTimeout();
0089   uint64_t GetRemainingTimeoutMilliSeconds();
0090 
0091   static std::string StateToString(State state);
0092 
0093   ThreadPlanSingleThreadTimeout(const ThreadPlanSingleThreadTimeout &) = delete;
0094   const ThreadPlanSingleThreadTimeout &
0095   operator=(const ThreadPlanSingleThreadTimeout &) = delete;
0096 
0097   TimeoutInfoSP m_info; // Reference to controlling ThreadPlan's TimeoutInfo.
0098   State m_state;
0099 
0100   // Lock for m_wakeup_cv and m_exit_flag between thread plan thread and timer
0101   // thread
0102   std::mutex m_mutex;
0103   std::condition_variable m_wakeup_cv;
0104   std::thread m_timer_thread;
0105   std::chrono::steady_clock::time_point m_timeout_start;
0106 };
0107 
0108 } // namespace lldb_private
0109 
0110 #endif // LLDB_TARGET_THREADPLANSINGLETHREADTIMEOUT_H