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",
105                              GetVoteAsCString (prev_vote));
106             return prev_vote;
107         }
108     }
109     if (log)
110         log->Printf ("ThreadPlan::ShouldReportStop() returning vote: %s", GetVoteAsCString (m_stop_vote));
111     return m_stop_vote;
112 }
113 
114 Vote
115 ThreadPlan::ShouldReportRun (Event *event_ptr)
116 {
117     if (m_run_vote == eVoteNoOpinion)
118     {
119         ThreadPlan *prev_plan = GetPreviousPlan ();
120         if (prev_plan)
121             return prev_plan->ShouldReportRun (event_ptr);
122     }
123     return m_run_vote;
124 }
125 
126 bool
127 ThreadPlan::StopOthers ()
128 {
129     ThreadPlan *prev_plan;
130     prev_plan = GetPreviousPlan ();
131     if (prev_plan == NULL)
132         return false;
133     else
134         return prev_plan->StopOthers();
135 }
136 
137 void
138 ThreadPlan::SetStopOthers (bool new_value)
139 {
140 	// SetStopOthers doesn't work up the hierarchy.  You have to set the
141     // explicit ThreadPlan you want to affect.
142 }
143 
144 bool
145 ThreadPlan::WillResume (StateType resume_state, bool current_plan)
146 {
147     if (current_plan)
148     {
149         LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
150 
151         if (log)
152         {
153             RegisterContext *reg_ctx = m_thread.GetRegisterContext().get();
154             addr_t pc = reg_ctx->GetPC();
155             addr_t sp = reg_ctx->GetSP();
156             addr_t fp = reg_ctx->GetFP();
157             log->Printf("%s Thread #%u: tid = 0x%4.4llx, pc = 0x%8.8llx, sp = 0x%8.8llx, fp = 0x%8.8llx, "
158                         "plan = '%s', state = %s, stop others = %d",
159                         __FUNCTION__,
160                         m_thread.GetIndexID(),
161                         m_thread.GetID(),
162                         (uint64_t)pc,
163                         (uint64_t)sp,
164                         (uint64_t)fp,
165                         m_name.c_str(),
166                         StateAsCString(resume_state),
167                         StopOthers());
168         }
169     }
170     return true;
171 }
172 
173 lldb::user_id_t
174 ThreadPlan::GetNextID()
175 {
176     static uint32_t g_nextPlanID = 0;
177     return ++g_nextPlanID;
178 }
179 
180 void
181 ThreadPlan::DidPush()
182 {
183 }
184 
185 void
186 ThreadPlan::WillPop()
187 {
188 }
189 
190 void
191 ThreadPlan::PushPlan (ThreadPlanSP &thread_plan_sp)
192 {
193     m_thread.PushPlan (thread_plan_sp);
194 }
195 
196 ThreadPlan *
197 ThreadPlan::GetPreviousPlan ()
198 {
199     return m_thread.GetPreviousPlan (this);
200 }
201 
202 void
203 ThreadPlan::SetPrivate (bool input)
204 {
205     m_plan_private = input;
206 }
207 
208 bool
209 ThreadPlan::GetPrivate (void)
210 {
211     return m_plan_private;
212 }
213 
214 bool
215 ThreadPlan::OkayToDiscard()
216 {
217     if (!IsMasterPlan())
218         return true;
219     else
220         return m_okay_to_discard;
221 }
222 
223 lldb::StateType
224 ThreadPlan::RunState ()
225 {
226     if (m_tracer_sp && m_tracer_sp->TracingEnabled() && m_tracer_sp->SingleStepEnabled())
227         return eStateStepping;
228     else
229         return GetPlanRunState();
230 }
231