1 //===-- 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 
10 #include "lldb/Target/ThreadPlan.h"
11 
12 // C Includes
13 // C++ Includes
14 // Other libraries and framework includes
15 // Project includes
16 #include "lldb/Core/Debugger.h"
17 #include "lldb/Core/Log.h"
18 #include "lldb/Core/State.h"
19 #include "lldb/Target/RegisterContext.h"
20 #include "lldb/Target/Thread.h"
21 #include "lldb/Target/Process.h"
22 #include "lldb/Target/Target.h"
23 
24 using namespace lldb;
25 using namespace lldb_private;
26 
27 //----------------------------------------------------------------------
28 // ThreadPlan constructor
29 //----------------------------------------------------------------------
30 ThreadPlan::ThreadPlan(ThreadPlanKind kind, const char *name, Thread &thread, Vote stop_vote, Vote run_vote) :
31     m_thread (thread),
32     m_stop_vote (stop_vote),
33     m_run_vote (run_vote),
34     m_kind (kind),
35     m_name (name),
36     m_plan_complete_mutex (Mutex::eMutexTypeRecursive),
37     m_plan_complete (false),
38     m_plan_private (false),
39     m_okay_to_discard (false)
40 {
41     SetID (GetNextID());
42 }
43 
44 //----------------------------------------------------------------------
45 // Destructor
46 //----------------------------------------------------------------------
47 ThreadPlan::~ThreadPlan()
48 {
49 }
50 
51 const char *
52 ThreadPlan::GetName () const
53 {
54     return m_name.c_str();
55 }
56 
57 Thread &
58 ThreadPlan::GetThread()
59 {
60     return m_thread;
61 }
62 
63 
64 const Thread &
65 ThreadPlan::GetThread() const
66 {
67     return m_thread;
68 }
69 
70 bool
71 ThreadPlan::IsPlanComplete ()
72 {
73     Mutex::Locker locker(m_plan_complete_mutex);
74     return m_plan_complete;
75 }
76 
77 void
78 ThreadPlan::SetPlanComplete ()
79 {
80     Mutex::Locker locker(m_plan_complete_mutex);
81     m_plan_complete = true;
82 }
83 
84 bool
85 ThreadPlan::MischiefManaged ()
86 {
87     Mutex::Locker locker(m_plan_complete_mutex);
88     m_plan_complete = true;
89     return true;
90 }
91 
92 Vote
93 ThreadPlan::ShouldReportStop (Event *event_ptr)
94 {
95     LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
96 
97     if (m_stop_vote == eVoteNoOpinion)
98     {
99         ThreadPlan *prev_plan = GetPreviousPlan ();
100         if (prev_plan)
101         {
102             Vote prev_vote = prev_plan->ShouldReportStop (event_ptr);
103             if (log)
104                 log->Printf ("ThreadPlan::ShouldReportStop() returning previous thread plan vote: %s", GetVoteAsCString (prev_vote));
105             return prev_vote;
106         }
107     }
108     if (log)
109         log->Printf ("ThreadPlan::ShouldReportStop() returning vote: %s", GetVoteAsCString (m_stop_vote));
110     return m_stop_vote;
111 }
112 
113 Vote
114 ThreadPlan::ShouldReportRun (Event *event_ptr)
115 {
116     if (m_run_vote == eVoteNoOpinion)
117     {
118         ThreadPlan *prev_plan = GetPreviousPlan ();
119         if (prev_plan)
120             return prev_plan->ShouldReportRun (event_ptr);
121     }
122     return m_run_vote;
123 }
124 
125 bool
126 ThreadPlan::StopOthers ()
127 {
128     ThreadPlan *prev_plan;
129     prev_plan = GetPreviousPlan ();
130     if (prev_plan == NULL)
131         return false;
132     else
133         return prev_plan->StopOthers();
134 }
135 
136 void
137 ThreadPlan::SetStopOthers (bool new_value)
138 {
139 	// SetStopOthers doesn't work up the hierarchy.  You have to set the
140     // explicit ThreadPlan you want to affect.
141 }
142 
143 bool
144 ThreadPlan::WillResume (StateType resume_state, bool current_plan)
145 {
146     if (current_plan)
147     {
148         LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
149 
150         if (log)
151         {
152             RegisterContext *reg_ctx = m_thread.GetRegisterContext().get();
153             addr_t pc = reg_ctx->GetPC();
154             addr_t sp = reg_ctx->GetSP();
155             addr_t fp = reg_ctx->GetFP();
156             log->Printf("%s Thread #%u: tid = 0x%4.4x, pc = 0x%8.8llx, sp = 0x%8.8llx, fp = 0x%8.8llx, plan = '%s', state = %s, stop others = %d",
157                         __FUNCTION__,
158                         m_thread.GetIndexID(),
159                         m_thread.GetID(),
160                         (uint64_t)pc,
161                         (uint64_t)sp,
162                         (uint64_t)fp,
163                         m_name.c_str(),
164                         StateAsCString(resume_state),
165                         StopOthers());
166         }
167     }
168     return true;
169 }
170 
171 lldb::user_id_t
172 ThreadPlan::GetNextID()
173 {
174     static uint32_t g_nextPlanID = 0;
175     return ++g_nextPlanID;
176 }
177 
178 void
179 ThreadPlan::DidPush()
180 {
181 }
182 
183 void
184 ThreadPlan::WillPop()
185 {
186 }
187 
188 void
189 ThreadPlan::PushPlan (ThreadPlanSP &thread_plan_sp)
190 {
191     m_thread.PushPlan (thread_plan_sp);
192 }
193 
194 ThreadPlan *
195 ThreadPlan::GetPreviousPlan ()
196 {
197     return m_thread.GetPreviousPlan (this);
198 }
199 
200 void
201 ThreadPlan::SetPrivate (bool input)
202 {
203     m_plan_private = input;
204 }
205 
206 bool
207 ThreadPlan::GetPrivate (void)
208 {
209     return m_plan_private;
210 }
211 
212 bool
213 ThreadPlan::OkayToDiscard()
214 {
215     if (!IsMasterPlan())
216         return true;
217     else
218         return m_okay_to_discard;
219 }
220 
221 lldb::StateType
222 ThreadPlan::RunState ()
223 {
224     if (m_tracer_sp && m_tracer_sp->TracingEnabled() && m_tracer_sp->SingleStepEnabled())
225         return eStateStepping;
226     else
227         return GetPlanRunState();
228 }
229