| //===-- ThreadPlan.cpp ------------------------------------------*- C++ -*-===// |
| // |
| // The LLVM Compiler Infrastructure |
| // |
| // This file is distributed under the University of Illinois Open Source |
| // License. See LICENSE.TXT for details. |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #include "lldb/Target/ThreadPlan.h" |
| |
| // C Includes |
| // C++ Includes |
| // Other libraries and framework includes |
| // Project includes |
| #include "lldb/Core/Debugger.h" |
| #include "lldb/Core/Log.h" |
| #include "lldb/Core/State.h" |
| #include "lldb/Target/RegisterContext.h" |
| #include "lldb/Target/Thread.h" |
| #include "lldb/Target/Process.h" |
| #include "lldb/Target/Target.h" |
| |
| using namespace lldb; |
| using namespace lldb_private; |
| |
| //---------------------------------------------------------------------- |
| // ThreadPlan constructor |
| //---------------------------------------------------------------------- |
| ThreadPlan::ThreadPlan(ThreadPlanKind kind, const char *name, Thread &thread, Vote stop_vote, Vote run_vote) : |
| m_thread (thread), |
| m_stop_vote (stop_vote), |
| m_run_vote (run_vote), |
| m_kind (kind), |
| m_name (name), |
| m_plan_complete_mutex (Mutex::eMutexTypeRecursive), |
| m_plan_complete (false), |
| m_plan_private (false), |
| m_okay_to_discard (false) |
| { |
| SetID (GetNextID()); |
| } |
| |
| //---------------------------------------------------------------------- |
| // Destructor |
| //---------------------------------------------------------------------- |
| ThreadPlan::~ThreadPlan() |
| { |
| } |
| |
| const char * |
| ThreadPlan::GetName () const |
| { |
| return m_name.c_str(); |
| } |
| |
| Thread & |
| ThreadPlan::GetThread() |
| { |
| return m_thread; |
| } |
| |
| |
| const Thread & |
| ThreadPlan::GetThread() const |
| { |
| return m_thread; |
| } |
| |
| bool |
| ThreadPlan::IsPlanComplete () |
| { |
| Mutex::Locker locker(m_plan_complete_mutex); |
| return m_plan_complete; |
| } |
| |
| void |
| ThreadPlan::SetPlanComplete () |
| { |
| Mutex::Locker locker(m_plan_complete_mutex); |
| m_plan_complete = true; |
| } |
| |
| bool |
| ThreadPlan::MischiefManaged () |
| { |
| Mutex::Locker locker(m_plan_complete_mutex); |
| m_plan_complete = true; |
| return true; |
| } |
| |
| Vote |
| ThreadPlan::ShouldReportStop (Event *event_ptr) |
| { |
| LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); |
| |
| if (m_stop_vote == eVoteNoOpinion) |
| { |
| ThreadPlan *prev_plan = GetPreviousPlan (); |
| if (prev_plan) |
| { |
| Vote prev_vote = prev_plan->ShouldReportStop (event_ptr); |
| if (log) |
| log->Printf ("ThreadPlan::ShouldReportStop() returning previous thread plan vote: %s", GetVoteAsCString (prev_vote)); |
| return prev_vote; |
| } |
| } |
| if (log) |
| log->Printf ("ThreadPlan::ShouldReportStop() returning vote: %s", GetVoteAsCString (m_stop_vote)); |
| return m_stop_vote; |
| } |
| |
| Vote |
| ThreadPlan::ShouldReportRun (Event *event_ptr) |
| { |
| if (m_run_vote == eVoteNoOpinion) |
| { |
| ThreadPlan *prev_plan = GetPreviousPlan (); |
| if (prev_plan) |
| return prev_plan->ShouldReportRun (event_ptr); |
| } |
| return m_run_vote; |
| } |
| |
| bool |
| ThreadPlan::StopOthers () |
| { |
| ThreadPlan *prev_plan; |
| prev_plan = GetPreviousPlan (); |
| if (prev_plan == NULL) |
| return false; |
| else |
| return prev_plan->StopOthers(); |
| } |
| |
| void |
| ThreadPlan::SetStopOthers (bool new_value) |
| { |
| // SetStopOthers doesn't work up the hierarchy. You have to set the |
| // explicit ThreadPlan you want to affect. |
| } |
| |
| bool |
| ThreadPlan::WillResume (StateType resume_state, bool current_plan) |
| { |
| if (current_plan) |
| { |
| LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); |
| |
| if (log) |
| { |
| RegisterContext *reg_ctx = m_thread.GetRegisterContext().get(); |
| addr_t pc = reg_ctx->GetPC(); |
| addr_t sp = reg_ctx->GetSP(); |
| addr_t fp = reg_ctx->GetFP(); |
| log->Printf("%s Thread #%u: tid = 0x%4.4llx, pc = 0x%8.8llx, sp = 0x%8.8llx, fp = 0x%8.8llx, plan = '%s', state = %s, stop others = %d", |
| __FUNCTION__, |
| m_thread.GetIndexID(), |
| m_thread.GetID(), |
| (uint64_t)pc, |
| (uint64_t)sp, |
| (uint64_t)fp, |
| m_name.c_str(), |
| StateAsCString(resume_state), |
| StopOthers()); |
| } |
| } |
| return true; |
| } |
| |
| lldb::user_id_t |
| ThreadPlan::GetNextID() |
| { |
| static uint32_t g_nextPlanID = 0; |
| return ++g_nextPlanID; |
| } |
| |
| void |
| ThreadPlan::DidPush() |
| { |
| } |
| |
| void |
| ThreadPlan::WillPop() |
| { |
| } |
| |
| void |
| ThreadPlan::PushPlan (ThreadPlanSP &thread_plan_sp) |
| { |
| m_thread.PushPlan (thread_plan_sp); |
| } |
| |
| ThreadPlan * |
| ThreadPlan::GetPreviousPlan () |
| { |
| return m_thread.GetPreviousPlan (this); |
| } |
| |
| void |
| ThreadPlan::SetPrivate (bool input) |
| { |
| m_plan_private = input; |
| } |
| |
| bool |
| ThreadPlan::GetPrivate (void) |
| { |
| return m_plan_private; |
| } |
| |
| bool |
| ThreadPlan::OkayToDiscard() |
| { |
| if (!IsMasterPlan()) |
| return true; |
| else |
| return m_okay_to_discard; |
| } |
| |
| lldb::StateType |
| ThreadPlan::RunState () |
| { |
| if (m_tracer_sp && m_tracer_sp->TracingEnabled() && m_tracer_sp->SingleStepEnabled()) |
| return eStateStepping; |
| else |
| return GetPlanRunState(); |
| } |