130fdc8d8SChris Lattner //===-- ThreadPlan.cpp ------------------------------------------*- C++ -*-===//
230fdc8d8SChris Lattner //
330fdc8d8SChris Lattner //                     The LLVM Compiler Infrastructure
430fdc8d8SChris Lattner //
530fdc8d8SChris Lattner // This file is distributed under the University of Illinois Open Source
630fdc8d8SChris Lattner // License. See LICENSE.TXT for details.
730fdc8d8SChris Lattner //
830fdc8d8SChris Lattner //===----------------------------------------------------------------------===//
930fdc8d8SChris Lattner 
1030fdc8d8SChris Lattner #include "lldb/Target/ThreadPlan.h"
1130fdc8d8SChris Lattner 
1230fdc8d8SChris Lattner // C Includes
1330fdc8d8SChris Lattner // C++ Includes
1430fdc8d8SChris Lattner // Other libraries and framework includes
1530fdc8d8SChris Lattner // Project includes
1606e827ccSJim Ingham #include "lldb/Core/Debugger.h"
1730fdc8d8SChris Lattner #include "lldb/Core/Log.h"
1830fdc8d8SChris Lattner #include "lldb/Core/State.h"
192cad65a5SGreg Clayton #include "lldb/Target/RegisterContext.h"
202cad65a5SGreg Clayton #include "lldb/Target/Thread.h"
2106e827ccSJim Ingham #include "lldb/Target/Process.h"
2206e827ccSJim Ingham #include "lldb/Target/Target.h"
235023257fSZachary Turner #include "lldb/Utility/ConvertEnum.h"
2430fdc8d8SChris Lattner 
2530fdc8d8SChris Lattner using namespace lldb;
2630fdc8d8SChris Lattner using namespace lldb_private;
2730fdc8d8SChris Lattner 
2830fdc8d8SChris Lattner //----------------------------------------------------------------------
2930fdc8d8SChris Lattner // ThreadPlan constructor
3030fdc8d8SChris Lattner //----------------------------------------------------------------------
31b01e742aSJim Ingham ThreadPlan::ThreadPlan(ThreadPlanKind kind, const char *name, Thread &thread, Vote stop_vote, Vote run_vote) :
3230fdc8d8SChris Lattner     m_thread (thread),
3330fdc8d8SChris Lattner     m_stop_vote (stop_vote),
3430fdc8d8SChris Lattner     m_run_vote (run_vote),
351ee0d4f7SBenjamin Kramer     m_kind (kind),
361ee0d4f7SBenjamin Kramer     m_name (name),
371ee0d4f7SBenjamin Kramer     m_plan_complete_mutex (Mutex::eMutexTypeRecursive),
38221d51cfSJim Ingham     m_cached_plan_explains_stop (eLazyBoolCalculate),
391ee0d4f7SBenjamin Kramer     m_plan_complete (false),
401ee0d4f7SBenjamin Kramer     m_plan_private (false),
4164e7ead1SJim Ingham     m_okay_to_discard (true),
42fbbfe6ecSJim Ingham     m_is_master_plan (false),
43fbbfe6ecSJim Ingham     m_plan_succeeded(true)
4430fdc8d8SChris Lattner {
4530fdc8d8SChris Lattner     SetID (GetNextID());
4630fdc8d8SChris Lattner }
4730fdc8d8SChris Lattner 
4830fdc8d8SChris Lattner //----------------------------------------------------------------------
4930fdc8d8SChris Lattner // Destructor
5030fdc8d8SChris Lattner //----------------------------------------------------------------------
5130fdc8d8SChris Lattner ThreadPlan::~ThreadPlan()
5230fdc8d8SChris Lattner {
5330fdc8d8SChris Lattner }
5430fdc8d8SChris Lattner 
5530fdc8d8SChris Lattner bool
56221d51cfSJim Ingham ThreadPlan::PlanExplainsStop (Event *event_ptr)
57221d51cfSJim Ingham {
58221d51cfSJim Ingham     if (m_cached_plan_explains_stop == eLazyBoolCalculate)
59221d51cfSJim Ingham     {
60221d51cfSJim Ingham         bool actual_value = DoPlanExplainsStop(event_ptr);
61221d51cfSJim Ingham         m_cached_plan_explains_stop = actual_value ? eLazyBoolYes : eLazyBoolNo;
62221d51cfSJim Ingham         return actual_value;
63221d51cfSJim Ingham     }
64221d51cfSJim Ingham     else
65221d51cfSJim Ingham     {
66221d51cfSJim Ingham         return m_cached_plan_explains_stop == eLazyBoolYes;
67221d51cfSJim Ingham     }
68221d51cfSJim Ingham }
69221d51cfSJim Ingham 
70221d51cfSJim Ingham bool
7130fdc8d8SChris Lattner ThreadPlan::IsPlanComplete ()
7230fdc8d8SChris Lattner {
73b132097bSGreg Clayton     Mutex::Locker locker(m_plan_complete_mutex);
7430fdc8d8SChris Lattner     return m_plan_complete;
7530fdc8d8SChris Lattner }
7630fdc8d8SChris Lattner 
7730fdc8d8SChris Lattner void
78fbbfe6ecSJim Ingham ThreadPlan::SetPlanComplete (bool success)
7930fdc8d8SChris Lattner {
80b132097bSGreg Clayton     Mutex::Locker locker(m_plan_complete_mutex);
8130fdc8d8SChris Lattner     m_plan_complete = true;
82fbbfe6ecSJim Ingham     m_plan_succeeded = success;
8330fdc8d8SChris Lattner }
8430fdc8d8SChris Lattner 
8530fdc8d8SChris Lattner bool
8630fdc8d8SChris Lattner ThreadPlan::MischiefManaged ()
8730fdc8d8SChris Lattner {
88b132097bSGreg Clayton     Mutex::Locker locker(m_plan_complete_mutex);
8918de2fdcSJim Ingham     // Mark the plan is complete, but don't override the success flag.
9030fdc8d8SChris Lattner     m_plan_complete = true;
9130fdc8d8SChris Lattner     return true;
9230fdc8d8SChris Lattner }
9330fdc8d8SChris Lattner 
9430fdc8d8SChris Lattner Vote
9530fdc8d8SChris Lattner ThreadPlan::ShouldReportStop (Event *event_ptr)
9630fdc8d8SChris Lattner {
975160ce5cSGreg Clayton     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
982cad65a5SGreg Clayton 
9930fdc8d8SChris Lattner     if (m_stop_vote == eVoteNoOpinion)
10030fdc8d8SChris Lattner     {
10130fdc8d8SChris Lattner         ThreadPlan *prev_plan = GetPreviousPlan ();
10230fdc8d8SChris Lattner         if (prev_plan)
1032cad65a5SGreg Clayton         {
1042cad65a5SGreg Clayton             Vote prev_vote = prev_plan->ShouldReportStop (event_ptr);
1052cad65a5SGreg Clayton             if (log)
106b5c0d1ccSJim Ingham                 log->Printf ("ThreadPlan::ShouldReportStop() returning previous thread plan vote: %s",
107b5c0d1ccSJim Ingham                              GetVoteAsCString (prev_vote));
1082cad65a5SGreg Clayton             return prev_vote;
10930fdc8d8SChris Lattner         }
1102cad65a5SGreg Clayton     }
1112cad65a5SGreg Clayton     if (log)
1121346f7e0SGreg Clayton         log->Printf ("ThreadPlan::ShouldReportStop() returning vote: %s", GetVoteAsCString (m_stop_vote));
11330fdc8d8SChris Lattner     return m_stop_vote;
11430fdc8d8SChris Lattner }
11530fdc8d8SChris Lattner 
11630fdc8d8SChris Lattner Vote
11730fdc8d8SChris Lattner ThreadPlan::ShouldReportRun (Event *event_ptr)
11830fdc8d8SChris Lattner {
11930fdc8d8SChris Lattner     if (m_run_vote == eVoteNoOpinion)
12030fdc8d8SChris Lattner     {
12130fdc8d8SChris Lattner         ThreadPlan *prev_plan = GetPreviousPlan ();
12230fdc8d8SChris Lattner         if (prev_plan)
12330fdc8d8SChris Lattner             return prev_plan->ShouldReportRun (event_ptr);
12430fdc8d8SChris Lattner     }
12530fdc8d8SChris Lattner     return m_run_vote;
12630fdc8d8SChris Lattner }
12730fdc8d8SChris Lattner 
12830fdc8d8SChris Lattner bool
12930fdc8d8SChris Lattner ThreadPlan::StopOthers ()
13030fdc8d8SChris Lattner {
13130fdc8d8SChris Lattner     ThreadPlan *prev_plan;
13230fdc8d8SChris Lattner     prev_plan = GetPreviousPlan ();
13330fdc8d8SChris Lattner     if (prev_plan == NULL)
13430fdc8d8SChris Lattner         return false;
13530fdc8d8SChris Lattner     else
13630fdc8d8SChris Lattner         return prev_plan->StopOthers();
13730fdc8d8SChris Lattner }
13830fdc8d8SChris Lattner 
139f48169bbSJim Ingham void
140f48169bbSJim Ingham ThreadPlan::SetStopOthers (bool new_value)
141f48169bbSJim Ingham {
142f48169bbSJim Ingham 	// SetStopOthers doesn't work up the hierarchy.  You have to set the
143f48169bbSJim Ingham     // explicit ThreadPlan you want to affect.
144f48169bbSJim Ingham }
145f48169bbSJim Ingham 
14630fdc8d8SChris Lattner bool
14730fdc8d8SChris Lattner ThreadPlan::WillResume (StateType resume_state, bool current_plan)
14830fdc8d8SChris Lattner {
149221d51cfSJim Ingham     m_cached_plan_explains_stop = eLazyBoolCalculate;
150221d51cfSJim Ingham 
15130fdc8d8SChris Lattner     if (current_plan)
15230fdc8d8SChris Lattner     {
1535160ce5cSGreg Clayton         Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
15430fdc8d8SChris Lattner 
15530fdc8d8SChris Lattner         if (log)
1562cad65a5SGreg Clayton         {
1575ccbd294SGreg Clayton             RegisterContext *reg_ctx = m_thread.GetRegisterContext().get();
158ff1b5c42SEd Maste             assert (reg_ctx);
1592cad65a5SGreg Clayton             addr_t pc = reg_ctx->GetPC();
1602cad65a5SGreg Clayton             addr_t sp = reg_ctx->GetSP();
1612cad65a5SGreg Clayton             addr_t fp = reg_ctx->GetFP();
162dee1bc98SJim Ingham             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 ", "
163b5c0d1ccSJim Ingham                         "plan = '%s', state = %s, stop others = %d",
164324a1036SSaleem Abdulrasool                         __FUNCTION__, m_thread.GetIndexID(),
165324a1036SSaleem Abdulrasool                         static_cast<void*>(&m_thread), m_thread.GetID(),
166324a1036SSaleem Abdulrasool                         static_cast<uint64_t>(pc), static_cast<uint64_t>(sp),
167324a1036SSaleem Abdulrasool                         static_cast<uint64_t>(fp), m_name.c_str(),
168324a1036SSaleem Abdulrasool                         StateAsCString(resume_state), StopOthers());
1692cad65a5SGreg Clayton         }
17030fdc8d8SChris Lattner     }
171221d51cfSJim Ingham     return DoWillResume (resume_state, current_plan);
17230fdc8d8SChris Lattner }
17330fdc8d8SChris Lattner 
17430fdc8d8SChris Lattner lldb::user_id_t
17530fdc8d8SChris Lattner ThreadPlan::GetNextID()
17630fdc8d8SChris Lattner {
17730fdc8d8SChris Lattner     static uint32_t g_nextPlanID = 0;
17830fdc8d8SChris Lattner     return ++g_nextPlanID;
17930fdc8d8SChris Lattner }
18030fdc8d8SChris Lattner 
18130fdc8d8SChris Lattner void
18230fdc8d8SChris Lattner ThreadPlan::DidPush()
18330fdc8d8SChris Lattner {
18430fdc8d8SChris Lattner }
18530fdc8d8SChris Lattner 
18630fdc8d8SChris Lattner void
18730fdc8d8SChris Lattner ThreadPlan::WillPop()
18830fdc8d8SChris Lattner {
18930fdc8d8SChris Lattner }
19030fdc8d8SChris Lattner 
19130fdc8d8SChris Lattner bool
19230fdc8d8SChris Lattner ThreadPlan::OkayToDiscard()
19330fdc8d8SChris Lattner {
19430fdc8d8SChris Lattner     if (!IsMasterPlan())
19530fdc8d8SChris Lattner         return true;
19630fdc8d8SChris Lattner     else
19730fdc8d8SChris Lattner         return m_okay_to_discard;
19830fdc8d8SChris Lattner }
19930fdc8d8SChris Lattner 
20006e827ccSJim Ingham lldb::StateType
20106e827ccSJim Ingham ThreadPlan::RunState ()
20206e827ccSJim Ingham {
20306e827ccSJim Ingham     if (m_tracer_sp && m_tracer_sp->TracingEnabled() && m_tracer_sp->SingleStepEnabled())
20406e827ccSJim Ingham         return eStateStepping;
20506e827ccSJim Ingham     else
20606e827ccSJim Ingham         return GetPlanRunState();
20706e827ccSJim Ingham }
2086e10f149SGreg Clayton 
209*9b03fa0cSJim Ingham bool
210*9b03fa0cSJim Ingham ThreadPlan::IsUsuallyUnexplainedStopReason(lldb::StopReason reason)
211*9b03fa0cSJim Ingham {
212*9b03fa0cSJim Ingham     switch (reason)
213*9b03fa0cSJim Ingham     {
214*9b03fa0cSJim Ingham         case eStopReasonWatchpoint:
215*9b03fa0cSJim Ingham         case eStopReasonSignal:
216*9b03fa0cSJim Ingham         case eStopReasonException:
217*9b03fa0cSJim Ingham         case eStopReasonExec:
218*9b03fa0cSJim Ingham         case eStopReasonThreadExiting:
219*9b03fa0cSJim Ingham         case eStopReasonInstrumentation:
220*9b03fa0cSJim Ingham             return true;
221*9b03fa0cSJim Ingham         default:
222*9b03fa0cSJim Ingham             return false;
223*9b03fa0cSJim Ingham     }
224*9b03fa0cSJim Ingham }
225*9b03fa0cSJim Ingham 
226*9b03fa0cSJim Ingham 
2276e10f149SGreg Clayton //----------------------------------------------------------------------
2286e10f149SGreg Clayton // ThreadPlanNull
2296e10f149SGreg Clayton //----------------------------------------------------------------------
2306e10f149SGreg Clayton 
2316e10f149SGreg Clayton ThreadPlanNull::ThreadPlanNull (Thread &thread) :
2326e10f149SGreg Clayton     ThreadPlan (ThreadPlan::eKindNull,
2336e10f149SGreg Clayton                 "Null Thread Plan",
2346e10f149SGreg Clayton                 thread,
2356e10f149SGreg Clayton                 eVoteNoOpinion,
2366e10f149SGreg Clayton                 eVoteNoOpinion)
2376e10f149SGreg Clayton {
2386e10f149SGreg Clayton }
2396e10f149SGreg Clayton 
2406e10f149SGreg Clayton ThreadPlanNull::~ThreadPlanNull ()
2416e10f149SGreg Clayton {
2426e10f149SGreg Clayton }
2436e10f149SGreg Clayton 
2446e10f149SGreg Clayton void
2456e10f149SGreg Clayton ThreadPlanNull::GetDescription (Stream *s,
2466e10f149SGreg Clayton                                 lldb::DescriptionLevel level)
2476e10f149SGreg Clayton {
2486e10f149SGreg Clayton     s->PutCString("Null thread plan - thread has been destroyed.");
2496e10f149SGreg Clayton }
2506e10f149SGreg Clayton 
2516e10f149SGreg Clayton bool
2526e10f149SGreg Clayton ThreadPlanNull::ValidatePlan (Stream *error)
2536e10f149SGreg Clayton {
2546e10f149SGreg Clayton #ifdef LLDB_CONFIGURATION_DEBUG
25589c862f2SMichael Sartain     fprintf(stderr, "error: %s called on thread that has been destroyed (tid = 0x%" PRIx64 ", ptid = 0x%" PRIx64 ")",
2566e10f149SGreg Clayton             __PRETTY_FUNCTION__,
2576e10f149SGreg Clayton             m_thread.GetID(),
2586e10f149SGreg Clayton             m_thread.GetProtocolID());
2596e10f149SGreg Clayton #else
2606e10f149SGreg Clayton     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD));
2616e10f149SGreg Clayton     if (log)
26289c862f2SMichael Sartain         log->Error("%s called on thread that has been destroyed (tid = 0x%" PRIx64 ", ptid = 0x%" PRIx64 ")",
2636e10f149SGreg Clayton                     __PRETTY_FUNCTION__,
2646e10f149SGreg Clayton                     m_thread.GetID(),
2656e10f149SGreg Clayton                     m_thread.GetProtocolID());
2666e10f149SGreg Clayton #endif
2676e10f149SGreg Clayton     return true;
2686e10f149SGreg Clayton }
2696e10f149SGreg Clayton 
2706e10f149SGreg Clayton bool
2716e10f149SGreg Clayton ThreadPlanNull::ShouldStop (Event *event_ptr)
2726e10f149SGreg Clayton {
2736e10f149SGreg Clayton #ifdef LLDB_CONFIGURATION_DEBUG
27489c862f2SMichael Sartain     fprintf(stderr, "error: %s called on thread that has been destroyed (tid = 0x%" PRIx64 ", ptid = 0x%" PRIx64 ")",
2756e10f149SGreg Clayton             __PRETTY_FUNCTION__,
2766e10f149SGreg Clayton             m_thread.GetID(),
2776e10f149SGreg Clayton             m_thread.GetProtocolID());
2786e10f149SGreg Clayton #else
2796e10f149SGreg Clayton     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD));
2806e10f149SGreg Clayton     if (log)
28189c862f2SMichael Sartain         log->Error("%s called on thread that has been destroyed (tid = 0x%" PRIx64 ", ptid = 0x%" PRIx64 ")",
2826e10f149SGreg Clayton                     __PRETTY_FUNCTION__,
2836e10f149SGreg Clayton                     m_thread.GetID(),
2846e10f149SGreg Clayton                     m_thread.GetProtocolID());
2856e10f149SGreg Clayton #endif
2866e10f149SGreg Clayton     return true;
2876e10f149SGreg Clayton }
2886e10f149SGreg Clayton 
2896e10f149SGreg Clayton bool
2906e10f149SGreg Clayton ThreadPlanNull::WillStop ()
2916e10f149SGreg Clayton {
2926e10f149SGreg Clayton #ifdef LLDB_CONFIGURATION_DEBUG
29389c862f2SMichael Sartain     fprintf(stderr, "error: %s called on thread that has been destroyed (tid = 0x%" PRIx64 ", ptid = 0x%" PRIx64 ")",
2946e10f149SGreg Clayton             __PRETTY_FUNCTION__,
2956e10f149SGreg Clayton             m_thread.GetID(),
2966e10f149SGreg Clayton             m_thread.GetProtocolID());
2976e10f149SGreg Clayton #else
2986e10f149SGreg Clayton     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD));
2996e10f149SGreg Clayton     if (log)
30089c862f2SMichael Sartain         log->Error("%s called on thread that has been destroyed (tid = 0x%" PRIx64 ", ptid = 0x%" PRIx64 ")",
3016e10f149SGreg Clayton                     __PRETTY_FUNCTION__,
3026e10f149SGreg Clayton                     m_thread.GetID(),
3036e10f149SGreg Clayton                     m_thread.GetProtocolID());
3046e10f149SGreg Clayton #endif
3056e10f149SGreg Clayton     return true;
3066e10f149SGreg Clayton }
3076e10f149SGreg Clayton 
3086e10f149SGreg Clayton bool
3096e10f149SGreg Clayton ThreadPlanNull::DoPlanExplainsStop (Event *event_ptr)
3106e10f149SGreg Clayton {
3116e10f149SGreg Clayton #ifdef LLDB_CONFIGURATION_DEBUG
31289c862f2SMichael Sartain     fprintf(stderr, "error: %s called on thread that has been destroyed (tid = 0x%" PRIx64 ", ptid = 0x%" PRIx64 ")",
3136e10f149SGreg Clayton             __PRETTY_FUNCTION__,
3146e10f149SGreg Clayton             m_thread.GetID(),
3156e10f149SGreg Clayton             m_thread.GetProtocolID());
3166e10f149SGreg Clayton #else
3176e10f149SGreg Clayton     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD));
3186e10f149SGreg Clayton     if (log)
31989c862f2SMichael Sartain         log->Error("%s called on thread that has been destroyed (tid = 0x%" PRIx64 ", ptid = 0x%" PRIx64 ")",
3206e10f149SGreg Clayton                    __PRETTY_FUNCTION__,
3216e10f149SGreg Clayton                    m_thread.GetID(),
3226e10f149SGreg Clayton                    m_thread.GetProtocolID());
3236e10f149SGreg Clayton #endif
3246e10f149SGreg Clayton     return true;
3256e10f149SGreg Clayton }
3266e10f149SGreg Clayton 
3276e10f149SGreg Clayton // The null plan is never done.
3286e10f149SGreg Clayton bool
3296e10f149SGreg Clayton ThreadPlanNull::MischiefManaged ()
3306e10f149SGreg Clayton {
3316e10f149SGreg Clayton     // The null plan is never done.
3326e10f149SGreg Clayton #ifdef LLDB_CONFIGURATION_DEBUG
33389c862f2SMichael Sartain     fprintf(stderr, "error: %s called on thread that has been destroyed (tid = 0x%" PRIx64 ", ptid = 0x%" PRIx64 ")",
3346e10f149SGreg Clayton             __PRETTY_FUNCTION__,
3356e10f149SGreg Clayton             m_thread.GetID(),
3366e10f149SGreg Clayton             m_thread.GetProtocolID());
3376e10f149SGreg Clayton #else
3386e10f149SGreg Clayton     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD));
3396e10f149SGreg Clayton     if (log)
34089c862f2SMichael Sartain         log->Error("%s called on thread that has been destroyed (tid = 0x%" PRIx64 ", ptid = 0x%" PRIx64 ")",
3416e10f149SGreg Clayton                    __PRETTY_FUNCTION__,
3426e10f149SGreg Clayton                    m_thread.GetID(),
3436e10f149SGreg Clayton                    m_thread.GetProtocolID());
3446e10f149SGreg Clayton #endif
3456e10f149SGreg Clayton     return false;
3466e10f149SGreg Clayton }
3476e10f149SGreg Clayton 
3486e10f149SGreg Clayton lldb::StateType
3496e10f149SGreg Clayton ThreadPlanNull::GetPlanRunState ()
3506e10f149SGreg Clayton {
3516e10f149SGreg Clayton     // Not sure what to return here.  This is a dead thread.
3526e10f149SGreg Clayton #ifdef LLDB_CONFIGURATION_DEBUG
35389c862f2SMichael Sartain     fprintf(stderr, "error: %s called on thread that has been destroyed (tid = 0x%" PRIx64 ", ptid = 0x%" PRIx64 ")",
3546e10f149SGreg Clayton             __PRETTY_FUNCTION__,
3556e10f149SGreg Clayton             m_thread.GetID(),
3566e10f149SGreg Clayton             m_thread.GetProtocolID());
3576e10f149SGreg Clayton #else
3586e10f149SGreg Clayton     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD));
3596e10f149SGreg Clayton     if (log)
36089c862f2SMichael Sartain         log->Error("%s called on thread that has been destroyed (tid = 0x%" PRIx64 ", ptid = 0x%" PRIx64 ")",
3616e10f149SGreg Clayton                    __PRETTY_FUNCTION__,
3626e10f149SGreg Clayton                    m_thread.GetID(),
3636e10f149SGreg Clayton                    m_thread.GetProtocolID());
3646e10f149SGreg Clayton #endif
3656e10f149SGreg Clayton     return eStateRunning;
3666e10f149SGreg Clayton }
367