blob: 6b997476d92f40a3fe4cc7aeaef3d582e430331b [file] [log] [blame]
Chris Lattner30fdc8d2010-06-08 16:52:241//===-- ThreadPlan.cpp ------------------------------------------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
Chris Lattner30fdc8d2010-06-08 16:52:2410// C Includes
11// C++ Includes
12// Other libraries and framework includes
13// Project includes
Eugene Zelenkoe65b2cf2015-12-15 01:33:1914#include "lldb/Target/ThreadPlan.h"
Jim Ingham06e827c2010-11-11 19:26:0915#include "lldb/Core/Debugger.h"
Chris Lattner30fdc8d2010-06-08 16:52:2416#include "lldb/Core/Log.h"
17#include "lldb/Core/State.h"
Jim Ingham06e827c2010-11-11 19:26:0918#include "lldb/Target/Process.h"
Kate Stoneb9c1b512016-09-06 20:57:5019#include "lldb/Target/RegisterContext.h"
Jim Ingham06e827c2010-11-11 19:26:0920#include "lldb/Target/Target.h"
Kate Stoneb9c1b512016-09-06 20:57:5021#include "lldb/Target/Thread.h"
Zachary Turner50232572015-03-18 21:31:4522#include "lldb/Utility/ConvertEnum.h"
Chris Lattner30fdc8d2010-06-08 16:52:2423
24using namespace lldb;
25using namespace lldb_private;
26
27//----------------------------------------------------------------------
28// ThreadPlan constructor
29//----------------------------------------------------------------------
Kate Stoneb9c1b512016-09-06 20:57:5030ThreadPlan::ThreadPlan(ThreadPlanKind kind, const char *name, Thread &thread,
31 Vote stop_vote, Vote run_vote)
32 : m_thread(thread), m_stop_vote(stop_vote), m_run_vote(run_vote),
33 m_kind(kind), m_name(name), m_plan_complete_mutex(),
34 m_cached_plan_explains_stop(eLazyBoolCalculate), m_plan_complete(false),
35 m_plan_private(false), m_okay_to_discard(true), m_is_master_plan(false),
36 m_plan_succeeded(true) {
37 SetID(GetNextID());
Chris Lattner30fdc8d2010-06-08 16:52:2438}
39
40//----------------------------------------------------------------------
41// Destructor
42//----------------------------------------------------------------------
Eugene Zelenkoe65b2cf2015-12-15 01:33:1943ThreadPlan::~ThreadPlan() = default;
Chris Lattner30fdc8d2010-06-08 16:52:2444
Kate Stoneb9c1b512016-09-06 20:57:5045bool ThreadPlan::PlanExplainsStop(Event *event_ptr) {
46 if (m_cached_plan_explains_stop == eLazyBoolCalculate) {
47 bool actual_value = DoPlanExplainsStop(event_ptr);
48 m_cached_plan_explains_stop = actual_value ? eLazyBoolYes : eLazyBoolNo;
49 return actual_value;
50 } else {
51 return m_cached_plan_explains_stop == eLazyBoolYes;
52 }
53}
54
55bool ThreadPlan::IsPlanComplete() {
56 std::lock_guard<std::recursive_mutex> guard(m_plan_complete_mutex);
57 return m_plan_complete;
58}
59
60void ThreadPlan::SetPlanComplete(bool success) {
61 std::lock_guard<std::recursive_mutex> guard(m_plan_complete_mutex);
62 m_plan_complete = true;
63 m_plan_succeeded = success;
64}
65
66bool ThreadPlan::MischiefManaged() {
67 std::lock_guard<std::recursive_mutex> guard(m_plan_complete_mutex);
68 // Mark the plan is complete, but don't override the success flag.
69 m_plan_complete = true;
70 return true;
71}
72
73Vote ThreadPlan::ShouldReportStop(Event *event_ptr) {
74 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));
75
76 if (m_stop_vote == eVoteNoOpinion) {
77 ThreadPlan *prev_plan = GetPreviousPlan();
78 if (prev_plan) {
79 Vote prev_vote = prev_plan->ShouldReportStop(event_ptr);
80 if (log)
81 log->Printf("ThreadPlan::ShouldReportStop() returning previous thread "
82 "plan vote: %s",
83 GetVoteAsCString(prev_vote));
84 return prev_vote;
Jim Ingham221d51c2013-05-08 00:35:1685 }
Kate Stoneb9c1b512016-09-06 20:57:5086 }
87 if (log)
88 log->Printf("ThreadPlan::ShouldReportStop() returning vote: %s",
89 GetVoteAsCString(m_stop_vote));
90 return m_stop_vote;
91}
92
93Vote ThreadPlan::ShouldReportRun(Event *event_ptr) {
94 if (m_run_vote == eVoteNoOpinion) {
95 ThreadPlan *prev_plan = GetPreviousPlan();
96 if (prev_plan)
97 return prev_plan->ShouldReportRun(event_ptr);
98 }
99 return m_run_vote;
100}
101
102bool ThreadPlan::StopOthers() {
103 ThreadPlan *prev_plan;
104 prev_plan = GetPreviousPlan();
105 return (prev_plan == nullptr) ? false : prev_plan->StopOthers();
106}
107
108void ThreadPlan::SetStopOthers(bool new_value) {
109 // SetStopOthers doesn't work up the hierarchy. You have to set the
110 // explicit ThreadPlan you want to affect.
111}
112
113bool ThreadPlan::WillResume(StateType resume_state, bool current_plan) {
114 m_cached_plan_explains_stop = eLazyBoolCalculate;
115
116 if (current_plan) {
117 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));
118
119 if (log) {
120 RegisterContext *reg_ctx = m_thread.GetRegisterContext().get();
121 assert(reg_ctx);
122 addr_t pc = reg_ctx->GetPC();
123 addr_t sp = reg_ctx->GetSP();
124 addr_t fp = reg_ctx->GetFP();
125 log->Printf(
126 "%s Thread #%u (0x%p): tid = 0x%4.4" PRIx64 ", pc = 0x%8.8" PRIx64
127 ", sp = 0x%8.8" PRIx64 ", fp = 0x%8.8" PRIx64 ", "
128 "plan = '%s', state = %s, stop others = %d",
129 __FUNCTION__, m_thread.GetIndexID(), static_cast<void *>(&m_thread),
130 m_thread.GetID(), static_cast<uint64_t>(pc),
131 static_cast<uint64_t>(sp), static_cast<uint64_t>(fp), m_name.c_str(),
132 StateAsCString(resume_state), StopOthers());
Jim Ingham221d51c2013-05-08 00:35:16133 }
Kate Stoneb9c1b512016-09-06 20:57:50134 }
135 return DoWillResume(resume_state, current_plan);
Jim Ingham221d51c2013-05-08 00:35:16136}
137
Kate Stoneb9c1b512016-09-06 20:57:50138lldb::user_id_t ThreadPlan::GetNextID() {
139 static uint32_t g_nextPlanID = 0;
140 return ++g_nextPlanID;
Chris Lattner30fdc8d2010-06-08 16:52:24141}
142
Kate Stoneb9c1b512016-09-06 20:57:50143void ThreadPlan::DidPush() {}
144
145void ThreadPlan::WillPop() {}
146
147bool ThreadPlan::OkayToDiscard() {
148 return IsMasterPlan() ? m_okay_to_discard : true;
Chris Lattner30fdc8d2010-06-08 16:52:24149}
150
Kate Stoneb9c1b512016-09-06 20:57:50151lldb::StateType ThreadPlan::RunState() {
152 if (m_tracer_sp && m_tracer_sp->TracingEnabled() &&
153 m_tracer_sp->SingleStepEnabled())
154 return eStateStepping;
155 else
156 return GetPlanRunState();
157}
158
159bool ThreadPlan::IsUsuallyUnexplainedStopReason(lldb::StopReason reason) {
160 switch (reason) {
161 case eStopReasonWatchpoint:
162 case eStopReasonSignal:
163 case eStopReasonException:
164 case eStopReasonExec:
165 case eStopReasonThreadExiting:
166 case eStopReasonInstrumentation:
Chris Lattner30fdc8d2010-06-08 16:52:24167 return true;
Kate Stoneb9c1b512016-09-06 20:57:50168 default:
169 return false;
170 }
Jim Ingham9b03fa02015-07-23 19:55:02171}
172
Greg Clayton6e10f142013-07-30 00:23:06173//----------------------------------------------------------------------
174// ThreadPlanNull
175//----------------------------------------------------------------------
176
Kate Stoneb9c1b512016-09-06 20:57:50177ThreadPlanNull::ThreadPlanNull(Thread &thread)
178 : ThreadPlan(ThreadPlan::eKindNull, "Null Thread Plan", thread,
179 eVoteNoOpinion, eVoteNoOpinion) {}
Greg Clayton6e10f142013-07-30 00:23:06180
Eugene Zelenkoe65b2cf2015-12-15 01:33:19181ThreadPlanNull::~ThreadPlanNull() = default;
Greg Clayton6e10f142013-07-30 00:23:06182
Kate Stoneb9c1b512016-09-06 20:57:50183void ThreadPlanNull::GetDescription(Stream *s, lldb::DescriptionLevel level) {
184 s->PutCString("Null thread plan - thread has been destroyed.");
Greg Clayton6e10f142013-07-30 00:23:06185}
186
Kate Stoneb9c1b512016-09-06 20:57:50187bool ThreadPlanNull::ValidatePlan(Stream *error) {
Greg Clayton6e10f142013-07-30 00:23:06188#ifdef LLDB_CONFIGURATION_DEBUG
Kate Stoneb9c1b512016-09-06 20:57:50189 fprintf(stderr,
190 "error: %s called on thread that has been destroyed (tid = 0x%" PRIx64
191 ", ptid = 0x%" PRIx64 ")",
192 LLVM_PRETTY_FUNCTION, m_thread.GetID(), m_thread.GetProtocolID());
Greg Clayton6e10f142013-07-30 00:23:06193#else
Kate Stoneb9c1b512016-09-06 20:57:50194 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD));
195 if (log)
196 log->Error("%s called on thread that has been destroyed (tid = 0x%" PRIx64
197 ", ptid = 0x%" PRIx64 ")",
198 LLVM_PRETTY_FUNCTION, m_thread.GetID(),
199 m_thread.GetProtocolID());
Greg Clayton6e10f142013-07-30 00:23:06200#endif
Kate Stoneb9c1b512016-09-06 20:57:50201 return true;
Greg Clayton6e10f142013-07-30 00:23:06202}
203
Kate Stoneb9c1b512016-09-06 20:57:50204bool ThreadPlanNull::ShouldStop(Event *event_ptr) {
Greg Clayton6e10f142013-07-30 00:23:06205#ifdef LLDB_CONFIGURATION_DEBUG
Kate Stoneb9c1b512016-09-06 20:57:50206 fprintf(stderr,
207 "error: %s called on thread that has been destroyed (tid = 0x%" PRIx64
208 ", ptid = 0x%" PRIx64 ")",
209 LLVM_PRETTY_FUNCTION, m_thread.GetID(), m_thread.GetProtocolID());
Greg Clayton6e10f142013-07-30 00:23:06210#else
Kate Stoneb9c1b512016-09-06 20:57:50211 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD));
212 if (log)
213 log->Error("%s called on thread that has been destroyed (tid = 0x%" PRIx64
214 ", ptid = 0x%" PRIx64 ")",
215 LLVM_PRETTY_FUNCTION, m_thread.GetID(),
216 m_thread.GetProtocolID());
Greg Clayton6e10f142013-07-30 00:23:06217#endif
Kate Stoneb9c1b512016-09-06 20:57:50218 return true;
Greg Clayton6e10f142013-07-30 00:23:06219}
220
Kate Stoneb9c1b512016-09-06 20:57:50221bool ThreadPlanNull::WillStop() {
Greg Clayton6e10f142013-07-30 00:23:06222#ifdef LLDB_CONFIGURATION_DEBUG
Kate Stoneb9c1b512016-09-06 20:57:50223 fprintf(stderr,
224 "error: %s called on thread that has been destroyed (tid = 0x%" PRIx64
225 ", ptid = 0x%" PRIx64 ")",
226 LLVM_PRETTY_FUNCTION, m_thread.GetID(), m_thread.GetProtocolID());
Greg Clayton6e10f142013-07-30 00:23:06227#else
Kate Stoneb9c1b512016-09-06 20:57:50228 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD));
229 if (log)
230 log->Error("%s called on thread that has been destroyed (tid = 0x%" PRIx64
231 ", ptid = 0x%" PRIx64 ")",
232 LLVM_PRETTY_FUNCTION, m_thread.GetID(),
233 m_thread.GetProtocolID());
Greg Clayton6e10f142013-07-30 00:23:06234#endif
Kate Stoneb9c1b512016-09-06 20:57:50235 return true;
Greg Clayton6e10f142013-07-30 00:23:06236}
237
Kate Stoneb9c1b512016-09-06 20:57:50238bool ThreadPlanNull::DoPlanExplainsStop(Event *event_ptr) {
Greg Clayton6e10f142013-07-30 00:23:06239#ifdef LLDB_CONFIGURATION_DEBUG
Kate Stoneb9c1b512016-09-06 20:57:50240 fprintf(stderr,
241 "error: %s called on thread that has been destroyed (tid = 0x%" PRIx64
242 ", ptid = 0x%" PRIx64 ")",
243 LLVM_PRETTY_FUNCTION, m_thread.GetID(), m_thread.GetProtocolID());
Greg Clayton6e10f142013-07-30 00:23:06244#else
Kate Stoneb9c1b512016-09-06 20:57:50245 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD));
246 if (log)
247 log->Error("%s called on thread that has been destroyed (tid = 0x%" PRIx64
248 ", ptid = 0x%" PRIx64 ")",
249 LLVM_PRETTY_FUNCTION, m_thread.GetID(),
250 m_thread.GetProtocolID());
Greg Clayton6e10f142013-07-30 00:23:06251#endif
Kate Stoneb9c1b512016-09-06 20:57:50252 return true;
Greg Clayton6e10f142013-07-30 00:23:06253}
254
255// The null plan is never done.
Kate Stoneb9c1b512016-09-06 20:57:50256bool ThreadPlanNull::MischiefManaged() {
257// The null plan is never done.
Greg Clayton6e10f142013-07-30 00:23:06258#ifdef LLDB_CONFIGURATION_DEBUG
Kate Stoneb9c1b512016-09-06 20:57:50259 fprintf(stderr,
260 "error: %s called on thread that has been destroyed (tid = 0x%" PRIx64
261 ", ptid = 0x%" PRIx64 ")",
262 LLVM_PRETTY_FUNCTION, m_thread.GetID(), m_thread.GetProtocolID());
Greg Clayton6e10f142013-07-30 00:23:06263#else
Kate Stoneb9c1b512016-09-06 20:57:50264 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD));
265 if (log)
266 log->Error("%s called on thread that has been destroyed (tid = 0x%" PRIx64
267 ", ptid = 0x%" PRIx64 ")",
268 LLVM_PRETTY_FUNCTION, m_thread.GetID(),
269 m_thread.GetProtocolID());
Greg Clayton6e10f142013-07-30 00:23:06270#endif
Kate Stoneb9c1b512016-09-06 20:57:50271 return false;
Greg Clayton6e10f142013-07-30 00:23:06272}
273
Kate Stoneb9c1b512016-09-06 20:57:50274lldb::StateType ThreadPlanNull::GetPlanRunState() {
275// Not sure what to return here. This is a dead thread.
Greg Clayton6e10f142013-07-30 00:23:06276#ifdef LLDB_CONFIGURATION_DEBUG
Kate Stoneb9c1b512016-09-06 20:57:50277 fprintf(stderr,
278 "error: %s called on thread that has been destroyed (tid = 0x%" PRIx64
279 ", ptid = 0x%" PRIx64 ")",
280 LLVM_PRETTY_FUNCTION, m_thread.GetID(), m_thread.GetProtocolID());
Greg Clayton6e10f142013-07-30 00:23:06281#else
Kate Stoneb9c1b512016-09-06 20:57:50282 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD));
283 if (log)
284 log->Error("%s called on thread that has been destroyed (tid = 0x%" PRIx64
285 ", ptid = 0x%" PRIx64 ")",
286 LLVM_PRETTY_FUNCTION, m_thread.GetID(),
287 m_thread.GetProtocolID());
Greg Clayton6e10f142013-07-30 00:23:06288#endif
Kate Stoneb9c1b512016-09-06 20:57:50289 return eStateRunning;
Greg Clayton6e10f142013-07-30 00:23:06290}