LLDB mainline
ThreadPlanStack.h
Go to the documentation of this file.
1//===-- ThreadPlanStack.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_THREADPLANSTACK_H
10#define LLDB_TARGET_THREADPLANSTACK_H
11
12#include <mutex>
13#include <string>
14#include <unordered_map>
15#include <vector>
16
17#include "lldb/Target/Target.h"
18#include "lldb/Target/Thread.h"
20#include "lldb/lldb-private.h"
21
22namespace lldb_private {
23
24// The ThreadPlans have a thread for use when they are asked all the ThreadPlan
25// state machine questions, but they should never cache any pointers from their
26// owning lldb_private::Thread. That's because we want to be able to detach
27// them from an owning thread, then reattach them by TID.
28// The ThreadPlanStack holds the ThreadPlans for a given TID. All its methods
29// are private, and it should only be accessed through the owning thread. When
30// it is detached from a thread, all you can do is reattach it or delete it.
33
34public:
35 ThreadPlanStack(const Thread &thread, bool make_empty = false);
36 ~ThreadPlanStack() = default;
37
38 using PlanStack = std::vector<lldb::ThreadPlanSP>;
39
41 bool include_internal) const;
42
44
45 void RestoreCompletedPlanCheckpoint(size_t checkpoint);
46
47 void DiscardCompletedPlanCheckpoint(size_t checkpoint);
48
49 void ThreadDestroyed(Thread *thread);
50
51 void PushPlan(lldb::ThreadPlanSP new_plan_sp);
52
54
56
57 // If the input plan is nullptr, discard all plans. Otherwise make sure this
58 // plan is in the stack, and if so discard up to and including it.
59 void DiscardPlansUpToPlan(ThreadPlan *up_to_plan_ptr);
60
61 void DiscardAllPlans();
62
64
66
67 lldb::ThreadPlanSP GetCompletedPlan(bool skip_private = true) const;
68
69 lldb::ThreadPlanSP GetPlanByIndex(uint32_t plan_idx,
70 bool skip_private = true) const;
71
73
75
76 bool AnyPlans() const;
77
78 bool AnyCompletedPlans() const;
79
80 bool AnyDiscardedPlans() const;
81
82 bool IsPlanDone(ThreadPlan *plan) const;
83
84 bool WasPlanDiscarded(ThreadPlan *plan) const;
85
86 ThreadPlan *GetPreviousPlan(ThreadPlan *current_plan) const;
87
89
90 void WillResume();
91
92 /// Clear the Thread* cache that each ThreadPlan contains.
93 ///
94 /// This is useful in situations like when a new Thread list is being
95 /// generated.
96 void ClearThreadCache();
97
98private:
99 void PrintOneStack(Stream &s, llvm::StringRef stack_name,
100 const PlanStack &stack, lldb::DescriptionLevel desc_level,
101 bool include_internal) const;
102
103 PlanStack m_plans; ///< The stack of plans this thread is executing.
104 PlanStack m_completed_plans; ///< Plans that have been completed by this
105 /// stop. They get deleted when the thread
106 /// resumes.
107 PlanStack m_discarded_plans; ///< Plans that have been discarded by this
108 /// stop. They get deleted when the thread
109 /// resumes.
110 size_t m_completed_plan_checkpoint = 0; // Monotonically increasing token for
111 // completed plan checkpoints.
112 std::unordered_map<size_t, PlanStack> m_completed_plan_store;
113 mutable std::recursive_mutex m_stack_mutex;
114};
115
117public:
118 ThreadPlanStackMap(Process &process) : m_process(process) {}
120
121 // Prune the map using the current_threads list.
122 void Update(ThreadList &current_threads, bool delete_missing,
123 bool check_for_new = true);
124
125 void AddThread(Thread &thread) {
126 std::lock_guard<std::recursive_mutex> guard(m_stack_map_mutex);
127 lldb::tid_t tid = thread.GetID();
128 m_plans_list.emplace(tid, thread);
129 }
130
132 std::lock_guard<std::recursive_mutex> guard(m_stack_map_mutex);
133 auto result = m_plans_list.find(tid);
134 if (result == m_plans_list.end())
135 return false;
136 result->second.ThreadDestroyed(nullptr);
137 m_plans_list.erase(result);
138 return true;
139 }
140
142 std::lock_guard<std::recursive_mutex> guard(m_stack_map_mutex);
143 auto result = m_plans_list.find(tid);
144 if (result == m_plans_list.end())
145 return nullptr;
146 else
147 return &result->second;
148 }
149
150 /// Clear the Thread* cache that each ThreadPlan contains.
151 ///
152 /// This is useful in situations like when a new Thread list is being
153 /// generated.
155 for (auto &plan_list : m_plans_list)
156 plan_list.second.ClearThreadCache();
157 }
158
159 void Clear() {
160 std::lock_guard<std::recursive_mutex> guard(m_stack_map_mutex);
161 for (auto &plan : m_plans_list)
162 plan.second.ThreadDestroyed(nullptr);
163 m_plans_list.clear();
164 }
165
166 // Implements Process::DumpThreadPlans
167 void DumpPlans(Stream &strm, lldb::DescriptionLevel desc_level, bool internal,
168 bool ignore_boring, bool skip_unreported);
169
170 // Implements Process::DumpThreadPlansForTID
171 bool DumpPlansForTID(Stream &strm, lldb::tid_t tid,
172 lldb::DescriptionLevel desc_level, bool internal,
173 bool ignore_boring, bool skip_unreported);
174
176
177private:
179 mutable std::recursive_mutex m_stack_map_mutex;
180 using PlansList = std::unordered_map<lldb::tid_t, ThreadPlanStack>;
182
183};
184
185} // namespace lldb_private
186
187#endif // LLDB_TARGET_THREADPLANSTACK_H
A plug-in interface definition class for debugging a process.
Definition: Process.h:341
A stream class that can stream formatted output to a file.
Definition: Stream.h:28
void ClearThreadCache()
Clear the Thread* cache that each ThreadPlan contains.
bool RemoveTID(lldb::tid_t tid)
std::recursive_mutex m_stack_map_mutex
void DumpPlans(Stream &strm, lldb::DescriptionLevel desc_level, bool internal, bool ignore_boring, bool skip_unreported)
bool PrunePlansForTID(lldb::tid_t tid)
ThreadPlanStack * Find(lldb::tid_t tid)
void Update(ThreadList &current_threads, bool delete_missing, bool check_for_new=true)
bool DumpPlansForTID(Stream &strm, lldb::tid_t tid, lldb::DescriptionLevel desc_level, bool internal, bool ignore_boring, bool skip_unreported)
std::unordered_map< lldb::tid_t, ThreadPlanStack > PlansList
PlanStack m_discarded_plans
Plans that have been discarded by this stop.
void DiscardPlansUpToPlan(ThreadPlan *up_to_plan_ptr)
void PrintOneStack(Stream &s, llvm::StringRef stack_name, const PlanStack &stack, lldb::DescriptionLevel desc_level, bool include_internal) const
void DumpThreadPlans(Stream &s, lldb::DescriptionLevel desc_level, bool include_internal) const
lldb::ThreadPlanSP GetCompletedPlan(bool skip_private=true) const
lldb::ExpressionVariableSP GetExpressionVariable() const
PlanStack m_completed_plans
Plans that have been completed by this stop.
void ThreadDestroyed(Thread *thread)
std::recursive_mutex m_stack_mutex
bool IsPlanDone(ThreadPlan *plan) const
void RestoreCompletedPlanCheckpoint(size_t checkpoint)
lldb::ThreadPlanSP GetPlanByIndex(uint32_t plan_idx, bool skip_private=true) const
lldb::ValueObjectSP GetReturnValueObject() const
void PushPlan(lldb::ThreadPlanSP new_plan_sp)
lldb::ThreadPlanSP DiscardPlan()
std::unordered_map< size_t, PlanStack > m_completed_plan_store
bool WasPlanDiscarded(ThreadPlan *plan) const
void ClearThreadCache()
Clear the Thread* cache that each ThreadPlan contains.
void DiscardCompletedPlanCheckpoint(size_t checkpoint)
ThreadPlan * GetInnermostExpression() const
PlanStack m_plans
The stack of plans this thread is executing.
lldb::ThreadPlanSP GetCurrentPlan() const
ThreadPlan * GetPreviousPlan(ThreadPlan *current_plan) const
std::vector< lldb::ThreadPlanSP > PlanStack
A class that represents a running process on the host machine.
Definition: SBAttachInfo.h:14
std::shared_ptr< lldb_private::ThreadPlan > ThreadPlanSP
Definition: lldb-forward.h:441
DescriptionLevel
Description levels for "void GetDescription(Stream *, DescriptionLevel)" calls.
std::shared_ptr< lldb_private::ValueObject > ValueObjectSP
Definition: lldb-forward.h:472
std::shared_ptr< lldb_private::ExpressionVariable > ExpressionVariableSP
Definition: lldb-forward.h:343
uint64_t tid_t
Definition: lldb-types.h:82
lldb::user_id_t GetID() const
Get accessor for the user ID.
Definition: UserID.h:47