]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - source/Target/ThreadPlan.cpp
Import LLDB as of upstream SVN 241361 (git 612c075f)
[FreeBSD/FreeBSD.git] / source / Target / ThreadPlan.cpp
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 #include "lldb/Utility/ConvertEnum.h"
24
25 using namespace lldb;
26 using namespace lldb_private;
27
28 //----------------------------------------------------------------------
29 // ThreadPlan constructor
30 //----------------------------------------------------------------------
31 ThreadPlan::ThreadPlan(ThreadPlanKind kind, const char *name, Thread &thread, Vote stop_vote, Vote run_vote) :
32     m_thread (thread),
33     m_stop_vote (stop_vote),
34     m_run_vote (run_vote),
35     m_kind (kind),
36     m_name (name),
37     m_plan_complete_mutex (Mutex::eMutexTypeRecursive),
38     m_cached_plan_explains_stop (eLazyBoolCalculate),
39     m_plan_complete (false),
40     m_plan_private (false),
41     m_okay_to_discard (true),
42     m_is_master_plan (false),
43     m_plan_succeeded(true)
44 {
45     SetID (GetNextID());
46 }
47
48 //----------------------------------------------------------------------
49 // Destructor
50 //----------------------------------------------------------------------
51 ThreadPlan::~ThreadPlan()
52 {
53 }
54
55 bool
56 ThreadPlan::PlanExplainsStop (Event *event_ptr)
57 {
58     if (m_cached_plan_explains_stop == eLazyBoolCalculate)
59     {
60         bool actual_value = DoPlanExplainsStop(event_ptr);
61         m_cached_plan_explains_stop = actual_value ? eLazyBoolYes : eLazyBoolNo;
62         return actual_value;
63     }
64     else
65     {
66         return m_cached_plan_explains_stop == eLazyBoolYes;
67     }
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 (bool success)
79 {
80     Mutex::Locker locker(m_plan_complete_mutex);
81     m_plan_complete = true;
82     m_plan_succeeded = success;
83 }
84
85 bool
86 ThreadPlan::MischiefManaged ()
87 {
88     Mutex::Locker locker(m_plan_complete_mutex);
89     // Mark the plan is complete, but don't override the success flag.
90     m_plan_complete = true;
91     return true;
92 }
93
94 Vote
95 ThreadPlan::ShouldReportStop (Event *event_ptr)
96 {
97     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
98
99     if (m_stop_vote == eVoteNoOpinion)
100     {
101         ThreadPlan *prev_plan = GetPreviousPlan ();
102         if (prev_plan)
103         {
104             Vote prev_vote = prev_plan->ShouldReportStop (event_ptr);
105             if (log)
106                 log->Printf ("ThreadPlan::ShouldReportStop() returning previous thread plan vote: %s", 
107                              GetVoteAsCString (prev_vote));
108             return prev_vote;
109         }
110     }
111     if (log)
112         log->Printf ("ThreadPlan::ShouldReportStop() returning vote: %s", GetVoteAsCString (m_stop_vote));
113     return m_stop_vote;
114 }
115
116 Vote
117 ThreadPlan::ShouldReportRun (Event *event_ptr)
118 {
119     if (m_run_vote == eVoteNoOpinion)
120     {
121         ThreadPlan *prev_plan = GetPreviousPlan ();
122         if (prev_plan)
123             return prev_plan->ShouldReportRun (event_ptr);
124     }
125     return m_run_vote;
126 }
127
128 bool
129 ThreadPlan::StopOthers ()
130 {
131     ThreadPlan *prev_plan;
132     prev_plan = GetPreviousPlan ();
133     if (prev_plan == NULL)
134         return false;
135     else
136         return prev_plan->StopOthers();
137 }
138
139 void
140 ThreadPlan::SetStopOthers (bool new_value)
141 {
142         // SetStopOthers doesn't work up the hierarchy.  You have to set the 
143     // explicit ThreadPlan you want to affect.
144 }
145
146 bool
147 ThreadPlan::WillResume (StateType resume_state, bool current_plan)
148 {
149     m_cached_plan_explains_stop = eLazyBoolCalculate;
150     
151     if (current_plan)
152     {
153         Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
154
155         if (log)
156         {
157             RegisterContext *reg_ctx = m_thread.GetRegisterContext().get();
158             assert (reg_ctx);
159             addr_t pc = reg_ctx->GetPC();
160             addr_t sp = reg_ctx->GetSP();
161             addr_t fp = reg_ctx->GetFP();
162             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 ", "
163                         "plan = '%s', state = %s, stop others = %d", 
164                         __FUNCTION__, m_thread.GetIndexID(),
165                         static_cast<void*>(&m_thread), m_thread.GetID(),
166                         static_cast<uint64_t>(pc), static_cast<uint64_t>(sp),
167                         static_cast<uint64_t>(fp), m_name.c_str(),
168                         StateAsCString(resume_state), StopOthers());
169         }
170     }
171     return DoWillResume (resume_state, current_plan);
172 }
173
174 lldb::user_id_t
175 ThreadPlan::GetNextID()
176 {
177     static uint32_t g_nextPlanID = 0;
178     return ++g_nextPlanID;
179 }
180
181 void
182 ThreadPlan::DidPush()
183 {
184 }
185
186 void
187 ThreadPlan::WillPop()
188 {
189 }
190
191 bool
192 ThreadPlan::OkayToDiscard()
193 {
194     if (!IsMasterPlan())
195         return true;
196     else
197         return m_okay_to_discard;
198 }
199
200 lldb::StateType
201 ThreadPlan::RunState ()
202 {
203     if (m_tracer_sp && m_tracer_sp->TracingEnabled() && m_tracer_sp->SingleStepEnabled())
204         return eStateStepping;
205     else
206         return GetPlanRunState();
207 }
208
209 //----------------------------------------------------------------------
210 // ThreadPlanNull
211 //----------------------------------------------------------------------
212
213 ThreadPlanNull::ThreadPlanNull (Thread &thread) :
214     ThreadPlan (ThreadPlan::eKindNull,
215                 "Null Thread Plan",
216                 thread,
217                 eVoteNoOpinion,
218                 eVoteNoOpinion)
219 {
220 }
221
222 ThreadPlanNull::~ThreadPlanNull ()
223 {
224 }
225
226 void
227 ThreadPlanNull::GetDescription (Stream *s,
228                                 lldb::DescriptionLevel level)
229 {
230     s->PutCString("Null thread plan - thread has been destroyed.");
231 }
232
233 bool
234 ThreadPlanNull::ValidatePlan (Stream *error)
235 {
236 #ifdef LLDB_CONFIGURATION_DEBUG
237     fprintf(stderr, "error: %s called on thread that has been destroyed (tid = 0x%" PRIx64 ", ptid = 0x%" PRIx64 ")",
238             __PRETTY_FUNCTION__,
239             m_thread.GetID(),
240             m_thread.GetProtocolID());
241 #else
242     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD));
243     if (log)
244         log->Error("%s called on thread that has been destroyed (tid = 0x%" PRIx64 ", ptid = 0x%" PRIx64 ")",
245                     __PRETTY_FUNCTION__,
246                     m_thread.GetID(),
247                     m_thread.GetProtocolID());
248 #endif
249     return true;
250 }
251
252 bool
253 ThreadPlanNull::ShouldStop (Event *event_ptr)
254 {
255 #ifdef LLDB_CONFIGURATION_DEBUG
256     fprintf(stderr, "error: %s called on thread that has been destroyed (tid = 0x%" PRIx64 ", ptid = 0x%" PRIx64 ")",
257             __PRETTY_FUNCTION__,
258             m_thread.GetID(),
259             m_thread.GetProtocolID());
260 #else
261     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD));
262     if (log)
263         log->Error("%s called on thread that has been destroyed (tid = 0x%" PRIx64 ", ptid = 0x%" PRIx64 ")",
264                     __PRETTY_FUNCTION__,
265                     m_thread.GetID(),
266                     m_thread.GetProtocolID());
267 #endif
268     return true;
269 }
270
271 bool
272 ThreadPlanNull::WillStop ()
273 {
274 #ifdef LLDB_CONFIGURATION_DEBUG
275     fprintf(stderr, "error: %s called on thread that has been destroyed (tid = 0x%" PRIx64 ", ptid = 0x%" PRIx64 ")",
276             __PRETTY_FUNCTION__,
277             m_thread.GetID(),
278             m_thread.GetProtocolID());
279 #else
280     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD));
281     if (log)
282         log->Error("%s called on thread that has been destroyed (tid = 0x%" PRIx64 ", ptid = 0x%" PRIx64 ")",
283                     __PRETTY_FUNCTION__,
284                     m_thread.GetID(),
285                     m_thread.GetProtocolID());
286 #endif
287     return true;
288 }
289
290 bool
291 ThreadPlanNull::DoPlanExplainsStop (Event *event_ptr)
292 {
293 #ifdef LLDB_CONFIGURATION_DEBUG
294     fprintf(stderr, "error: %s called on thread that has been destroyed (tid = 0x%" PRIx64 ", ptid = 0x%" PRIx64 ")",
295             __PRETTY_FUNCTION__,
296             m_thread.GetID(),
297             m_thread.GetProtocolID());
298 #else
299     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD));
300     if (log)
301         log->Error("%s called on thread that has been destroyed (tid = 0x%" PRIx64 ", ptid = 0x%" PRIx64 ")",
302                    __PRETTY_FUNCTION__,
303                    m_thread.GetID(),
304                    m_thread.GetProtocolID());
305 #endif
306     return true;
307 }
308
309 // The null plan is never done.
310 bool
311 ThreadPlanNull::MischiefManaged ()
312 {
313     // The null plan is never done.
314 #ifdef LLDB_CONFIGURATION_DEBUG
315     fprintf(stderr, "error: %s called on thread that has been destroyed (tid = 0x%" PRIx64 ", ptid = 0x%" PRIx64 ")",
316             __PRETTY_FUNCTION__,
317             m_thread.GetID(),
318             m_thread.GetProtocolID());
319 #else
320     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD));
321     if (log)
322         log->Error("%s called on thread that has been destroyed (tid = 0x%" PRIx64 ", ptid = 0x%" PRIx64 ")",
323                    __PRETTY_FUNCTION__,
324                    m_thread.GetID(),
325                    m_thread.GetProtocolID());
326 #endif
327     return false;
328 }
329
330 lldb::StateType
331 ThreadPlanNull::GetPlanRunState ()
332 {
333     // Not sure what to return here.  This is a dead thread.
334 #ifdef LLDB_CONFIGURATION_DEBUG
335     fprintf(stderr, "error: %s called on thread that has been destroyed (tid = 0x%" PRIx64 ", ptid = 0x%" PRIx64 ")",
336             __PRETTY_FUNCTION__,
337             m_thread.GetID(),
338             m_thread.GetProtocolID());
339 #else
340     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD));
341     if (log)
342         log->Error("%s called on thread that has been destroyed (tid = 0x%" PRIx64 ", ptid = 0x%" PRIx64 ")",
343                    __PRETTY_FUNCTION__,
344                    m_thread.GetID(),
345                    m_thread.GetProtocolID());
346 #endif
347     return eStateRunning;
348 }