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