File indexing completed on 2026-05-10 08:42:56
0001
0002
0003
0004
0005
0006
0007
0008
0009 #ifndef LLDB_TARGET_THREADPLANSTACK_H
0010 #define LLDB_TARGET_THREADPLANSTACK_H
0011
0012 #include <mutex>
0013 #include <string>
0014 #include <unordered_map>
0015 #include <vector>
0016
0017 #include "llvm/Support/RWMutex.h"
0018
0019 #include "lldb/Target/Target.h"
0020 #include "lldb/Target/Thread.h"
0021 #include "lldb/lldb-private-forward.h"
0022 #include "lldb/lldb-private.h"
0023
0024 namespace lldb_private {
0025
0026
0027
0028
0029
0030
0031
0032
0033 class ThreadPlanStack {
0034 friend class lldb_private::Thread;
0035
0036 public:
0037 ThreadPlanStack(const Thread &thread, bool make_empty = false);
0038 ~ThreadPlanStack() = default;
0039
0040 using PlanStack = std::vector<lldb::ThreadPlanSP>;
0041
0042 void DumpThreadPlans(Stream &s, lldb::DescriptionLevel desc_level,
0043 bool include_internal) const;
0044
0045 size_t CheckpointCompletedPlans();
0046
0047 void RestoreCompletedPlanCheckpoint(size_t checkpoint);
0048
0049 void DiscardCompletedPlanCheckpoint(size_t checkpoint);
0050
0051 void ThreadDestroyed(Thread *thread);
0052
0053 void PushPlan(lldb::ThreadPlanSP new_plan_sp);
0054
0055 lldb::ThreadPlanSP PopPlan();
0056
0057 lldb::ThreadPlanSP DiscardPlan();
0058
0059
0060
0061 void DiscardPlansUpToPlan(ThreadPlan *up_to_plan_ptr);
0062
0063 void DiscardAllPlans();
0064
0065 void DiscardConsultingControllingPlans();
0066
0067 lldb::ThreadPlanSP GetCurrentPlan() const;
0068
0069 lldb::ThreadPlanSP GetCompletedPlan(bool skip_private = true) const;
0070
0071 lldb::ThreadPlanSP GetPlanByIndex(uint32_t plan_idx,
0072 bool skip_private = true) const;
0073
0074 lldb::ValueObjectSP GetReturnValueObject() const;
0075
0076 lldb::ExpressionVariableSP GetExpressionVariable() const;
0077
0078 bool AnyPlans() const;
0079
0080 bool AnyCompletedPlans() const;
0081
0082 bool AnyDiscardedPlans() const;
0083
0084 bool IsPlanDone(ThreadPlan *plan) const;
0085
0086 bool WasPlanDiscarded(ThreadPlan *plan) const;
0087
0088 ThreadPlan *GetPreviousPlan(ThreadPlan *current_plan) const;
0089
0090 ThreadPlan *GetInnermostExpression() const;
0091
0092 void WillResume();
0093
0094
0095
0096
0097
0098 void ClearThreadCache();
0099
0100 private:
0101 lldb::ThreadPlanSP DiscardPlanNoLock();
0102 lldb::ThreadPlanSP GetCurrentPlanNoLock() const;
0103 void PrintOneStackNoLock(Stream &s, llvm::StringRef stack_name,
0104 const PlanStack &stack,
0105 lldb::DescriptionLevel desc_level,
0106 bool include_internal) const;
0107
0108 PlanStack m_plans;
0109 PlanStack m_completed_plans;
0110
0111
0112 PlanStack m_discarded_plans;
0113
0114
0115 size_t m_completed_plan_checkpoint = 0;
0116
0117 std::unordered_map<size_t, PlanStack> m_completed_plan_store;
0118 mutable llvm::sys::RWMutex m_stack_mutex;
0119 };
0120
0121 class ThreadPlanStackMap {
0122 public:
0123 ThreadPlanStackMap(Process &process) : m_process(process) {}
0124 ~ThreadPlanStackMap() = default;
0125
0126
0127 void Update(ThreadList ¤t_threads, bool delete_missing,
0128 bool check_for_new = true);
0129
0130 void AddThread(Thread &thread) {
0131 std::lock_guard<std::recursive_mutex> guard(m_stack_map_mutex);
0132 lldb::tid_t tid = thread.GetID();
0133 m_plans_list.emplace(tid, thread);
0134 }
0135
0136 bool RemoveTID(lldb::tid_t tid) {
0137 std::lock_guard<std::recursive_mutex> guard(m_stack_map_mutex);
0138 auto result = m_plans_list.find(tid);
0139 if (result == m_plans_list.end())
0140 return false;
0141 result->second.ThreadDestroyed(nullptr);
0142 m_plans_list.erase(result);
0143 return true;
0144 }
0145
0146 ThreadPlanStack *Find(lldb::tid_t tid) {
0147 std::lock_guard<std::recursive_mutex> guard(m_stack_map_mutex);
0148 auto result = m_plans_list.find(tid);
0149 if (result == m_plans_list.end())
0150 return nullptr;
0151 else
0152 return &result->second;
0153 }
0154
0155
0156
0157
0158
0159 void ClearThreadCache() {
0160 for (auto &plan_list : m_plans_list)
0161 plan_list.second.ClearThreadCache();
0162 }
0163
0164 void Clear() {
0165 std::lock_guard<std::recursive_mutex> guard(m_stack_map_mutex);
0166 for (auto &plan : m_plans_list)
0167 plan.second.ThreadDestroyed(nullptr);
0168 m_plans_list.clear();
0169 }
0170
0171
0172 void DumpPlans(Stream &strm, lldb::DescriptionLevel desc_level, bool internal,
0173 bool ignore_boring, bool skip_unreported);
0174
0175
0176 bool DumpPlansForTID(Stream &strm, lldb::tid_t tid,
0177 lldb::DescriptionLevel desc_level, bool internal,
0178 bool ignore_boring, bool skip_unreported);
0179
0180 bool PrunePlansForTID(lldb::tid_t tid);
0181
0182 private:
0183 Process &m_process;
0184 mutable std::recursive_mutex m_stack_map_mutex;
0185 using PlansList = std::unordered_map<lldb::tid_t, ThreadPlanStack>;
0186 PlansList m_plans_list;
0187
0188 };
0189
0190 }
0191
0192 #endif