12bdbfd50SJim Ingham //===-- ThreadPlan.cpp ------------------------------------------*- C++ -*-===//
22bdbfd50SJim Ingham //
32bdbfd50SJim Ingham //                     The LLVM Compiler Infrastructure
42bdbfd50SJim Ingham //
52bdbfd50SJim Ingham // This file is distributed under the University of Illinois Open Source
62bdbfd50SJim Ingham // License. See LICENSE.TXT for details.
72bdbfd50SJim Ingham //
82bdbfd50SJim Ingham //===----------------------------------------------------------------------===//
92bdbfd50SJim Ingham 
102bdbfd50SJim Ingham #include "lldb/Target/ThreadPlan.h"
112bdbfd50SJim Ingham 
122bdbfd50SJim Ingham // C Includes
132bdbfd50SJim Ingham // C++ Includes
142bdbfd50SJim Ingham // Other libraries and framework includes
152bdbfd50SJim Ingham // Project includes
162bdbfd50SJim Ingham #include "lldb/Core/Debugger.h"
172bdbfd50SJim Ingham #include "lldb/Core/Log.h"
182bdbfd50SJim Ingham #include "lldb/Core/State.h"
192bdbfd50SJim Ingham #include "lldb/Interpreter/CommandInterpreter.h"
202bdbfd50SJim Ingham #include "lldb/Interpreter/ScriptInterpreter.h"
212bdbfd50SJim Ingham #include "lldb/Target/RegisterContext.h"
222bdbfd50SJim Ingham #include "lldb/Target/Thread.h"
232bdbfd50SJim Ingham #include "lldb/Target/ThreadPlan.h"
242bdbfd50SJim Ingham #include "lldb/Target/ThreadPlanPython.h"
252bdbfd50SJim Ingham #include "lldb/Target/Process.h"
262bdbfd50SJim Ingham #include "lldb/Target/Target.h"
272bdbfd50SJim Ingham 
282bdbfd50SJim Ingham using namespace lldb;
292bdbfd50SJim Ingham using namespace lldb_private;
302bdbfd50SJim Ingham 
312bdbfd50SJim Ingham //----------------------------------------------------------------------
322bdbfd50SJim Ingham // ThreadPlanPython
332bdbfd50SJim Ingham //----------------------------------------------------------------------
342bdbfd50SJim Ingham 
352bdbfd50SJim Ingham ThreadPlanPython::ThreadPlanPython (Thread &thread, const char *class_name) :
362bdbfd50SJim Ingham     ThreadPlan (ThreadPlan::eKindPython,
372bdbfd50SJim Ingham                 "Python based Thread Plan",
382bdbfd50SJim Ingham                 thread,
392bdbfd50SJim Ingham                 eVoteNoOpinion,
402bdbfd50SJim Ingham                 eVoteNoOpinion),
412bdbfd50SJim Ingham     m_class_name (class_name)
422bdbfd50SJim Ingham {
432bdbfd50SJim Ingham     SetIsMasterPlan (true);
442bdbfd50SJim Ingham     SetOkayToDiscard (true);
452bdbfd50SJim Ingham     SetPrivate (false);
462bdbfd50SJim Ingham }
472bdbfd50SJim Ingham 
482bdbfd50SJim Ingham ThreadPlanPython::~ThreadPlanPython ()
492bdbfd50SJim Ingham {
502bdbfd50SJim Ingham     // FIXME, do I need to decrement the ref count on this implementation object to make it go away?
512bdbfd50SJim Ingham }
522bdbfd50SJim Ingham 
532bdbfd50SJim Ingham bool
542bdbfd50SJim Ingham ThreadPlanPython::ValidatePlan (Stream *error)
552bdbfd50SJim Ingham {
562bdbfd50SJim Ingham     // I have to postpone setting up the implementation till after the constructor because I need to call
572bdbfd50SJim Ingham     // shared_from_this, which you can't do in the constructor.  So I'll do it here.
582bdbfd50SJim Ingham     if (m_implementation_sp)
592bdbfd50SJim Ingham         return true;
602bdbfd50SJim Ingham     else
612bdbfd50SJim Ingham         return false;
622bdbfd50SJim Ingham }
632bdbfd50SJim Ingham 
642bdbfd50SJim Ingham void
652bdbfd50SJim Ingham ThreadPlanPython::DidPush()
662bdbfd50SJim Ingham {
672bdbfd50SJim Ingham     // We set up the script side in DidPush, so that it can push other plans in the constructor,
682bdbfd50SJim Ingham     // and doesn't have to care about the details of DidPush.
692bdbfd50SJim Ingham 
702bdbfd50SJim Ingham     if (!m_class_name.empty())
712bdbfd50SJim Ingham     {
722bdbfd50SJim Ingham         ScriptInterpreter *script_interp = m_thread.GetProcess()->GetTarget().GetDebugger().GetCommandInterpreter().GetScriptInterpreter();
732bdbfd50SJim Ingham         if (script_interp)
742bdbfd50SJim Ingham         {
752bdbfd50SJim Ingham             m_implementation_sp = script_interp->CreateScriptedThreadPlan (m_class_name.c_str(), this->shared_from_this());
762bdbfd50SJim Ingham         }
772bdbfd50SJim Ingham     }
782bdbfd50SJim Ingham }
792bdbfd50SJim Ingham 
802bdbfd50SJim Ingham bool
812bdbfd50SJim Ingham ThreadPlanPython::ShouldStop (Event *event_ptr)
822bdbfd50SJim Ingham {
832bdbfd50SJim Ingham     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD));
842bdbfd50SJim Ingham     if (log)
852bdbfd50SJim Ingham         log->Printf ("%s called on Python Thread Plan: %s )",
862bdbfd50SJim Ingham                     __PRETTY_FUNCTION__, m_class_name.c_str());
872bdbfd50SJim Ingham 
882bdbfd50SJim Ingham     bool should_stop = true;
892bdbfd50SJim Ingham     if (m_implementation_sp)
902bdbfd50SJim Ingham     {
912bdbfd50SJim Ingham         ScriptInterpreter *script_interp = m_thread.GetProcess()->GetTarget().GetDebugger().GetCommandInterpreter().GetScriptInterpreter();
922bdbfd50SJim Ingham         if (script_interp)
932bdbfd50SJim Ingham         {
942bdbfd50SJim Ingham             bool script_error;
952bdbfd50SJim Ingham             should_stop = script_interp->ScriptedThreadPlanShouldStop (m_implementation_sp, event_ptr, script_error);
962bdbfd50SJim Ingham             if (script_error)
972bdbfd50SJim Ingham                 SetPlanComplete(false);
982bdbfd50SJim Ingham         }
992bdbfd50SJim Ingham     }
1002bdbfd50SJim Ingham     return should_stop;
1012bdbfd50SJim Ingham }
1022bdbfd50SJim Ingham 
1032bdbfd50SJim Ingham bool
104*c915a7d2SJim Ingham ThreadPlanPython::IsPlanStale()
105*c915a7d2SJim Ingham {
106*c915a7d2SJim Ingham     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD));
107*c915a7d2SJim Ingham     if (log)
108*c915a7d2SJim Ingham         log->Printf ("%s called on Python Thread Plan: %s )",
109*c915a7d2SJim Ingham                     __PRETTY_FUNCTION__, m_class_name.c_str());
110*c915a7d2SJim Ingham 
111*c915a7d2SJim Ingham     bool is_stale = true;
112*c915a7d2SJim Ingham     if (m_implementation_sp)
113*c915a7d2SJim Ingham     {
114*c915a7d2SJim Ingham         ScriptInterpreter *script_interp = m_thread.GetProcess()->GetTarget().GetDebugger().GetCommandInterpreter().GetScriptInterpreter();
115*c915a7d2SJim Ingham         if (script_interp)
116*c915a7d2SJim Ingham         {
117*c915a7d2SJim Ingham             bool script_error;
118*c915a7d2SJim Ingham             is_stale = script_interp->ScriptedThreadPlanIsStale (m_implementation_sp, script_error);
119*c915a7d2SJim Ingham             if (script_error)
120*c915a7d2SJim Ingham                 SetPlanComplete(false);
121*c915a7d2SJim Ingham         }
122*c915a7d2SJim Ingham     }
123*c915a7d2SJim Ingham     return is_stale;
124*c915a7d2SJim Ingham }
125*c915a7d2SJim Ingham 
126*c915a7d2SJim Ingham bool
1272bdbfd50SJim Ingham ThreadPlanPython::DoPlanExplainsStop (Event *event_ptr)
1282bdbfd50SJim Ingham {
1292bdbfd50SJim Ingham     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD));
1302bdbfd50SJim Ingham     if (log)
1312bdbfd50SJim Ingham         log->Printf ("%s called on Python Thread Plan: %s )",
1322bdbfd50SJim Ingham                     __PRETTY_FUNCTION__, m_class_name.c_str());
1332bdbfd50SJim Ingham 
1342bdbfd50SJim Ingham     bool explains_stop = true;
1352bdbfd50SJim Ingham     if (m_implementation_sp)
1362bdbfd50SJim Ingham     {
1372bdbfd50SJim Ingham         ScriptInterpreter *script_interp = m_thread.GetProcess()->GetTarget().GetDebugger().GetCommandInterpreter().GetScriptInterpreter();
1382bdbfd50SJim Ingham         if (script_interp)
1392bdbfd50SJim Ingham         {
1402bdbfd50SJim Ingham             bool script_error;
1412bdbfd50SJim Ingham             explains_stop = script_interp->ScriptedThreadPlanExplainsStop (m_implementation_sp, event_ptr, script_error);
1422bdbfd50SJim Ingham             if (script_error)
1432bdbfd50SJim Ingham                 SetPlanComplete(false);
1442bdbfd50SJim Ingham         }
1452bdbfd50SJim Ingham     }
1462bdbfd50SJim Ingham     return explains_stop;
1472bdbfd50SJim Ingham }
1482bdbfd50SJim Ingham 
1492bdbfd50SJim Ingham bool
1502bdbfd50SJim Ingham ThreadPlanPython::MischiefManaged ()
1512bdbfd50SJim Ingham {
1522bdbfd50SJim Ingham     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD));
1532bdbfd50SJim Ingham     if (log)
1542bdbfd50SJim Ingham         log->Printf ("%s called on Python Thread Plan: %s )",
1552bdbfd50SJim Ingham                     __PRETTY_FUNCTION__, m_class_name.c_str());
1562bdbfd50SJim Ingham     bool mischief_managed = true;
1572bdbfd50SJim Ingham     if (m_implementation_sp)
1582bdbfd50SJim Ingham     {
1592bdbfd50SJim Ingham         // I don't really need mischief_managed, since it's simpler to just call SetPlanComplete in should_stop.
1602bdbfd50SJim Ingham         mischief_managed = IsPlanComplete();
1612bdbfd50SJim Ingham         if (mischief_managed)
1622bdbfd50SJim Ingham             m_implementation_sp.reset();
1632bdbfd50SJim Ingham     }
1642bdbfd50SJim Ingham     return mischief_managed;
1652bdbfd50SJim Ingham }
1662bdbfd50SJim Ingham 
1672bdbfd50SJim Ingham lldb::StateType
1682bdbfd50SJim Ingham ThreadPlanPython::GetPlanRunState ()
1692bdbfd50SJim Ingham {
1702bdbfd50SJim Ingham     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD));
1712bdbfd50SJim Ingham     if (log)
1722bdbfd50SJim Ingham         log->Printf ("%s called on Python Thread Plan: %s )",
1732bdbfd50SJim Ingham                      __PRETTY_FUNCTION__,
1742bdbfd50SJim Ingham                      m_class_name.c_str());
1752bdbfd50SJim Ingham     lldb::StateType run_state = eStateRunning;
1762bdbfd50SJim Ingham     if (m_implementation_sp)
1772bdbfd50SJim Ingham     {
1782bdbfd50SJim Ingham         ScriptInterpreter *script_interp = m_thread.GetProcess()->GetTarget().GetDebugger().GetCommandInterpreter().GetScriptInterpreter();
1792bdbfd50SJim Ingham         if (script_interp)
1802bdbfd50SJim Ingham         {
1812bdbfd50SJim Ingham             bool script_error;
1822bdbfd50SJim Ingham             run_state = script_interp->ScriptedThreadPlanGetRunState (m_implementation_sp, script_error);
1832bdbfd50SJim Ingham         }
1842bdbfd50SJim Ingham     }
1852bdbfd50SJim Ingham     return run_state;
1862bdbfd50SJim Ingham }
1872bdbfd50SJim Ingham 
1882bdbfd50SJim Ingham // The ones below are not currently exported to Python.
1892bdbfd50SJim Ingham 
1902bdbfd50SJim Ingham bool
1912bdbfd50SJim Ingham ThreadPlanPython::StopOthers ()
1922bdbfd50SJim Ingham {
1932bdbfd50SJim Ingham     // For now Python plans run all threads, but we should add some controls for this.
1942bdbfd50SJim Ingham     return false;
1952bdbfd50SJim Ingham }
1962bdbfd50SJim Ingham 
1972bdbfd50SJim Ingham void
1982bdbfd50SJim Ingham ThreadPlanPython::GetDescription (Stream *s,
1992bdbfd50SJim Ingham                                 lldb::DescriptionLevel level)
2002bdbfd50SJim Ingham {
2012bdbfd50SJim Ingham     s->Printf ("Python thread plan implemented by class %s.", m_class_name.c_str());
2022bdbfd50SJim Ingham }
2032bdbfd50SJim Ingham 
2042bdbfd50SJim Ingham bool
2052bdbfd50SJim Ingham ThreadPlanPython::WillStop ()
2062bdbfd50SJim Ingham {
2072bdbfd50SJim Ingham     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD));
2082bdbfd50SJim Ingham     if (log)
2092bdbfd50SJim Ingham         log->Printf ("%s called on Python Thread Plan: %s )",
2102bdbfd50SJim Ingham                     __PRETTY_FUNCTION__, m_class_name.c_str());
2112bdbfd50SJim Ingham     return true;
2122bdbfd50SJim Ingham }
213