1254721Semaste//===-- ThreadPlan.cpp ------------------------------------------*- C++ -*-===//
2254721Semaste//
3254721Semaste//                     The LLVM Compiler Infrastructure
4254721Semaste//
5254721Semaste// This file is distributed under the University of Illinois Open Source
6254721Semaste// License. See LICENSE.TXT for details.
7254721Semaste//
8254721Semaste//===----------------------------------------------------------------------===//
9254721Semaste
10254721Semaste#include "lldb/lldb-python.h"
11254721Semaste
12254721Semaste#include "lldb/Target/ThreadPlan.h"
13254721Semaste
14254721Semaste// C Includes
15254721Semaste// C++ Includes
16254721Semaste// Other libraries and framework includes
17254721Semaste// Project includes
18254721Semaste#include "lldb/Core/Debugger.h"
19254721Semaste#include "lldb/Core/Log.h"
20254721Semaste#include "lldb/Core/State.h"
21254721Semaste#include "lldb/Target/RegisterContext.h"
22254721Semaste#include "lldb/Target/Thread.h"
23254721Semaste#include "lldb/Target/Process.h"
24254721Semaste#include "lldb/Target/Target.h"
25254721Semaste
26254721Semasteusing namespace lldb;
27254721Semasteusing namespace lldb_private;
28254721Semaste
29254721Semaste//----------------------------------------------------------------------
30254721Semaste// ThreadPlan constructor
31254721Semaste//----------------------------------------------------------------------
32254721SemasteThreadPlan::ThreadPlan(ThreadPlanKind kind, const char *name, Thread &thread, Vote stop_vote, Vote run_vote) :
33254721Semaste    m_thread (thread),
34254721Semaste    m_stop_vote (stop_vote),
35254721Semaste    m_run_vote (run_vote),
36254721Semaste    m_kind (kind),
37254721Semaste    m_name (name),
38254721Semaste    m_plan_complete_mutex (Mutex::eMutexTypeRecursive),
39254721Semaste    m_cached_plan_explains_stop (eLazyBoolCalculate),
40254721Semaste    m_plan_complete (false),
41254721Semaste    m_plan_private (false),
42254721Semaste    m_okay_to_discard (true),
43254721Semaste    m_is_master_plan (false),
44254721Semaste    m_plan_succeeded(true)
45254721Semaste{
46254721Semaste    SetID (GetNextID());
47254721Semaste}
48254721Semaste
49254721Semaste//----------------------------------------------------------------------
50254721Semaste// Destructor
51254721Semaste//----------------------------------------------------------------------
52254721SemasteThreadPlan::~ThreadPlan()
53254721Semaste{
54254721Semaste}
55254721Semaste
56254721Semastebool
57254721SemasteThreadPlan::PlanExplainsStop (Event *event_ptr)
58254721Semaste{
59254721Semaste    if (m_cached_plan_explains_stop == eLazyBoolCalculate)
60254721Semaste    {
61254721Semaste        bool actual_value = DoPlanExplainsStop(event_ptr);
62254721Semaste        m_cached_plan_explains_stop = actual_value ? eLazyBoolYes : eLazyBoolNo;
63254721Semaste        return actual_value;
64254721Semaste    }
65254721Semaste    else
66254721Semaste    {
67254721Semaste        return m_cached_plan_explains_stop == eLazyBoolYes;
68254721Semaste    }
69254721Semaste}
70254721Semaste
71254721Semastebool
72254721SemasteThreadPlan::IsPlanComplete ()
73254721Semaste{
74254721Semaste    Mutex::Locker locker(m_plan_complete_mutex);
75254721Semaste    return m_plan_complete;
76254721Semaste}
77254721Semaste
78254721Semastevoid
79254721SemasteThreadPlan::SetPlanComplete (bool success)
80254721Semaste{
81254721Semaste    Mutex::Locker locker(m_plan_complete_mutex);
82254721Semaste    m_plan_complete = true;
83254721Semaste    m_plan_succeeded = success;
84254721Semaste}
85254721Semaste
86254721Semastebool
87254721SemasteThreadPlan::MischiefManaged ()
88254721Semaste{
89254721Semaste    Mutex::Locker locker(m_plan_complete_mutex);
90254721Semaste    // Mark the plan is complete, but don't override the success flag.
91254721Semaste    m_plan_complete = true;
92254721Semaste    return true;
93254721Semaste}
94254721Semaste
95254721SemasteVote
96254721SemasteThreadPlan::ShouldReportStop (Event *event_ptr)
97254721Semaste{
98254721Semaste    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
99254721Semaste
100254721Semaste    if (m_stop_vote == eVoteNoOpinion)
101254721Semaste    {
102254721Semaste        ThreadPlan *prev_plan = GetPreviousPlan ();
103254721Semaste        if (prev_plan)
104254721Semaste        {
105254721Semaste            Vote prev_vote = prev_plan->ShouldReportStop (event_ptr);
106254721Semaste            if (log)
107254721Semaste                log->Printf ("ThreadPlan::ShouldReportStop() returning previous thread plan vote: %s",
108254721Semaste                             GetVoteAsCString (prev_vote));
109254721Semaste            return prev_vote;
110254721Semaste        }
111254721Semaste    }
112254721Semaste    if (log)
113254721Semaste        log->Printf ("ThreadPlan::ShouldReportStop() returning vote: %s", GetVoteAsCString (m_stop_vote));
114254721Semaste    return m_stop_vote;
115254721Semaste}
116254721Semaste
117254721SemasteVote
118254721SemasteThreadPlan::ShouldReportRun (Event *event_ptr)
119254721Semaste{
120254721Semaste    if (m_run_vote == eVoteNoOpinion)
121254721Semaste    {
122254721Semaste        ThreadPlan *prev_plan = GetPreviousPlan ();
123254721Semaste        if (prev_plan)
124254721Semaste            return prev_plan->ShouldReportRun (event_ptr);
125254721Semaste    }
126254721Semaste    return m_run_vote;
127254721Semaste}
128254721Semaste
129254721Semastebool
130254721SemasteThreadPlan::StopOthers ()
131254721Semaste{
132254721Semaste    ThreadPlan *prev_plan;
133254721Semaste    prev_plan = GetPreviousPlan ();
134254721Semaste    if (prev_plan == NULL)
135254721Semaste        return false;
136254721Semaste    else
137254721Semaste        return prev_plan->StopOthers();
138254721Semaste}
139254721Semaste
140254721Semastevoid
141254721SemasteThreadPlan::SetStopOthers (bool new_value)
142254721Semaste{
143254721Semaste	// SetStopOthers doesn't work up the hierarchy.  You have to set the
144254721Semaste    // explicit ThreadPlan you want to affect.
145254721Semaste}
146254721Semaste
147254721Semastebool
148254721SemasteThreadPlan::WillResume (StateType resume_state, bool current_plan)
149254721Semaste{
150254721Semaste    m_cached_plan_explains_stop = eLazyBoolCalculate;
151254721Semaste
152254721Semaste    if (current_plan)
153254721Semaste    {
154254721Semaste        Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
155254721Semaste
156254721Semaste        if (log)
157254721Semaste        {
158254721Semaste            RegisterContext *reg_ctx = m_thread.GetRegisterContext().get();
159254721Semaste            addr_t pc = reg_ctx->GetPC();
160254721Semaste            addr_t sp = reg_ctx->GetSP();
161254721Semaste            addr_t fp = reg_ctx->GetFP();
162254721Semaste            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 ", "
163254721Semaste                        "plan = '%s', state = %s, stop others = %d",
164254721Semaste                        __FUNCTION__,
165254721Semaste                        m_thread.GetIndexID(),
166254721Semaste                        &m_thread,
167254721Semaste                        m_thread.GetID(),
168254721Semaste                        (uint64_t)pc,
169254721Semaste                        (uint64_t)sp,
170254721Semaste                        (uint64_t)fp,
171254721Semaste                        m_name.c_str(),
172254721Semaste                        StateAsCString(resume_state),
173254721Semaste                        StopOthers());
174254721Semaste        }
175254721Semaste    }
176254721Semaste    return DoWillResume (resume_state, current_plan);
177254721Semaste}
178254721Semaste
179254721Semastelldb::user_id_t
180254721SemasteThreadPlan::GetNextID()
181254721Semaste{
182254721Semaste    static uint32_t g_nextPlanID = 0;
183254721Semaste    return ++g_nextPlanID;
184254721Semaste}
185254721Semaste
186254721Semastevoid
187254721SemasteThreadPlan::DidPush()
188254721Semaste{
189254721Semaste}
190254721Semaste
191254721Semastevoid
192254721SemasteThreadPlan::WillPop()
193254721Semaste{
194254721Semaste}
195254721Semaste
196254721Semastebool
197254721SemasteThreadPlan::OkayToDiscard()
198254721Semaste{
199254721Semaste    if (!IsMasterPlan())
200254721Semaste        return true;
201254721Semaste    else
202254721Semaste        return m_okay_to_discard;
203254721Semaste}
204254721Semaste
205254721Semastelldb::StateType
206254721SemasteThreadPlan::RunState ()
207254721Semaste{
208254721Semaste    if (m_tracer_sp && m_tracer_sp->TracingEnabled() && m_tracer_sp->SingleStepEnabled())
209254721Semaste        return eStateStepping;
210254721Semaste    else
211254721Semaste        return GetPlanRunState();
212254721Semaste}
213254721Semaste
214254721Semaste//----------------------------------------------------------------------
215254721Semaste// ThreadPlanNull
216254721Semaste//----------------------------------------------------------------------
217254721Semaste
218254721SemasteThreadPlanNull::ThreadPlanNull (Thread &thread) :
219254721Semaste    ThreadPlan (ThreadPlan::eKindNull,
220254721Semaste                "Null Thread Plan",
221254721Semaste                thread,
222254721Semaste                eVoteNoOpinion,
223254721Semaste                eVoteNoOpinion)
224254721Semaste{
225254721Semaste}
226254721Semaste
227254721SemasteThreadPlanNull::~ThreadPlanNull ()
228254721Semaste{
229254721Semaste}
230254721Semaste
231254721Semastevoid
232254721SemasteThreadPlanNull::GetDescription (Stream *s,
233254721Semaste                                lldb::DescriptionLevel level)
234254721Semaste{
235254721Semaste    s->PutCString("Null thread plan - thread has been destroyed.");
236254721Semaste}
237254721Semaste
238254721Semastebool
239254721SemasteThreadPlanNull::ValidatePlan (Stream *error)
240254721Semaste{
241254721Semaste#ifdef LLDB_CONFIGURATION_DEBUG
242254721Semaste    fprintf(stderr, "error: %s called on thread that has been destroyed (tid = 0x%" PRIx64 ", ptid = 0x%" PRIx64 ")",
243254721Semaste            __PRETTY_FUNCTION__,
244254721Semaste            m_thread.GetID(),
245254721Semaste            m_thread.GetProtocolID());
246254721Semaste#else
247254721Semaste    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD));
248254721Semaste    if (log)
249254721Semaste        log->Error("%s called on thread that has been destroyed (tid = 0x%" PRIx64 ", ptid = 0x%" PRIx64 ")",
250254721Semaste                    __PRETTY_FUNCTION__,
251254721Semaste                    m_thread.GetID(),
252254721Semaste                    m_thread.GetProtocolID());
253254721Semaste#endif
254254721Semaste    return true;
255254721Semaste}
256254721Semaste
257254721Semastebool
258254721SemasteThreadPlanNull::ShouldStop (Event *event_ptr)
259254721Semaste{
260254721Semaste#ifdef LLDB_CONFIGURATION_DEBUG
261254721Semaste    fprintf(stderr, "error: %s called on thread that has been destroyed (tid = 0x%" PRIx64 ", ptid = 0x%" PRIx64 ")",
262254721Semaste            __PRETTY_FUNCTION__,
263254721Semaste            m_thread.GetID(),
264254721Semaste            m_thread.GetProtocolID());
265254721Semaste#else
266254721Semaste    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD));
267254721Semaste    if (log)
268254721Semaste        log->Error("%s called on thread that has been destroyed (tid = 0x%" PRIx64 ", ptid = 0x%" PRIx64 ")",
269254721Semaste                    __PRETTY_FUNCTION__,
270254721Semaste                    m_thread.GetID(),
271254721Semaste                    m_thread.GetProtocolID());
272254721Semaste#endif
273254721Semaste    return true;
274254721Semaste}
275254721Semaste
276254721Semastebool
277254721SemasteThreadPlanNull::WillStop ()
278254721Semaste{
279254721Semaste#ifdef LLDB_CONFIGURATION_DEBUG
280254721Semaste    fprintf(stderr, "error: %s called on thread that has been destroyed (tid = 0x%" PRIx64 ", ptid = 0x%" PRIx64 ")",
281254721Semaste            __PRETTY_FUNCTION__,
282254721Semaste            m_thread.GetID(),
283254721Semaste            m_thread.GetProtocolID());
284254721Semaste#else
285254721Semaste    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD));
286254721Semaste    if (log)
287254721Semaste        log->Error("%s called on thread that has been destroyed (tid = 0x%" PRIx64 ", ptid = 0x%" PRIx64 ")",
288254721Semaste                    __PRETTY_FUNCTION__,
289254721Semaste                    m_thread.GetID(),
290254721Semaste                    m_thread.GetProtocolID());
291254721Semaste#endif
292254721Semaste    return true;
293254721Semaste}
294254721Semaste
295254721Semastebool
296254721SemasteThreadPlanNull::DoPlanExplainsStop (Event *event_ptr)
297254721Semaste{
298254721Semaste#ifdef LLDB_CONFIGURATION_DEBUG
299254721Semaste    fprintf(stderr, "error: %s called on thread that has been destroyed (tid = 0x%" PRIx64 ", ptid = 0x%" PRIx64 ")",
300254721Semaste            __PRETTY_FUNCTION__,
301254721Semaste            m_thread.GetID(),
302254721Semaste            m_thread.GetProtocolID());
303254721Semaste#else
304254721Semaste    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD));
305254721Semaste    if (log)
306254721Semaste        log->Error("%s called on thread that has been destroyed (tid = 0x%" PRIx64 ", ptid = 0x%" PRIx64 ")",
307254721Semaste                   __PRETTY_FUNCTION__,
308254721Semaste                   m_thread.GetID(),
309254721Semaste                   m_thread.GetProtocolID());
310254721Semaste#endif
311254721Semaste    return true;
312254721Semaste}
313254721Semaste
314254721Semaste// The null plan is never done.
315254721Semastebool
316254721SemasteThreadPlanNull::MischiefManaged ()
317254721Semaste{
318254721Semaste    // The null plan is never done.
319254721Semaste#ifdef LLDB_CONFIGURATION_DEBUG
320254721Semaste    fprintf(stderr, "error: %s called on thread that has been destroyed (tid = 0x%" PRIx64 ", ptid = 0x%" PRIx64 ")",
321254721Semaste            __PRETTY_FUNCTION__,
322254721Semaste            m_thread.GetID(),
323254721Semaste            m_thread.GetProtocolID());
324254721Semaste#else
325254721Semaste    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD));
326254721Semaste    if (log)
327254721Semaste        log->Error("%s called on thread that has been destroyed (tid = 0x%" PRIx64 ", ptid = 0x%" PRIx64 ")",
328254721Semaste                   __PRETTY_FUNCTION__,
329254721Semaste                   m_thread.GetID(),
330254721Semaste                   m_thread.GetProtocolID());
331254721Semaste#endif
332254721Semaste    return false;
333254721Semaste}
334254721Semaste
335254721Semastelldb::StateType
336254721SemasteThreadPlanNull::GetPlanRunState ()
337254721Semaste{
338254721Semaste    // Not sure what to return here.  This is a dead thread.
339254721Semaste#ifdef LLDB_CONFIGURATION_DEBUG
340254721Semaste    fprintf(stderr, "error: %s called on thread that has been destroyed (tid = 0x%" PRIx64 ", ptid = 0x%" PRIx64 ")",
341254721Semaste            __PRETTY_FUNCTION__,
342254721Semaste            m_thread.GetID(),
343254721Semaste            m_thread.GetProtocolID());
344254721Semaste#else
345254721Semaste    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD));
346254721Semaste    if (log)
347254721Semaste        log->Error("%s called on thread that has been destroyed (tid = 0x%" PRIx64 ", ptid = 0x%" PRIx64 ")",
348254721Semaste                   __PRETTY_FUNCTION__,
349254721Semaste                   m_thread.GetID(),
350254721Semaste                   m_thread.GetProtocolID());
351254721Semaste#endif
352254721Semaste    return eStateRunning;
353254721Semaste}
354