24 s.
Printf(
"Element %d: ", elem_idx);
25 plan->GetDescription(&s, desc_level);
30 ThreadPlanStack::ThreadPlanStack(
const Thread &thread,
bool make_null) {
39 void ThreadPlanStack::DumpThreadPlans(
Stream &s,
41 bool include_internal)
const {
42 std::lock_guard<std::recursive_mutex> guard(m_stack_mutex);
44 PrintOneStack(s,
"Active plan stack", m_plans, desc_level, include_internal);
45 PrintOneStack(s,
"Completed plan stack", m_completed_plans, desc_level,
47 PrintOneStack(s,
"Discarded plan stack", m_discarded_plans, desc_level,
52 void ThreadPlanStack::PrintOneStack(
Stream &s, llvm::StringRef stack_name,
55 bool include_internal)
const {
56 std::lock_guard<std::recursive_mutex> guard(m_stack_mutex);
62 bool any_public =
false;
63 if (!include_internal) {
64 for (
auto plan : stack) {
65 if (!plan->GetPrivate()) {
72 if (include_internal || any_public) {
75 s << stack_name <<
":\n";
76 for (
auto plan : stack) {
77 if (!include_internal && plan->GetPrivate())
84 size_t ThreadPlanStack::CheckpointCompletedPlans() {
85 std::lock_guard<std::recursive_mutex> guard(m_stack_mutex);
86 m_completed_plan_checkpoint++;
87 m_completed_plan_store.insert(
88 std::make_pair(m_completed_plan_checkpoint, m_completed_plans));
89 return m_completed_plan_checkpoint;
92 void ThreadPlanStack::RestoreCompletedPlanCheckpoint(
size_t checkpoint) {
93 std::lock_guard<std::recursive_mutex> guard(m_stack_mutex);
94 auto result = m_completed_plan_store.find(checkpoint);
95 assert(result != m_completed_plan_store.end() &&
96 "Asked for a checkpoint that didn't exist");
97 m_completed_plans.swap((*result).second);
98 m_completed_plan_store.erase(result);
101 void ThreadPlanStack::DiscardCompletedPlanCheckpoint(
size_t checkpoint) {
102 std::lock_guard<std::recursive_mutex> guard(m_stack_mutex);
103 m_completed_plan_store.erase(checkpoint);
106 void ThreadPlanStack::ThreadDestroyed(
Thread *thread) {
108 std::lock_guard<std::recursive_mutex> guard(m_stack_mutex);
109 for (ThreadPlanSP plan : m_plans)
110 plan->ThreadDestroyed();
112 for (ThreadPlanSP plan : m_discarded_plans)
113 plan->ThreadDestroyed();
115 for (ThreadPlanSP plan : m_completed_plans)
116 plan->ThreadDestroyed();
120 m_discarded_plans.clear();
121 m_completed_plans.clear();
127 if (thread !=
nullptr) {
129 m_plans.push_back(null_plan_sp);
133 void ThreadPlanStack::PushPlan(lldb::ThreadPlanSP new_plan_sp) {
137 std::lock_guard<std::recursive_mutex> guard(m_stack_mutex);
138 assert((m_plans.size() > 0 || new_plan_sp->IsBasePlan()) &&
139 "Zeroth plan must be a base plan");
141 if (!new_plan_sp->GetThreadPlanTracer()) {
142 assert(!m_plans.empty());
143 new_plan_sp->SetThreadPlanTracer(m_plans.back()->GetThreadPlanTracer());
145 m_plans.push_back(new_plan_sp);
146 new_plan_sp->DidPush();
149 lldb::ThreadPlanSP ThreadPlanStack::PopPlan() {
150 std::lock_guard<std::recursive_mutex> guard(m_stack_mutex);
151 assert(m_plans.size() > 1 &&
"Can't pop the base thread plan");
156 lldb::ThreadPlanSP plan_sp = m_plans.back();
158 m_completed_plans.push_back(plan_sp);
163 lldb::ThreadPlanSP ThreadPlanStack::DiscardPlan() {
164 std::lock_guard<std::recursive_mutex> guard(m_stack_mutex);
165 assert(m_plans.size() > 1 &&
"Can't discard the base thread plan");
170 lldb::ThreadPlanSP plan_sp = m_plans.back();
172 m_discarded_plans.push_back(plan_sp);
179 void ThreadPlanStack::DiscardPlansUpToPlan(
ThreadPlan *up_to_plan_ptr) {
180 std::lock_guard<std::recursive_mutex> guard(m_stack_mutex);
181 int stack_size = m_plans.size();
183 if (up_to_plan_ptr ==
nullptr) {
184 for (
int i = stack_size - 1; i > 0; i--)
189 bool found_it =
false;
190 for (
int i = stack_size - 1; i > 0; i--) {
191 if (m_plans[i].get() == up_to_plan_ptr) {
198 bool last_one =
false;
199 for (
int i = stack_size - 1; i > 0 && !last_one; i--) {
200 if (GetCurrentPlan().get() == up_to_plan_ptr)
207 void ThreadPlanStack::DiscardAllPlans() {
208 std::lock_guard<std::recursive_mutex> guard(m_stack_mutex);
209 int stack_size = m_plans.size();
210 for (
int i = stack_size - 1; i > 0; i--) {
215 void ThreadPlanStack::DiscardConsultingControllingPlans() {
216 std::lock_guard<std::recursive_mutex> guard(m_stack_mutex);
218 int controlling_plan_idx;
223 for (controlling_plan_idx = m_plans.size() - 1; controlling_plan_idx >= 0;
224 controlling_plan_idx--) {
225 if (m_plans[controlling_plan_idx]->IsControllingPlan()) {
226 discard = m_plans[controlling_plan_idx]->OkayToDiscard();
236 for (
int i = m_plans.size() - 1; i > controlling_plan_idx; i--) {
243 if (controlling_plan_idx > 0) {
249 lldb::ThreadPlanSP ThreadPlanStack::GetCurrentPlan()
const {
250 std::lock_guard<std::recursive_mutex> guard(m_stack_mutex);
251 assert(m_plans.size() != 0 &&
"There will always be a base plan.");
252 return m_plans.back();
255 lldb::ThreadPlanSP ThreadPlanStack::GetCompletedPlan(
bool skip_private)
const {
256 std::lock_guard<std::recursive_mutex> guard(m_stack_mutex);
257 if (m_completed_plans.empty())
261 return m_completed_plans.back();
263 for (
int i = m_completed_plans.size() - 1; i >= 0; i--) {
264 lldb::ThreadPlanSP completed_plan_sp;
265 completed_plan_sp = m_completed_plans[i];
266 if (!completed_plan_sp->GetPrivate())
267 return completed_plan_sp;
272 lldb::ThreadPlanSP ThreadPlanStack::GetPlanByIndex(
uint32_t plan_idx,
273 bool skip_private)
const {
274 std::lock_guard<std::recursive_mutex> guard(m_stack_mutex);
277 for (lldb::ThreadPlanSP plan_sp : m_plans) {
278 if (skip_private && plan_sp->GetPrivate())
287 lldb::ValueObjectSP ThreadPlanStack::GetReturnValueObject()
const {
288 std::lock_guard<std::recursive_mutex> guard(m_stack_mutex);
289 if (m_completed_plans.empty())
292 for (
int i = m_completed_plans.size() - 1; i >= 0; i--) {
293 lldb::ValueObjectSP return_valobj_sp;
294 return_valobj_sp = m_completed_plans[i]->GetReturnValueObject();
295 if (return_valobj_sp)
296 return return_valobj_sp;
301 lldb::ExpressionVariableSP ThreadPlanStack::GetExpressionVariable()
const {
302 std::lock_guard<std::recursive_mutex> guard(m_stack_mutex);
303 if (m_completed_plans.empty())
306 for (
int i = m_completed_plans.size() - 1; i >= 0; i--) {
307 lldb::ExpressionVariableSP expression_variable_sp;
308 expression_variable_sp = m_completed_plans[i]->GetExpressionVariable();
309 if (expression_variable_sp)
310 return expression_variable_sp;
314 bool ThreadPlanStack::AnyPlans()
const {
315 std::lock_guard<std::recursive_mutex> guard(m_stack_mutex);
317 return m_plans.size() > 1;
320 bool ThreadPlanStack::AnyCompletedPlans()
const {
321 std::lock_guard<std::recursive_mutex> guard(m_stack_mutex);
322 return !m_completed_plans.empty();
325 bool ThreadPlanStack::AnyDiscardedPlans()
const {
326 std::lock_guard<std::recursive_mutex> guard(m_stack_mutex);
327 return !m_discarded_plans.empty();
330 bool ThreadPlanStack::IsPlanDone(
ThreadPlan *in_plan)
const {
331 std::lock_guard<std::recursive_mutex> guard(m_stack_mutex);
332 for (
auto plan : m_completed_plans) {
333 if (plan.get() == in_plan)
339 bool ThreadPlanStack::WasPlanDiscarded(
ThreadPlan *in_plan)
const {
340 std::lock_guard<std::recursive_mutex> guard(m_stack_mutex);
341 for (
auto plan : m_discarded_plans) {
342 if (plan.get() == in_plan)
349 std::lock_guard<std::recursive_mutex> guard(m_stack_mutex);
350 if (current_plan ==
nullptr)
355 int stack_size = m_completed_plans.size();
356 for (
int i = stack_size - 1; i > 0; i--) {
357 if (current_plan == m_completed_plans[i].get())
358 return m_completed_plans[i - 1].get();
363 if (stack_size > 0 && m_completed_plans[0].get() == current_plan) {
364 return GetCurrentPlan().get();
368 stack_size = m_plans.size();
369 for (
int i = stack_size - 1; i > 0; i--) {
370 if (current_plan == m_plans[i].get())
371 return m_plans[i - 1].get();
376 ThreadPlan *ThreadPlanStack::GetInnermostExpression()
const {
377 std::lock_guard<std::recursive_mutex> guard(m_stack_mutex);
378 int stack_size = m_plans.size();
380 for (
int i = stack_size - 1; i > 0; i--) {
381 if (m_plans[i]->GetKind() == ThreadPlan::eKindCallFunction)
382 return m_plans[i].get();
387 void ThreadPlanStack::ClearThreadCache() {
388 std::lock_guard<std::recursive_mutex> guard(m_stack_mutex);
389 for (lldb::ThreadPlanSP thread_plan_sp : m_plans)
390 thread_plan_sp->ClearThreadCache();
393 void ThreadPlanStack::WillResume() {
394 std::lock_guard<std::recursive_mutex> guard(m_stack_mutex);
395 m_completed_plans.clear();
396 m_discarded_plans.clear();
401 bool check_for_new) {
403 std::lock_guard<std::recursive_mutex> guard(m_stack_map_mutex);
406 for (
auto thread : current_threads.
Threads()) {
408 if (!Find(cur_tid)) {
409 AddThread(*thread.get());
410 thread->QueueBasePlan(
true);
420 std::vector<lldb::tid_t> missing_threads;
423 for (
auto &thread_plans : m_plans_list) {
427 missing_threads.push_back(cur_tid);
434 void ThreadPlanStackMap::DumpPlans(
Stream &strm,
436 bool internal,
bool condense_if_trivial,
437 bool skip_unreported) {
438 std::lock_guard<std::recursive_mutex> guard(m_stack_map_mutex);
439 for (
auto &elem : m_plans_list) {
442 ThreadSP thread_sp = m_process.GetThreadList().FindThreadByID(tid);
444 if (skip_unreported) {
449 index_id = thread_sp->GetIndexID();
451 if (condense_if_trivial) {
452 if (!elem.second.AnyPlans() && !elem.second.AnyCompletedPlans() &&
453 !elem.second.AnyDiscardedPlans()) {
454 strm.
Printf(
"thread #%u: tid = 0x%4.4" PRIx64
"\n", index_id, tid);
457 strm.
Printf(
"No active thread plans\n");
464 strm.
Printf(
"thread #%u: tid = 0x%4.4" PRIx64
":\n", index_id, tid);
466 elem.second.DumpThreadPlans(strm, desc_level,
internal);
473 bool condense_if_trivial,
474 bool skip_unreported) {
475 std::lock_guard<std::recursive_mutex> guard(m_stack_map_mutex);
477 ThreadSP thread_sp = m_process.GetThreadList().FindThreadByID(tid);
479 if (skip_unreported) {
481 strm.
Format(
"Unknown TID: {0}", tid);
487 index_id = thread_sp->GetIndexID();
490 strm.
Format(
"Unknown TID: {0}\n", tid);
494 if (condense_if_trivial) {
497 strm.
Printf(
"thread #%u: tid = 0x%4.4" PRIx64
"\n", index_id, tid);
500 strm.
Printf(
"No active thread plans\n");
507 strm.
Printf(
"thread #%u: tid = 0x%4.4" PRIx64
":\n", index_id, tid);
515 std::lock_guard<std::recursive_mutex> guard(m_stack_map_mutex);
516 ThreadSP thread_sp = m_process.GetThreadList().FindThreadByID(tid);
520 return RemoveTID(tid);