1 //===-- ThreadPlan.cpp ------------------------------------------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
12 // Other libraries and framework includes
14 #include "lldb/Target/ThreadPlan.h"
15 #include "lldb/Core/Debugger.h"
16 #include "lldb/Core/Log.h"
17 #include "lldb/Core/State.h"
18 #include "lldb/Target/Process.h"
19 #include "lldb/Target/RegisterContext.h"
20 #include "lldb/Target/Target.h"
21 #include "lldb/Target/Thread.h"
22 #include "lldb/Utility/ConvertEnum.h"
25 using namespace lldb_private;
27 //----------------------------------------------------------------------
28 // ThreadPlan constructor
29 //----------------------------------------------------------------------
30 ThreadPlan::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) {
40 //----------------------------------------------------------------------
42 //----------------------------------------------------------------------
43 ThreadPlan::~ThreadPlan() = default;
45 bool 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;
51 return m_cached_plan_explains_stop == eLazyBoolYes;
55 bool ThreadPlan::IsPlanComplete() {
56 std::lock_guard<std::recursive_mutex> guard(m_plan_complete_mutex);
57 return m_plan_complete;
60 void 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;
66 bool 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;
73 Vote ThreadPlan::ShouldReportStop(Event *event_ptr) {
74 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));
76 if (m_stop_vote == eVoteNoOpinion) {
77 ThreadPlan *prev_plan = GetPreviousPlan();
79 Vote prev_vote = prev_plan->ShouldReportStop(event_ptr);
81 log->Printf("ThreadPlan::ShouldReportStop() returning previous thread "
83 GetVoteAsCString(prev_vote));
88 log->Printf("ThreadPlan::ShouldReportStop() returning vote: %s",
89 GetVoteAsCString(m_stop_vote));
93 Vote ThreadPlan::ShouldReportRun(Event *event_ptr) {
94 if (m_run_vote == eVoteNoOpinion) {
95 ThreadPlan *prev_plan = GetPreviousPlan();
97 return prev_plan->ShouldReportRun(event_ptr);
102 bool ThreadPlan::StopOthers() {
103 ThreadPlan *prev_plan;
104 prev_plan = GetPreviousPlan();
105 return (prev_plan == nullptr) ? false : prev_plan->StopOthers();
108 void 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.
113 bool ThreadPlan::WillResume(StateType resume_state, bool current_plan) {
114 m_cached_plan_explains_stop = eLazyBoolCalculate;
117 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));
120 RegisterContext *reg_ctx = m_thread.GetRegisterContext().get();
122 addr_t pc = reg_ctx->GetPC();
123 addr_t sp = reg_ctx->GetSP();
124 addr_t fp = reg_ctx->GetFP();
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());
135 return DoWillResume(resume_state, current_plan);
138 lldb::user_id_t ThreadPlan::GetNextID() {
139 static uint32_t g_nextPlanID = 0;
140 return ++g_nextPlanID;
143 void ThreadPlan::DidPush() {}
145 void ThreadPlan::WillPop() {}
147 bool ThreadPlan::OkayToDiscard() {
148 return IsMasterPlan() ? m_okay_to_discard : true;
151 lldb::StateType ThreadPlan::RunState() {
152 if (m_tracer_sp && m_tracer_sp->TracingEnabled() &&
153 m_tracer_sp->SingleStepEnabled())
154 return eStateStepping;
156 return GetPlanRunState();
159 bool ThreadPlan::IsUsuallyUnexplainedStopReason(lldb::StopReason reason) {
161 case eStopReasonWatchpoint:
162 case eStopReasonSignal:
163 case eStopReasonException:
164 case eStopReasonExec:
165 case eStopReasonThreadExiting:
166 case eStopReasonInstrumentation:
173 //----------------------------------------------------------------------
175 //----------------------------------------------------------------------
177 ThreadPlanNull::ThreadPlanNull(Thread &thread)
178 : ThreadPlan(ThreadPlan::eKindNull, "Null Thread Plan", thread,
179 eVoteNoOpinion, eVoteNoOpinion) {}
181 ThreadPlanNull::~ThreadPlanNull() = default;
183 void ThreadPlanNull::GetDescription(Stream *s, lldb::DescriptionLevel level) {
184 s->PutCString("Null thread plan - thread has been destroyed.");
187 bool ThreadPlanNull::ValidatePlan(Stream *error) {
188 #ifdef LLDB_CONFIGURATION_DEBUG
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());
194 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD));
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());
204 bool ThreadPlanNull::ShouldStop(Event *event_ptr) {
205 #ifdef LLDB_CONFIGURATION_DEBUG
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());
211 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD));
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());
221 bool ThreadPlanNull::WillStop() {
222 #ifdef LLDB_CONFIGURATION_DEBUG
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());
228 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD));
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());
238 bool ThreadPlanNull::DoPlanExplainsStop(Event *event_ptr) {
239 #ifdef LLDB_CONFIGURATION_DEBUG
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());
245 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD));
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());
255 // The null plan is never done.
256 bool ThreadPlanNull::MischiefManaged() {
257 // The null plan is never done.
258 #ifdef LLDB_CONFIGURATION_DEBUG
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());
264 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD));
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());
274 lldb::StateType ThreadPlanNull::GetPlanRunState() {
275 // Not sure what to return here. This is a dead thread.
276 #ifdef LLDB_CONFIGURATION_DEBUG
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());
282 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD));
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());
289 return eStateRunning;