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