130fdc8d8SChris Lattner //===-- ThreadPlan.cpp ------------------------------------------*- C++ -*-===//
230fdc8d8SChris Lattner //
330fdc8d8SChris Lattner //                     The LLVM Compiler Infrastructure
430fdc8d8SChris Lattner //
530fdc8d8SChris Lattner // This file is distributed under the University of Illinois Open Source
630fdc8d8SChris Lattner // License. See LICENSE.TXT for details.
730fdc8d8SChris Lattner //
830fdc8d8SChris Lattner //===----------------------------------------------------------------------===//
930fdc8d8SChris Lattner 
1030fdc8d8SChris Lattner // C Includes
1130fdc8d8SChris Lattner // C++ Includes
1230fdc8d8SChris Lattner // Other libraries and framework includes
1330fdc8d8SChris Lattner // Project includes
14*e65b2cf2SEugene Zelenko #include "lldb/Target/ThreadPlan.h"
1506e827ccSJim Ingham #include "lldb/Core/Debugger.h"
1630fdc8d8SChris Lattner #include "lldb/Core/Log.h"
1730fdc8d8SChris Lattner #include "lldb/Core/State.h"
182cad65a5SGreg Clayton #include "lldb/Target/RegisterContext.h"
192cad65a5SGreg Clayton #include "lldb/Target/Thread.h"
2006e827ccSJim Ingham #include "lldb/Target/Process.h"
2106e827ccSJim Ingham #include "lldb/Target/Target.h"
225023257fSZachary Turner #include "lldb/Utility/ConvertEnum.h"
2330fdc8d8SChris Lattner 
2430fdc8d8SChris Lattner using namespace lldb;
2530fdc8d8SChris Lattner using namespace lldb_private;
2630fdc8d8SChris Lattner 
2730fdc8d8SChris Lattner //----------------------------------------------------------------------
2830fdc8d8SChris Lattner // ThreadPlan constructor
2930fdc8d8SChris Lattner //----------------------------------------------------------------------
30b01e742aSJim Ingham ThreadPlan::ThreadPlan(ThreadPlanKind kind, const char *name, Thread &thread, Vote stop_vote, Vote run_vote) :
3130fdc8d8SChris Lattner     m_thread (thread),
3230fdc8d8SChris Lattner     m_stop_vote (stop_vote),
3330fdc8d8SChris Lattner     m_run_vote (run_vote),
341ee0d4f7SBenjamin Kramer     m_kind (kind),
351ee0d4f7SBenjamin Kramer     m_name (name),
361ee0d4f7SBenjamin Kramer     m_plan_complete_mutex (Mutex::eMutexTypeRecursive),
37221d51cfSJim Ingham     m_cached_plan_explains_stop (eLazyBoolCalculate),
381ee0d4f7SBenjamin Kramer     m_plan_complete (false),
391ee0d4f7SBenjamin Kramer     m_plan_private (false),
4064e7ead1SJim Ingham     m_okay_to_discard (true),
41fbbfe6ecSJim Ingham     m_is_master_plan (false),
42fbbfe6ecSJim Ingham     m_plan_succeeded(true)
4330fdc8d8SChris Lattner {
4430fdc8d8SChris Lattner     SetID (GetNextID());
4530fdc8d8SChris Lattner }
4630fdc8d8SChris Lattner 
4730fdc8d8SChris Lattner //----------------------------------------------------------------------
4830fdc8d8SChris Lattner // Destructor
4930fdc8d8SChris Lattner //----------------------------------------------------------------------
50*e65b2cf2SEugene Zelenko ThreadPlan::~ThreadPlan() = default;
5130fdc8d8SChris Lattner 
5230fdc8d8SChris Lattner bool
53221d51cfSJim Ingham ThreadPlan::PlanExplainsStop (Event *event_ptr)
54221d51cfSJim Ingham {
55221d51cfSJim Ingham     if (m_cached_plan_explains_stop == eLazyBoolCalculate)
56221d51cfSJim Ingham     {
57221d51cfSJim Ingham         bool actual_value = DoPlanExplainsStop(event_ptr);
58221d51cfSJim Ingham         m_cached_plan_explains_stop = actual_value ? eLazyBoolYes : eLazyBoolNo;
59221d51cfSJim Ingham         return actual_value;
60221d51cfSJim Ingham     }
61221d51cfSJim Ingham     else
62221d51cfSJim Ingham     {
63221d51cfSJim Ingham         return m_cached_plan_explains_stop == eLazyBoolYes;
64221d51cfSJim Ingham     }
65221d51cfSJim Ingham }
66221d51cfSJim Ingham 
67221d51cfSJim Ingham bool
6830fdc8d8SChris Lattner ThreadPlan::IsPlanComplete ()
6930fdc8d8SChris Lattner {
70b132097bSGreg Clayton     Mutex::Locker locker(m_plan_complete_mutex);
7130fdc8d8SChris Lattner     return m_plan_complete;
7230fdc8d8SChris Lattner }
7330fdc8d8SChris Lattner 
7430fdc8d8SChris Lattner void
75fbbfe6ecSJim Ingham ThreadPlan::SetPlanComplete (bool success)
7630fdc8d8SChris Lattner {
77b132097bSGreg Clayton     Mutex::Locker locker(m_plan_complete_mutex);
7830fdc8d8SChris Lattner     m_plan_complete = true;
79fbbfe6ecSJim Ingham     m_plan_succeeded = success;
8030fdc8d8SChris Lattner }
8130fdc8d8SChris Lattner 
8230fdc8d8SChris Lattner bool
8330fdc8d8SChris Lattner ThreadPlan::MischiefManaged ()
8430fdc8d8SChris Lattner {
85b132097bSGreg Clayton     Mutex::Locker locker(m_plan_complete_mutex);
8618de2fdcSJim Ingham     // Mark the plan is complete, but don't override the success flag.
8730fdc8d8SChris Lattner     m_plan_complete = true;
8830fdc8d8SChris Lattner     return true;
8930fdc8d8SChris Lattner }
9030fdc8d8SChris Lattner 
9130fdc8d8SChris Lattner Vote
9230fdc8d8SChris Lattner ThreadPlan::ShouldReportStop (Event *event_ptr)
9330fdc8d8SChris Lattner {
945160ce5cSGreg Clayton     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
952cad65a5SGreg Clayton 
9630fdc8d8SChris Lattner     if (m_stop_vote == eVoteNoOpinion)
9730fdc8d8SChris Lattner     {
9830fdc8d8SChris Lattner         ThreadPlan *prev_plan = GetPreviousPlan ();
9930fdc8d8SChris Lattner         if (prev_plan)
1002cad65a5SGreg Clayton         {
1012cad65a5SGreg Clayton             Vote prev_vote = prev_plan->ShouldReportStop (event_ptr);
1022cad65a5SGreg Clayton             if (log)
103b5c0d1ccSJim Ingham                 log->Printf ("ThreadPlan::ShouldReportStop() returning previous thread plan vote: %s",
104b5c0d1ccSJim Ingham                              GetVoteAsCString (prev_vote));
1052cad65a5SGreg Clayton             return prev_vote;
10630fdc8d8SChris Lattner         }
1072cad65a5SGreg Clayton     }
1082cad65a5SGreg Clayton     if (log)
1091346f7e0SGreg Clayton         log->Printf ("ThreadPlan::ShouldReportStop() returning vote: %s", GetVoteAsCString (m_stop_vote));
11030fdc8d8SChris Lattner     return m_stop_vote;
11130fdc8d8SChris Lattner }
11230fdc8d8SChris Lattner 
11330fdc8d8SChris Lattner Vote
11430fdc8d8SChris Lattner ThreadPlan::ShouldReportRun (Event *event_ptr)
11530fdc8d8SChris Lattner {
11630fdc8d8SChris Lattner     if (m_run_vote == eVoteNoOpinion)
11730fdc8d8SChris Lattner     {
11830fdc8d8SChris Lattner         ThreadPlan *prev_plan = GetPreviousPlan ();
11930fdc8d8SChris Lattner         if (prev_plan)
12030fdc8d8SChris Lattner             return prev_plan->ShouldReportRun (event_ptr);
12130fdc8d8SChris Lattner     }
12230fdc8d8SChris Lattner     return m_run_vote;
12330fdc8d8SChris Lattner }
12430fdc8d8SChris Lattner 
12530fdc8d8SChris Lattner bool
12630fdc8d8SChris Lattner ThreadPlan::StopOthers ()
12730fdc8d8SChris Lattner {
12830fdc8d8SChris Lattner     ThreadPlan *prev_plan;
12930fdc8d8SChris Lattner     prev_plan = GetPreviousPlan ();
130*e65b2cf2SEugene Zelenko     return (prev_plan == nullptr) ? false : prev_plan->StopOthers();
13130fdc8d8SChris Lattner }
13230fdc8d8SChris Lattner 
133f48169bbSJim Ingham void
134f48169bbSJim Ingham ThreadPlan::SetStopOthers (bool new_value)
135f48169bbSJim Ingham {
136f48169bbSJim Ingham 	// SetStopOthers doesn't work up the hierarchy.  You have to set the
137f48169bbSJim Ingham     // explicit ThreadPlan you want to affect.
138f48169bbSJim Ingham }
139f48169bbSJim Ingham 
14030fdc8d8SChris Lattner bool
14130fdc8d8SChris Lattner ThreadPlan::WillResume (StateType resume_state, bool current_plan)
14230fdc8d8SChris Lattner {
143221d51cfSJim Ingham     m_cached_plan_explains_stop = eLazyBoolCalculate;
144221d51cfSJim Ingham 
14530fdc8d8SChris Lattner     if (current_plan)
14630fdc8d8SChris Lattner     {
1475160ce5cSGreg Clayton         Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
14830fdc8d8SChris Lattner 
14930fdc8d8SChris Lattner         if (log)
1502cad65a5SGreg Clayton         {
1515ccbd294SGreg Clayton             RegisterContext *reg_ctx = m_thread.GetRegisterContext().get();
152ff1b5c42SEd Maste             assert (reg_ctx);
1532cad65a5SGreg Clayton             addr_t pc = reg_ctx->GetPC();
1542cad65a5SGreg Clayton             addr_t sp = reg_ctx->GetSP();
1552cad65a5SGreg Clayton             addr_t fp = reg_ctx->GetFP();
156dee1bc98SJim Ingham             log->Printf("%s Thread #%u (0x%p): tid = 0x%4.4" PRIx64 ", pc = 0x%8.8" PRIx64 ", sp = 0x%8.8" PRIx64 ", fp = 0x%8.8" PRIx64 ", "
157b5c0d1ccSJim Ingham                         "plan = '%s', state = %s, stop others = %d",
158324a1036SSaleem Abdulrasool                         __FUNCTION__, m_thread.GetIndexID(),
159324a1036SSaleem Abdulrasool                         static_cast<void*>(&m_thread), m_thread.GetID(),
160324a1036SSaleem Abdulrasool                         static_cast<uint64_t>(pc), static_cast<uint64_t>(sp),
161324a1036SSaleem Abdulrasool                         static_cast<uint64_t>(fp), m_name.c_str(),
162324a1036SSaleem Abdulrasool                         StateAsCString(resume_state), StopOthers());
1632cad65a5SGreg Clayton         }
16430fdc8d8SChris Lattner     }
165221d51cfSJim Ingham     return DoWillResume (resume_state, current_plan);
16630fdc8d8SChris Lattner }
16730fdc8d8SChris Lattner 
16830fdc8d8SChris Lattner lldb::user_id_t
16930fdc8d8SChris Lattner ThreadPlan::GetNextID()
17030fdc8d8SChris Lattner {
17130fdc8d8SChris Lattner     static uint32_t g_nextPlanID = 0;
17230fdc8d8SChris Lattner     return ++g_nextPlanID;
17330fdc8d8SChris Lattner }
17430fdc8d8SChris Lattner 
17530fdc8d8SChris Lattner void
17630fdc8d8SChris Lattner ThreadPlan::DidPush()
17730fdc8d8SChris Lattner {
17830fdc8d8SChris Lattner }
17930fdc8d8SChris Lattner 
18030fdc8d8SChris Lattner void
18130fdc8d8SChris Lattner ThreadPlan::WillPop()
18230fdc8d8SChris Lattner {
18330fdc8d8SChris Lattner }
18430fdc8d8SChris Lattner 
18530fdc8d8SChris Lattner bool
18630fdc8d8SChris Lattner ThreadPlan::OkayToDiscard()
18730fdc8d8SChris Lattner {
188*e65b2cf2SEugene Zelenko     return IsMasterPlan() ? m_okay_to_discard : true;
18930fdc8d8SChris Lattner }
19030fdc8d8SChris Lattner 
19106e827ccSJim Ingham lldb::StateType
19206e827ccSJim Ingham ThreadPlan::RunState ()
19306e827ccSJim Ingham {
19406e827ccSJim Ingham     if (m_tracer_sp && m_tracer_sp->TracingEnabled() && m_tracer_sp->SingleStepEnabled())
19506e827ccSJim Ingham         return eStateStepping;
19606e827ccSJim Ingham     else
19706e827ccSJim Ingham         return GetPlanRunState();
19806e827ccSJim Ingham }
1996e10f149SGreg Clayton 
2009b03fa0cSJim Ingham bool
2019b03fa0cSJim Ingham ThreadPlan::IsUsuallyUnexplainedStopReason(lldb::StopReason reason)
2029b03fa0cSJim Ingham {
2039b03fa0cSJim Ingham     switch (reason)
2049b03fa0cSJim Ingham     {
2059b03fa0cSJim Ingham         case eStopReasonWatchpoint:
2069b03fa0cSJim Ingham         case eStopReasonSignal:
2079b03fa0cSJim Ingham         case eStopReasonException:
2089b03fa0cSJim Ingham         case eStopReasonExec:
2099b03fa0cSJim Ingham         case eStopReasonThreadExiting:
2109b03fa0cSJim Ingham         case eStopReasonInstrumentation:
2119b03fa0cSJim Ingham             return true;
2129b03fa0cSJim Ingham         default:
2139b03fa0cSJim Ingham             return false;
2149b03fa0cSJim Ingham     }
2159b03fa0cSJim Ingham }
2169b03fa0cSJim Ingham 
2176e10f149SGreg Clayton //----------------------------------------------------------------------
2186e10f149SGreg Clayton // ThreadPlanNull
2196e10f149SGreg Clayton //----------------------------------------------------------------------
2206e10f149SGreg Clayton 
2216e10f149SGreg Clayton ThreadPlanNull::ThreadPlanNull (Thread &thread) :
2226e10f149SGreg Clayton     ThreadPlan (ThreadPlan::eKindNull,
2236e10f149SGreg Clayton                 "Null Thread Plan",
2246e10f149SGreg Clayton                 thread,
2256e10f149SGreg Clayton                 eVoteNoOpinion,
2266e10f149SGreg Clayton                 eVoteNoOpinion)
2276e10f149SGreg Clayton {
2286e10f149SGreg Clayton }
2296e10f149SGreg Clayton 
230*e65b2cf2SEugene Zelenko ThreadPlanNull::~ThreadPlanNull() = default;
2316e10f149SGreg Clayton 
2326e10f149SGreg Clayton void
2336e10f149SGreg Clayton ThreadPlanNull::GetDescription (Stream *s,
2346e10f149SGreg Clayton                                 lldb::DescriptionLevel level)
2356e10f149SGreg Clayton {
2366e10f149SGreg Clayton     s->PutCString("Null thread plan - thread has been destroyed.");
2376e10f149SGreg Clayton }
2386e10f149SGreg Clayton 
2396e10f149SGreg Clayton bool
2406e10f149SGreg Clayton ThreadPlanNull::ValidatePlan (Stream *error)
2416e10f149SGreg Clayton {
2426e10f149SGreg Clayton #ifdef LLDB_CONFIGURATION_DEBUG
24389c862f2SMichael Sartain     fprintf(stderr, "error: %s called on thread that has been destroyed (tid = 0x%" PRIx64 ", ptid = 0x%" PRIx64 ")",
2446e10f149SGreg Clayton             __PRETTY_FUNCTION__,
2456e10f149SGreg Clayton             m_thread.GetID(),
2466e10f149SGreg Clayton             m_thread.GetProtocolID());
2476e10f149SGreg Clayton #else
2486e10f149SGreg Clayton     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD));
2496e10f149SGreg Clayton     if (log)
25089c862f2SMichael Sartain         log->Error("%s called on thread that has been destroyed (tid = 0x%" PRIx64 ", ptid = 0x%" PRIx64 ")",
2516e10f149SGreg Clayton                     __PRETTY_FUNCTION__,
2526e10f149SGreg Clayton                     m_thread.GetID(),
2536e10f149SGreg Clayton                     m_thread.GetProtocolID());
2546e10f149SGreg Clayton #endif
2556e10f149SGreg Clayton     return true;
2566e10f149SGreg Clayton }
2576e10f149SGreg Clayton 
2586e10f149SGreg Clayton bool
2596e10f149SGreg Clayton ThreadPlanNull::ShouldStop (Event *event_ptr)
2606e10f149SGreg Clayton {
2616e10f149SGreg Clayton #ifdef LLDB_CONFIGURATION_DEBUG
26289c862f2SMichael Sartain     fprintf(stderr, "error: %s called on thread that has been destroyed (tid = 0x%" PRIx64 ", ptid = 0x%" PRIx64 ")",
2636e10f149SGreg Clayton             __PRETTY_FUNCTION__,
2646e10f149SGreg Clayton             m_thread.GetID(),
2656e10f149SGreg Clayton             m_thread.GetProtocolID());
2666e10f149SGreg Clayton #else
2676e10f149SGreg Clayton     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD));
2686e10f149SGreg Clayton     if (log)
26989c862f2SMichael Sartain         log->Error("%s called on thread that has been destroyed (tid = 0x%" PRIx64 ", ptid = 0x%" PRIx64 ")",
2706e10f149SGreg Clayton                     __PRETTY_FUNCTION__,
2716e10f149SGreg Clayton                     m_thread.GetID(),
2726e10f149SGreg Clayton                     m_thread.GetProtocolID());
2736e10f149SGreg Clayton #endif
2746e10f149SGreg Clayton     return true;
2756e10f149SGreg Clayton }
2766e10f149SGreg Clayton 
2776e10f149SGreg Clayton bool
2786e10f149SGreg Clayton ThreadPlanNull::WillStop ()
2796e10f149SGreg Clayton {
2806e10f149SGreg Clayton #ifdef LLDB_CONFIGURATION_DEBUG
28189c862f2SMichael Sartain     fprintf(stderr, "error: %s called on thread that has been destroyed (tid = 0x%" PRIx64 ", ptid = 0x%" PRIx64 ")",
2826e10f149SGreg Clayton             __PRETTY_FUNCTION__,
2836e10f149SGreg Clayton             m_thread.GetID(),
2846e10f149SGreg Clayton             m_thread.GetProtocolID());
2856e10f149SGreg Clayton #else
2866e10f149SGreg Clayton     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD));
2876e10f149SGreg Clayton     if (log)
28889c862f2SMichael Sartain         log->Error("%s called on thread that has been destroyed (tid = 0x%" PRIx64 ", ptid = 0x%" PRIx64 ")",
2896e10f149SGreg Clayton                     __PRETTY_FUNCTION__,
2906e10f149SGreg Clayton                     m_thread.GetID(),
2916e10f149SGreg Clayton                     m_thread.GetProtocolID());
2926e10f149SGreg Clayton #endif
2936e10f149SGreg Clayton     return true;
2946e10f149SGreg Clayton }
2956e10f149SGreg Clayton 
2966e10f149SGreg Clayton bool
2976e10f149SGreg Clayton ThreadPlanNull::DoPlanExplainsStop (Event *event_ptr)
2986e10f149SGreg Clayton {
2996e10f149SGreg Clayton #ifdef LLDB_CONFIGURATION_DEBUG
30089c862f2SMichael Sartain     fprintf(stderr, "error: %s called on thread that has been destroyed (tid = 0x%" PRIx64 ", ptid = 0x%" PRIx64 ")",
3016e10f149SGreg Clayton             __PRETTY_FUNCTION__,
3026e10f149SGreg Clayton             m_thread.GetID(),
3036e10f149SGreg Clayton             m_thread.GetProtocolID());
3046e10f149SGreg Clayton #else
3056e10f149SGreg Clayton     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD));
3066e10f149SGreg Clayton     if (log)
30789c862f2SMichael Sartain         log->Error("%s called on thread that has been destroyed (tid = 0x%" PRIx64 ", ptid = 0x%" PRIx64 ")",
3086e10f149SGreg Clayton                    __PRETTY_FUNCTION__,
3096e10f149SGreg Clayton                    m_thread.GetID(),
3106e10f149SGreg Clayton                    m_thread.GetProtocolID());
3116e10f149SGreg Clayton #endif
3126e10f149SGreg Clayton     return true;
3136e10f149SGreg Clayton }
3146e10f149SGreg Clayton 
3156e10f149SGreg Clayton // The null plan is never done.
3166e10f149SGreg Clayton bool
3176e10f149SGreg Clayton ThreadPlanNull::MischiefManaged ()
3186e10f149SGreg Clayton {
3196e10f149SGreg Clayton     // The null plan is never done.
3206e10f149SGreg Clayton #ifdef LLDB_CONFIGURATION_DEBUG
32189c862f2SMichael Sartain     fprintf(stderr, "error: %s called on thread that has been destroyed (tid = 0x%" PRIx64 ", ptid = 0x%" PRIx64 ")",
3226e10f149SGreg Clayton             __PRETTY_FUNCTION__,
3236e10f149SGreg Clayton             m_thread.GetID(),
3246e10f149SGreg Clayton             m_thread.GetProtocolID());
3256e10f149SGreg Clayton #else
3266e10f149SGreg Clayton     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD));
3276e10f149SGreg Clayton     if (log)
32889c862f2SMichael Sartain         log->Error("%s called on thread that has been destroyed (tid = 0x%" PRIx64 ", ptid = 0x%" PRIx64 ")",
3296e10f149SGreg Clayton                    __PRETTY_FUNCTION__,
3306e10f149SGreg Clayton                    m_thread.GetID(),
3316e10f149SGreg Clayton                    m_thread.GetProtocolID());
3326e10f149SGreg Clayton #endif
3336e10f149SGreg Clayton     return false;
3346e10f149SGreg Clayton }
3356e10f149SGreg Clayton 
3366e10f149SGreg Clayton lldb::StateType
3376e10f149SGreg Clayton ThreadPlanNull::GetPlanRunState ()
3386e10f149SGreg Clayton {
3396e10f149SGreg Clayton     // Not sure what to return here.  This is a dead thread.
3406e10f149SGreg Clayton #ifdef LLDB_CONFIGURATION_DEBUG
34189c862f2SMichael Sartain     fprintf(stderr, "error: %s called on thread that has been destroyed (tid = 0x%" PRIx64 ", ptid = 0x%" PRIx64 ")",
3426e10f149SGreg Clayton             __PRETTY_FUNCTION__,
3436e10f149SGreg Clayton             m_thread.GetID(),
3446e10f149SGreg Clayton             m_thread.GetProtocolID());
3456e10f149SGreg Clayton #else
3466e10f149SGreg Clayton     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD));
3476e10f149SGreg Clayton     if (log)
34889c862f2SMichael Sartain         log->Error("%s called on thread that has been destroyed (tid = 0x%" PRIx64 ", ptid = 0x%" PRIx64 ")",
3496e10f149SGreg Clayton                    __PRETTY_FUNCTION__,
3506e10f149SGreg Clayton                    m_thread.GetID(),
3516e10f149SGreg Clayton                    m_thread.GetProtocolID());
3526e10f149SGreg Clayton #endif
3536e10f149SGreg Clayton     return eStateRunning;
3546e10f149SGreg Clayton }
355