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 
1093a64300SDaniel Malea #include "lldb/lldb-python.h"
1193a64300SDaniel Malea 
1230fdc8d8SChris Lattner #include "lldb/Target/ThreadPlan.h"
1330fdc8d8SChris Lattner 
1430fdc8d8SChris Lattner // C Includes
1530fdc8d8SChris Lattner // C++ Includes
1630fdc8d8SChris Lattner // Other libraries and framework includes
1730fdc8d8SChris Lattner // Project includes
1806e827ccSJim Ingham #include "lldb/Core/Debugger.h"
1930fdc8d8SChris Lattner #include "lldb/Core/Log.h"
2030fdc8d8SChris Lattner #include "lldb/Core/State.h"
212cad65a5SGreg Clayton #include "lldb/Target/RegisterContext.h"
222cad65a5SGreg Clayton #include "lldb/Target/Thread.h"
2306e827ccSJim Ingham #include "lldb/Target/Process.h"
2406e827ccSJim Ingham #include "lldb/Target/Target.h"
25*5023257fSZachary Turner #include "lldb/Utility/ConvertEnum.h"
2630fdc8d8SChris Lattner 
2730fdc8d8SChris Lattner using namespace lldb;
2830fdc8d8SChris Lattner using namespace lldb_private;
2930fdc8d8SChris Lattner 
3030fdc8d8SChris Lattner //----------------------------------------------------------------------
3130fdc8d8SChris Lattner // ThreadPlan constructor
3230fdc8d8SChris Lattner //----------------------------------------------------------------------
33b01e742aSJim Ingham ThreadPlan::ThreadPlan(ThreadPlanKind kind, const char *name, Thread &thread, Vote stop_vote, Vote run_vote) :
3430fdc8d8SChris Lattner     m_thread (thread),
3530fdc8d8SChris Lattner     m_stop_vote (stop_vote),
3630fdc8d8SChris Lattner     m_run_vote (run_vote),
371ee0d4f7SBenjamin Kramer     m_kind (kind),
381ee0d4f7SBenjamin Kramer     m_name (name),
391ee0d4f7SBenjamin Kramer     m_plan_complete_mutex (Mutex::eMutexTypeRecursive),
40221d51cfSJim Ingham     m_cached_plan_explains_stop (eLazyBoolCalculate),
411ee0d4f7SBenjamin Kramer     m_plan_complete (false),
421ee0d4f7SBenjamin Kramer     m_plan_private (false),
4364e7ead1SJim Ingham     m_okay_to_discard (true),
44fbbfe6ecSJim Ingham     m_is_master_plan (false),
45fbbfe6ecSJim Ingham     m_plan_succeeded(true)
4630fdc8d8SChris Lattner {
4730fdc8d8SChris Lattner     SetID (GetNextID());
4830fdc8d8SChris Lattner }
4930fdc8d8SChris Lattner 
5030fdc8d8SChris Lattner //----------------------------------------------------------------------
5130fdc8d8SChris Lattner // Destructor
5230fdc8d8SChris Lattner //----------------------------------------------------------------------
5330fdc8d8SChris Lattner ThreadPlan::~ThreadPlan()
5430fdc8d8SChris Lattner {
5530fdc8d8SChris Lattner }
5630fdc8d8SChris Lattner 
5730fdc8d8SChris Lattner bool
58221d51cfSJim Ingham ThreadPlan::PlanExplainsStop (Event *event_ptr)
59221d51cfSJim Ingham {
60221d51cfSJim Ingham     if (m_cached_plan_explains_stop == eLazyBoolCalculate)
61221d51cfSJim Ingham     {
62221d51cfSJim Ingham         bool actual_value = DoPlanExplainsStop(event_ptr);
63221d51cfSJim Ingham         m_cached_plan_explains_stop = actual_value ? eLazyBoolYes : eLazyBoolNo;
64221d51cfSJim Ingham         return actual_value;
65221d51cfSJim Ingham     }
66221d51cfSJim Ingham     else
67221d51cfSJim Ingham     {
68221d51cfSJim Ingham         return m_cached_plan_explains_stop == eLazyBoolYes;
69221d51cfSJim Ingham     }
70221d51cfSJim Ingham }
71221d51cfSJim Ingham 
72221d51cfSJim Ingham bool
7330fdc8d8SChris Lattner ThreadPlan::IsPlanComplete ()
7430fdc8d8SChris Lattner {
75b132097bSGreg Clayton     Mutex::Locker locker(m_plan_complete_mutex);
7630fdc8d8SChris Lattner     return m_plan_complete;
7730fdc8d8SChris Lattner }
7830fdc8d8SChris Lattner 
7930fdc8d8SChris Lattner void
80fbbfe6ecSJim Ingham ThreadPlan::SetPlanComplete (bool success)
8130fdc8d8SChris Lattner {
82b132097bSGreg Clayton     Mutex::Locker locker(m_plan_complete_mutex);
8330fdc8d8SChris Lattner     m_plan_complete = true;
84fbbfe6ecSJim Ingham     m_plan_succeeded = success;
8530fdc8d8SChris Lattner }
8630fdc8d8SChris Lattner 
8730fdc8d8SChris Lattner bool
8830fdc8d8SChris Lattner ThreadPlan::MischiefManaged ()
8930fdc8d8SChris Lattner {
90b132097bSGreg Clayton     Mutex::Locker locker(m_plan_complete_mutex);
9118de2fdcSJim Ingham     // Mark the plan is complete, but don't override the success flag.
9230fdc8d8SChris Lattner     m_plan_complete = true;
9330fdc8d8SChris Lattner     return true;
9430fdc8d8SChris Lattner }
9530fdc8d8SChris Lattner 
9630fdc8d8SChris Lattner Vote
9730fdc8d8SChris Lattner ThreadPlan::ShouldReportStop (Event *event_ptr)
9830fdc8d8SChris Lattner {
995160ce5cSGreg Clayton     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
1002cad65a5SGreg Clayton 
10130fdc8d8SChris Lattner     if (m_stop_vote == eVoteNoOpinion)
10230fdc8d8SChris Lattner     {
10330fdc8d8SChris Lattner         ThreadPlan *prev_plan = GetPreviousPlan ();
10430fdc8d8SChris Lattner         if (prev_plan)
1052cad65a5SGreg Clayton         {
1062cad65a5SGreg Clayton             Vote prev_vote = prev_plan->ShouldReportStop (event_ptr);
1072cad65a5SGreg Clayton             if (log)
108b5c0d1ccSJim Ingham                 log->Printf ("ThreadPlan::ShouldReportStop() returning previous thread plan vote: %s",
109b5c0d1ccSJim Ingham                              GetVoteAsCString (prev_vote));
1102cad65a5SGreg Clayton             return prev_vote;
11130fdc8d8SChris Lattner         }
1122cad65a5SGreg Clayton     }
1132cad65a5SGreg Clayton     if (log)
1141346f7e0SGreg Clayton         log->Printf ("ThreadPlan::ShouldReportStop() returning vote: %s", GetVoteAsCString (m_stop_vote));
11530fdc8d8SChris Lattner     return m_stop_vote;
11630fdc8d8SChris Lattner }
11730fdc8d8SChris Lattner 
11830fdc8d8SChris Lattner Vote
11930fdc8d8SChris Lattner ThreadPlan::ShouldReportRun (Event *event_ptr)
12030fdc8d8SChris Lattner {
12130fdc8d8SChris Lattner     if (m_run_vote == eVoteNoOpinion)
12230fdc8d8SChris Lattner     {
12330fdc8d8SChris Lattner         ThreadPlan *prev_plan = GetPreviousPlan ();
12430fdc8d8SChris Lattner         if (prev_plan)
12530fdc8d8SChris Lattner             return prev_plan->ShouldReportRun (event_ptr);
12630fdc8d8SChris Lattner     }
12730fdc8d8SChris Lattner     return m_run_vote;
12830fdc8d8SChris Lattner }
12930fdc8d8SChris Lattner 
13030fdc8d8SChris Lattner bool
13130fdc8d8SChris Lattner ThreadPlan::StopOthers ()
13230fdc8d8SChris Lattner {
13330fdc8d8SChris Lattner     ThreadPlan *prev_plan;
13430fdc8d8SChris Lattner     prev_plan = GetPreviousPlan ();
13530fdc8d8SChris Lattner     if (prev_plan == NULL)
13630fdc8d8SChris Lattner         return false;
13730fdc8d8SChris Lattner     else
13830fdc8d8SChris Lattner         return prev_plan->StopOthers();
13930fdc8d8SChris Lattner }
14030fdc8d8SChris Lattner 
141f48169bbSJim Ingham void
142f48169bbSJim Ingham ThreadPlan::SetStopOthers (bool new_value)
143f48169bbSJim Ingham {
144f48169bbSJim Ingham 	// SetStopOthers doesn't work up the hierarchy.  You have to set the
145f48169bbSJim Ingham     // explicit ThreadPlan you want to affect.
146f48169bbSJim Ingham }
147f48169bbSJim Ingham 
14830fdc8d8SChris Lattner bool
14930fdc8d8SChris Lattner ThreadPlan::WillResume (StateType resume_state, bool current_plan)
15030fdc8d8SChris Lattner {
151221d51cfSJim Ingham     m_cached_plan_explains_stop = eLazyBoolCalculate;
152221d51cfSJim Ingham 
15330fdc8d8SChris Lattner     if (current_plan)
15430fdc8d8SChris Lattner     {
1555160ce5cSGreg Clayton         Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
15630fdc8d8SChris Lattner 
15730fdc8d8SChris Lattner         if (log)
1582cad65a5SGreg Clayton         {
1595ccbd294SGreg Clayton             RegisterContext *reg_ctx = m_thread.GetRegisterContext().get();
160ff1b5c42SEd Maste             assert (reg_ctx);
1612cad65a5SGreg Clayton             addr_t pc = reg_ctx->GetPC();
1622cad65a5SGreg Clayton             addr_t sp = reg_ctx->GetSP();
1632cad65a5SGreg Clayton             addr_t fp = reg_ctx->GetFP();
164dee1bc98SJim 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 ", "
165b5c0d1ccSJim Ingham                         "plan = '%s', state = %s, stop others = %d",
166324a1036SSaleem Abdulrasool                         __FUNCTION__, m_thread.GetIndexID(),
167324a1036SSaleem Abdulrasool                         static_cast<void*>(&m_thread), m_thread.GetID(),
168324a1036SSaleem Abdulrasool                         static_cast<uint64_t>(pc), static_cast<uint64_t>(sp),
169324a1036SSaleem Abdulrasool                         static_cast<uint64_t>(fp), m_name.c_str(),
170324a1036SSaleem Abdulrasool                         StateAsCString(resume_state), StopOthers());
1712cad65a5SGreg Clayton         }
17230fdc8d8SChris Lattner     }
173221d51cfSJim Ingham     return DoWillResume (resume_state, current_plan);
17430fdc8d8SChris Lattner }
17530fdc8d8SChris Lattner 
17630fdc8d8SChris Lattner lldb::user_id_t
17730fdc8d8SChris Lattner ThreadPlan::GetNextID()
17830fdc8d8SChris Lattner {
17930fdc8d8SChris Lattner     static uint32_t g_nextPlanID = 0;
18030fdc8d8SChris Lattner     return ++g_nextPlanID;
18130fdc8d8SChris Lattner }
18230fdc8d8SChris Lattner 
18330fdc8d8SChris Lattner void
18430fdc8d8SChris Lattner ThreadPlan::DidPush()
18530fdc8d8SChris Lattner {
18630fdc8d8SChris Lattner }
18730fdc8d8SChris Lattner 
18830fdc8d8SChris Lattner void
18930fdc8d8SChris Lattner ThreadPlan::WillPop()
19030fdc8d8SChris Lattner {
19130fdc8d8SChris Lattner }
19230fdc8d8SChris Lattner 
19330fdc8d8SChris Lattner bool
19430fdc8d8SChris Lattner ThreadPlan::OkayToDiscard()
19530fdc8d8SChris Lattner {
19630fdc8d8SChris Lattner     if (!IsMasterPlan())
19730fdc8d8SChris Lattner         return true;
19830fdc8d8SChris Lattner     else
19930fdc8d8SChris Lattner         return m_okay_to_discard;
20030fdc8d8SChris Lattner }
20130fdc8d8SChris Lattner 
20206e827ccSJim Ingham lldb::StateType
20306e827ccSJim Ingham ThreadPlan::RunState ()
20406e827ccSJim Ingham {
20506e827ccSJim Ingham     if (m_tracer_sp && m_tracer_sp->TracingEnabled() && m_tracer_sp->SingleStepEnabled())
20606e827ccSJim Ingham         return eStateStepping;
20706e827ccSJim Ingham     else
20806e827ccSJim Ingham         return GetPlanRunState();
20906e827ccSJim Ingham }
2106e10f149SGreg Clayton 
2116e10f149SGreg Clayton //----------------------------------------------------------------------
2126e10f149SGreg Clayton // ThreadPlanNull
2136e10f149SGreg Clayton //----------------------------------------------------------------------
2146e10f149SGreg Clayton 
2156e10f149SGreg Clayton ThreadPlanNull::ThreadPlanNull (Thread &thread) :
2166e10f149SGreg Clayton     ThreadPlan (ThreadPlan::eKindNull,
2176e10f149SGreg Clayton                 "Null Thread Plan",
2186e10f149SGreg Clayton                 thread,
2196e10f149SGreg Clayton                 eVoteNoOpinion,
2206e10f149SGreg Clayton                 eVoteNoOpinion)
2216e10f149SGreg Clayton {
2226e10f149SGreg Clayton }
2236e10f149SGreg Clayton 
2246e10f149SGreg Clayton ThreadPlanNull::~ThreadPlanNull ()
2256e10f149SGreg Clayton {
2266e10f149SGreg Clayton }
2276e10f149SGreg Clayton 
2286e10f149SGreg Clayton void
2296e10f149SGreg Clayton ThreadPlanNull::GetDescription (Stream *s,
2306e10f149SGreg Clayton                                 lldb::DescriptionLevel level)
2316e10f149SGreg Clayton {
2326e10f149SGreg Clayton     s->PutCString("Null thread plan - thread has been destroyed.");
2336e10f149SGreg Clayton }
2346e10f149SGreg Clayton 
2356e10f149SGreg Clayton bool
2366e10f149SGreg Clayton ThreadPlanNull::ValidatePlan (Stream *error)
2376e10f149SGreg Clayton {
2386e10f149SGreg Clayton #ifdef LLDB_CONFIGURATION_DEBUG
23989c862f2SMichael Sartain     fprintf(stderr, "error: %s called on thread that has been destroyed (tid = 0x%" PRIx64 ", ptid = 0x%" PRIx64 ")",
2406e10f149SGreg Clayton             __PRETTY_FUNCTION__,
2416e10f149SGreg Clayton             m_thread.GetID(),
2426e10f149SGreg Clayton             m_thread.GetProtocolID());
2436e10f149SGreg Clayton #else
2446e10f149SGreg Clayton     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD));
2456e10f149SGreg Clayton     if (log)
24689c862f2SMichael Sartain         log->Error("%s called on thread that has been destroyed (tid = 0x%" PRIx64 ", ptid = 0x%" PRIx64 ")",
2476e10f149SGreg Clayton                     __PRETTY_FUNCTION__,
2486e10f149SGreg Clayton                     m_thread.GetID(),
2496e10f149SGreg Clayton                     m_thread.GetProtocolID());
2506e10f149SGreg Clayton #endif
2516e10f149SGreg Clayton     return true;
2526e10f149SGreg Clayton }
2536e10f149SGreg Clayton 
2546e10f149SGreg Clayton bool
2556e10f149SGreg Clayton ThreadPlanNull::ShouldStop (Event *event_ptr)
2566e10f149SGreg Clayton {
2576e10f149SGreg Clayton #ifdef LLDB_CONFIGURATION_DEBUG
25889c862f2SMichael Sartain     fprintf(stderr, "error: %s called on thread that has been destroyed (tid = 0x%" PRIx64 ", ptid = 0x%" PRIx64 ")",
2596e10f149SGreg Clayton             __PRETTY_FUNCTION__,
2606e10f149SGreg Clayton             m_thread.GetID(),
2616e10f149SGreg Clayton             m_thread.GetProtocolID());
2626e10f149SGreg Clayton #else
2636e10f149SGreg Clayton     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD));
2646e10f149SGreg Clayton     if (log)
26589c862f2SMichael Sartain         log->Error("%s called on thread that has been destroyed (tid = 0x%" PRIx64 ", ptid = 0x%" PRIx64 ")",
2666e10f149SGreg Clayton                     __PRETTY_FUNCTION__,
2676e10f149SGreg Clayton                     m_thread.GetID(),
2686e10f149SGreg Clayton                     m_thread.GetProtocolID());
2696e10f149SGreg Clayton #endif
2706e10f149SGreg Clayton     return true;
2716e10f149SGreg Clayton }
2726e10f149SGreg Clayton 
2736e10f149SGreg Clayton bool
2746e10f149SGreg Clayton ThreadPlanNull::WillStop ()
2756e10f149SGreg Clayton {
2766e10f149SGreg Clayton #ifdef LLDB_CONFIGURATION_DEBUG
27789c862f2SMichael Sartain     fprintf(stderr, "error: %s called on thread that has been destroyed (tid = 0x%" PRIx64 ", ptid = 0x%" PRIx64 ")",
2786e10f149SGreg Clayton             __PRETTY_FUNCTION__,
2796e10f149SGreg Clayton             m_thread.GetID(),
2806e10f149SGreg Clayton             m_thread.GetProtocolID());
2816e10f149SGreg Clayton #else
2826e10f149SGreg Clayton     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD));
2836e10f149SGreg Clayton     if (log)
28489c862f2SMichael Sartain         log->Error("%s called on thread that has been destroyed (tid = 0x%" PRIx64 ", ptid = 0x%" PRIx64 ")",
2856e10f149SGreg Clayton                     __PRETTY_FUNCTION__,
2866e10f149SGreg Clayton                     m_thread.GetID(),
2876e10f149SGreg Clayton                     m_thread.GetProtocolID());
2886e10f149SGreg Clayton #endif
2896e10f149SGreg Clayton     return true;
2906e10f149SGreg Clayton }
2916e10f149SGreg Clayton 
2926e10f149SGreg Clayton bool
2936e10f149SGreg Clayton ThreadPlanNull::DoPlanExplainsStop (Event *event_ptr)
2946e10f149SGreg Clayton {
2956e10f149SGreg Clayton #ifdef LLDB_CONFIGURATION_DEBUG
29689c862f2SMichael Sartain     fprintf(stderr, "error: %s called on thread that has been destroyed (tid = 0x%" PRIx64 ", ptid = 0x%" PRIx64 ")",
2976e10f149SGreg Clayton             __PRETTY_FUNCTION__,
2986e10f149SGreg Clayton             m_thread.GetID(),
2996e10f149SGreg Clayton             m_thread.GetProtocolID());
3006e10f149SGreg Clayton #else
3016e10f149SGreg Clayton     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD));
3026e10f149SGreg Clayton     if (log)
30389c862f2SMichael Sartain         log->Error("%s called on thread that has been destroyed (tid = 0x%" PRIx64 ", ptid = 0x%" PRIx64 ")",
3046e10f149SGreg Clayton                    __PRETTY_FUNCTION__,
3056e10f149SGreg Clayton                    m_thread.GetID(),
3066e10f149SGreg Clayton                    m_thread.GetProtocolID());
3076e10f149SGreg Clayton #endif
3086e10f149SGreg Clayton     return true;
3096e10f149SGreg Clayton }
3106e10f149SGreg Clayton 
3116e10f149SGreg Clayton // The null plan is never done.
3126e10f149SGreg Clayton bool
3136e10f149SGreg Clayton ThreadPlanNull::MischiefManaged ()
3146e10f149SGreg Clayton {
3156e10f149SGreg Clayton     // The null plan is never done.
3166e10f149SGreg Clayton #ifdef LLDB_CONFIGURATION_DEBUG
31789c862f2SMichael Sartain     fprintf(stderr, "error: %s called on thread that has been destroyed (tid = 0x%" PRIx64 ", ptid = 0x%" PRIx64 ")",
3186e10f149SGreg Clayton             __PRETTY_FUNCTION__,
3196e10f149SGreg Clayton             m_thread.GetID(),
3206e10f149SGreg Clayton             m_thread.GetProtocolID());
3216e10f149SGreg Clayton #else
3226e10f149SGreg Clayton     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD));
3236e10f149SGreg Clayton     if (log)
32489c862f2SMichael Sartain         log->Error("%s called on thread that has been destroyed (tid = 0x%" PRIx64 ", ptid = 0x%" PRIx64 ")",
3256e10f149SGreg Clayton                    __PRETTY_FUNCTION__,
3266e10f149SGreg Clayton                    m_thread.GetID(),
3276e10f149SGreg Clayton                    m_thread.GetProtocolID());
3286e10f149SGreg Clayton #endif
3296e10f149SGreg Clayton     return false;
3306e10f149SGreg Clayton }
3316e10f149SGreg Clayton 
3326e10f149SGreg Clayton lldb::StateType
3336e10f149SGreg Clayton ThreadPlanNull::GetPlanRunState ()
3346e10f149SGreg Clayton {
3356e10f149SGreg Clayton     // Not sure what to return here.  This is a dead thread.
3366e10f149SGreg Clayton #ifdef LLDB_CONFIGURATION_DEBUG
33789c862f2SMichael Sartain     fprintf(stderr, "error: %s called on thread that has been destroyed (tid = 0x%" PRIx64 ", ptid = 0x%" PRIx64 ")",
3386e10f149SGreg Clayton             __PRETTY_FUNCTION__,
3396e10f149SGreg Clayton             m_thread.GetID(),
3406e10f149SGreg Clayton             m_thread.GetProtocolID());
3416e10f149SGreg Clayton #else
3426e10f149SGreg Clayton     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD));
3436e10f149SGreg Clayton     if (log)
34489c862f2SMichael Sartain         log->Error("%s called on thread that has been destroyed (tid = 0x%" PRIx64 ", ptid = 0x%" PRIx64 ")",
3456e10f149SGreg Clayton                    __PRETTY_FUNCTION__,
3466e10f149SGreg Clayton                    m_thread.GetID(),
3476e10f149SGreg Clayton                    m_thread.GetProtocolID());
3486e10f149SGreg Clayton #endif
3496e10f149SGreg Clayton     return eStateRunning;
3506e10f149SGreg Clayton }
351