[Lldb-commits] [lldb] r236576 - [ThreadStateCoordinator] Remove Event classes

Pavel Labath labath at google.com
Wed May 6 01:23:47 PDT 2015


Author: labath
Date: Wed May  6 03:23:47 2015
New Revision: 236576

URL: http://llvm.org/viewvc/llvm-project?rev=236576&view=rev
Log:
[ThreadStateCoordinator] Remove Event classes

Summary:
This is a cleanup patch for thread state coordinator. After making processing of all events
synchronous, there is no need to have a a separate class for each event. I have moved back
processing of all events back into the TSC class. No functional change.

Test Plan: All tests continue to pass.

Reviewers: chaoren, vharron

Subscribers: lldb-commits

Differential Revision: http://reviews.llvm.org/D9254

Modified:
    lldb/trunk/source/Plugins/Process/Linux/ThreadStateCoordinator.cpp
    lldb/trunk/source/Plugins/Process/Linux/ThreadStateCoordinator.h

Modified: lldb/trunk/source/Plugins/Process/Linux/ThreadStateCoordinator.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Linux/ThreadStateCoordinator.cpp?rev=236576&r1=236575&r2=236576&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/Linux/ThreadStateCoordinator.cpp (original)
+++ lldb/trunk/source/Plugins/Process/Linux/ThreadStateCoordinator.cpp Wed May  6 03:23:47 2015
@@ -24,618 +24,281 @@ using namespace lldb_private::process_li
 
 //===----------------------------------------------------------------------===//
 
-class ThreadStateCoordinator::EventBase : public std::enable_shared_from_this<ThreadStateCoordinator::EventBase>
-{
-public:
-    EventBase ()
-    {
-    }
-
-    virtual
-    ~EventBase ()
-    {
-    }
-
-    virtual std::string
-    GetDescription () = 0;
-
-    // Return false if the coordinator should terminate running.
-    virtual EventLoopResult
-    ProcessEvent (ThreadStateCoordinator &coordinator) = 0;
-};
-
-//===----------------------------------------------------------------------===//
-
-class ThreadStateCoordinator::EventCallAfterThreadsStop : public ThreadStateCoordinator::EventBase
+void
+ThreadStateCoordinator::DoResume(
+        lldb::tid_t tid,
+        ResumeThreadFunction request_thread_resume_function,
+        ErrorFunction error_function,
+        bool error_when_already_running)
 {
-public:
-    EventCallAfterThreadsStop (lldb::tid_t triggering_tid,
-                               const ThreadIDSet &wait_for_stop_tids,
-                               const StopThreadFunction &request_thread_stop_function,
-                               const ThreadIDFunction &call_after_function,
-                               const ErrorFunction &error_function):
-    EventBase (),
-    m_triggering_tid (triggering_tid),
-    m_wait_for_stop_tids (wait_for_stop_tids),
-    m_original_wait_for_stop_tids (wait_for_stop_tids),
-    m_request_thread_stop_function (request_thread_stop_function),
-    m_call_after_function (call_after_function),
-    m_error_function (error_function),
-    m_request_stop_on_all_unstopped_threads (false),
-    m_skip_stop_request_tids ()
-    {
-    }
-
-    EventCallAfterThreadsStop (lldb::tid_t triggering_tid,
-                               const StopThreadFunction &request_thread_stop_function,
-                               const ThreadIDFunction &call_after_function,
-                               const ErrorFunction &error_function) :
-    EventBase (),
-    m_triggering_tid (triggering_tid),
-    m_wait_for_stop_tids (),
-    m_original_wait_for_stop_tids (),
-    m_request_thread_stop_function (request_thread_stop_function),
-    m_call_after_function (call_after_function),
-    m_error_function (error_function),
-    m_request_stop_on_all_unstopped_threads (true),
-    m_skip_stop_request_tids ()
-    {
-    }
-
-    EventCallAfterThreadsStop (lldb::tid_t triggering_tid,
-                               const StopThreadFunction &request_thread_stop_function,
-                               const ThreadIDFunction &call_after_function,
-                               const ThreadIDSet &skip_stop_request_tids,
-                               const ErrorFunction &error_function) :
-    EventBase (),
-    m_triggering_tid (triggering_tid),
-    m_wait_for_stop_tids (),
-    m_original_wait_for_stop_tids (),
-    m_request_thread_stop_function (request_thread_stop_function),
-    m_call_after_function (call_after_function),
-    m_error_function (error_function),
-    m_request_stop_on_all_unstopped_threads (true),
-    m_skip_stop_request_tids (skip_stop_request_tids)
-    {
-    }
-
-    lldb::tid_t GetTriggeringTID () const
-    {
-        return m_triggering_tid;
-    }
-
-    ThreadIDSet &
-    GetRemainingWaitTIDs ()
-    {
-        return m_wait_for_stop_tids;
-    }
-
-    const ThreadIDSet &
-    GetRemainingWaitTIDs () const
-    {
-        return m_wait_for_stop_tids;
-    }
-
-
-    const ThreadIDSet &
-    GetInitialWaitTIDs () const
+    // Ensure we know about the thread.
+    auto find_it = m_tid_map.find (tid);
+    if (find_it == m_tid_map.end ())
     {
-        return m_original_wait_for_stop_tids;
+        // We don't know about this thread.  This is an error condition.
+        std::ostringstream error_message;
+        error_message << "error: tid " << tid << " asked to resume but tid is unknown";
+        error_function (error_message.str ());
+        return;
     }
-
-    EventLoopResult
-    ProcessEvent(ThreadStateCoordinator &coordinator) override
-    {
-        // Validate we know about the deferred trigger thread.
-        if (!coordinator.IsKnownThread (m_triggering_tid))
-        {
-            // We don't know about this thread.  This is an error condition.
-            std::ostringstream error_message;
-            error_message << "error: deferred notification tid " << m_triggering_tid << " is unknown";
-            m_error_function (error_message.str ());
-
-            // We bail out here.
-            return eventLoopResultContinue;
-        }
-
-        if (m_request_stop_on_all_unstopped_threads)
-        {
-            RequestStopOnAllRunningThreads (coordinator);
-        }
-        else
-        {
-            if (!RequestStopOnAllSpecifiedThreads (coordinator))
-                return eventLoopResultContinue;
-        }
-
-        if (m_wait_for_stop_tids.empty ())
-        {
-            // We're not waiting for any threads.  Fire off the deferred signal delivery event.
-            NotifyNow ();
+    auto& context = find_it->second;
+    // Tell the thread to resume if we don't already think it is running.
+    const bool is_stopped = context.m_state == ThreadState::Stopped;
+    if (!is_stopped)
+    {
+        // It's not an error, just a log, if the error_when_already_running flag is not set.
+        // This covers cases where, for instance, we're just trying to resume all threads
+        // from the user side.
+        if (!error_when_already_running)
+        {
+            Log ("ThreadStateCoordinator::%s tid %" PRIu64 " optional resume skipped since it is already running",
+                             __FUNCTION__,
+                             tid);
         }
         else
         {
-            // The real meat of this class: wait until all
-            // the thread stops (or thread deaths) come in
-            // before firing off that the triggering signal
-            // arrived.
-            coordinator.SetPendingNotification (shared_from_this ());
+            // Skip the resume call - we have tracked it to be running.  And we unconditionally
+            // expected to resume this thread.  Flag this as an error.
+            std::ostringstream error_message;
+            error_message << "error: tid " << tid << " asked to resume but we think it is already running";
+            error_function (error_message.str ());
         }
 
-        return eventLoopResultContinue;
+        // Error or not, we're done.
+        return;
     }
 
-    // Return true if still pending thread stops waiting; false if no more stops.
-    // If no more pending stops, signal.
-    bool
-    RemoveThreadStopRequirementAndMaybeSignal (lldb::tid_t tid)
+    // Before we do the resume below, first check if we have a pending
+    // stop notification this is currently or was previously waiting for
+    // this thread to stop.  This is potentially a buggy situation since
+    // we're ostensibly waiting for threads to stop before we send out the
+    // pending notification, and here we are resuming one before we send
+    // out the pending stop notification.
+    if (m_pending_notification_up)
     {
-        // Remove this tid if it was in it.
-        m_wait_for_stop_tids.erase (tid);
-
-        // Fire pending notification if no pending thread stops remain.
-        if (m_wait_for_stop_tids.empty ())
+        if (m_pending_notification_up->wait_for_stop_tids.count (tid) > 0)
         {
-            // Fire the pending notification now.
-            NotifyNow ();
-            return false;
+            Log ("ThreadStateCoordinator::%s about to resume tid %" PRIu64 " per explicit request but we have a pending stop notification (tid %" PRIu64 ") that is actively waiting for this thread to stop. Valid sequence of events?", __FUNCTION__, tid, m_pending_notification_up->triggering_tid);
         }
-
-        // Still have pending thread stops.
-        return true;
-    }
-
-    void
-    AddThreadStopRequirement (lldb::tid_t tid)
-    {
-        // Add this tid.
-        auto insert_result = m_wait_for_stop_tids.insert (tid);
-
-        // If it was really added, send the stop request to it.
-        if (insert_result.second)
-            m_request_thread_stop_function (tid);
-    }
-
-    std::string
-    GetDescription () override
-    {
-        std::ostringstream description;
-        description << "EventCallAfterThreadsStop (triggering_tid=" << m_triggering_tid << ", request_stop_on_all_unstopped_threads=" << m_request_stop_on_all_unstopped_threads << ", skip_stop_request_tids.size()=" << m_skip_stop_request_tids.size () << ")";
-        return description.str ();
-    }
-
-private:
-
-    void
-    NotifyNow ()
-    {
-        m_call_after_function (m_triggering_tid);
-    }
-
-    bool
-    RequestStopOnAllSpecifiedThreads (ThreadStateCoordinator &coordinator)
-    {
-        // Request a stop for all the thread stops that need to be stopped
-        // and are not already known to be stopped.  Keep a list of all the
-        // threads from which we still need to hear a stop reply.
-
-        ThreadIDSet sent_tids;
-        for (auto tid : m_wait_for_stop_tids)
+        else if (m_pending_notification_up->original_wait_for_stop_tids.count (tid) > 0)
         {
-            // Validate we know about all tids for which we must first receive a stop before
-            // triggering the deferred stop notification.
-            auto find_it = coordinator.m_tid_map.find (tid);
-            if (find_it == coordinator.m_tid_map.end ())
+            Log ("ThreadStateCoordinator::%s about to resume tid %" PRIu64 " per explicit request but we have a pending stop notification (tid %" PRIu64 ") that hasn't fired yet and this is one of the threads we had been waiting on (and already marked satisfied for this tid). Valid sequence of events?", __FUNCTION__, tid, m_pending_notification_up->triggering_tid);
+            for (auto tid : m_pending_notification_up->wait_for_stop_tids)
             {
-                // This is an error.  We shouldn't be asking for waiting pids that aren't known.
-                // NOTE: we may be stripping out the specification of wait tids and handle this
-                // automatically, in which case this state can never occur.
-                std::ostringstream error_message;
-                error_message << "error: deferred notification for tid " << m_triggering_tid << " specified an unknown/untracked pending stop tid " << m_triggering_tid;
-                m_error_function (error_message.str ());
-
-                // Bail out here.
-                return false;
-            }
-
-            // If the pending stop thread is currently running, we need to send it a stop request.
-            auto& context = find_it->second;
-            if (context.m_state == ThreadState::Running)
-            {
-                RequestThreadStop (tid, coordinator, context);
-                sent_tids.insert (tid);
+                Log ("ThreadStateCoordinator::%s tid %" PRIu64 " deferred stop notification still waiting on tid  %" PRIu64,
+                                 __FUNCTION__,
+                                 m_pending_notification_up->triggering_tid,
+                                 tid);
             }
         }
-
-        // We only need to wait for the sent_tids - so swap our wait set
-        // to the sent tids.  The rest are already stopped and we won't
-        // be receiving stop notifications for them.
-        m_wait_for_stop_tids.swap (sent_tids);
-
-        // Succeeded, keep running.
-        return true;
     }
 
-    void
-    RequestStopOnAllRunningThreads (ThreadStateCoordinator &coordinator)
+    // Request a resume.  We expect this to be synchronous and the system
+    // to reflect it is running after this completes.
+    const auto error = request_thread_resume_function (tid, false);
+    if (error.Success ())
     {
-        // Request a stop for all the thread stops that need to be stopped
-        // and are not already known to be stopped.  Keep a list of all the
-        // threads from which we still need to hear a stop reply.
-
-        ThreadIDSet sent_tids;
-        for (auto it = coordinator.m_tid_map.begin(); it != coordinator.m_tid_map.end(); ++it)
-        {
-            // We only care about threads not stopped.
-            const bool running = it->second.m_state == ThreadState::Running;
-            if (running)
-            {
-                const lldb::tid_t tid = it->first;
-
-                // Request this thread stop if the tid stop request is not explicitly ignored.
-                const bool skip_stop_request = m_skip_stop_request_tids.count (tid) > 0;
-                if (!skip_stop_request)
-                    RequestThreadStop (tid, coordinator, it->second);
-
-                // Even if we skipped sending the stop request for other reasons (like stepping),
-                // we still need to wait for that stepping thread to notify completion/stop.
-                sent_tids.insert (tid);
-            }
-        }
-
-        // Set the wait list to the set of tids for which we requested stops.
-        m_wait_for_stop_tids.swap (sent_tids);
+        // Now mark it is running.
+        context.m_state = ThreadState::Running;
+        context.m_request_resume_function = request_thread_resume_function;
     }
-
-    void
-    RequestThreadStop (lldb::tid_t tid, ThreadStateCoordinator &coordinator, ThreadContext& context)
+    else
     {
-        const auto error = m_request_thread_stop_function (tid);
-        if (error.Success ())
-        {
-            context.m_stop_requested = true;
-        }
-        else
-        {
-            coordinator.Log ("EventCallAfterThreadsStop::%s failed to request thread stop tid  %" PRIu64 ": %s",
-                             __FUNCTION__, tid, error.AsCString ());
-        }
+        Log ("ThreadStateCoordinator::%s failed to resume thread tid  %" PRIu64 ": %s",
+                         __FUNCTION__, tid, error.AsCString ());
     }
 
-    const lldb::tid_t m_triggering_tid;
-    ThreadIDSet m_wait_for_stop_tids;
-    const ThreadIDSet m_original_wait_for_stop_tids;
-    StopThreadFunction m_request_thread_stop_function;
-    ThreadIDFunction m_call_after_function;
-    ErrorFunction m_error_function;
-    const bool m_request_stop_on_all_unstopped_threads;
-    ThreadIDSet m_skip_stop_request_tids;
-};
+    return;
+}
 
 //===----------------------------------------------------------------------===//
 
-class ThreadStateCoordinator::EventReset : public ThreadStateCoordinator::EventBase
+ThreadStateCoordinator::ThreadStateCoordinator (const LogFunction &log_function) :
+    m_log_function (log_function),
+    m_tid_map (),
+    m_log_event_processing (false)
 {
-public:
-    EventReset ():
-    EventBase ()
-    {
-    }
-
-    EventLoopResult
-    ProcessEvent(ThreadStateCoordinator &coordinator) override
-    {
-        coordinator.ResetNow ();
-        return eventLoopResultContinue;
-    }
-
-    std::string
-    GetDescription () override
-    {
-        return "EventReset";
-    }
-};
-
-//===----------------------------------------------------------------------===//
+}
 
-class ThreadStateCoordinator::EventThreadStopped : public ThreadStateCoordinator::EventBase
+void
+ThreadStateCoordinator::CallAfterThreadsStop (const lldb::tid_t triggering_tid,
+                                              const ThreadIDSet &wait_for_stop_tids,
+                                              const StopThreadFunction &request_thread_stop_function,
+                                              const ThreadIDFunction &call_after_function,
+                                              const ErrorFunction &error_function)
 {
-public:
-    EventThreadStopped (lldb::tid_t tid,
-                        bool initiated_by_llgs,
-                        const ErrorFunction &error_function):
-    EventBase (),
-    m_tid (tid),
-    m_initiated_by_llgs (initiated_by_llgs),
-    m_error_function (error_function)
-    {
-    }
+    std::lock_guard<std::mutex> lock(m_event_mutex);
 
-    EventLoopResult
-    ProcessEvent(ThreadStateCoordinator &coordinator) override
+    if (m_log_event_processing)
     {
-        coordinator.ThreadDidStop (m_tid, m_initiated_by_llgs, m_error_function);
-        return eventLoopResultContinue;
+        Log ("ThreadStateCoordinator::%s about to process event: (triggering_tid: %" PRIu64 ", wait_for_stop_tids.size(): %zd)",
+                __FUNCTION__, triggering_tid, wait_for_stop_tids.size());
     }
 
-    std::string
-    GetDescription () override
+    DoCallAfterThreadsStop(PendingNotificationUP(new PendingNotification(
+                triggering_tid, wait_for_stop_tids, request_thread_stop_function,
+                call_after_function, error_function)));
+
+    if (m_log_event_processing)
     {
-        std::ostringstream description;
-        description << "EventThreadStopped (tid=" << m_tid << ")";
-        return description.str ();
+        Log ("ThreadStateCoordinator::%s event processing done", __FUNCTION__);
     }
+}
 
-private:
-
-    const lldb::tid_t m_tid;
-    const bool m_initiated_by_llgs;
-    ErrorFunction m_error_function;
-};
-
-//===----------------------------------------------------------------------===//
-
-class ThreadStateCoordinator::EventThreadCreate : public ThreadStateCoordinator::EventBase
+void
+ThreadStateCoordinator::CallAfterRunningThreadsStop (const lldb::tid_t triggering_tid,
+                                                     const StopThreadFunction &request_thread_stop_function,
+                                                     const ThreadIDFunction &call_after_function,
+                                                     const ErrorFunction &error_function)
 {
-public:
-    EventThreadCreate (lldb::tid_t tid,
-                       bool is_stopped,
-                       const ErrorFunction &error_function):
-    EventBase (),
-    m_tid (tid),
-    m_is_stopped (is_stopped),
-    m_error_function (error_function)
-    {
-    }
+    std::lock_guard<std::mutex> lock(m_event_mutex);
 
-    EventLoopResult
-    ProcessEvent(ThreadStateCoordinator &coordinator) override
+    if (m_log_event_processing)
     {
-        coordinator.ThreadWasCreated (m_tid, m_is_stopped, m_error_function);
-        return eventLoopResultContinue;
+        Log ("ThreadStateCoordinator::%s about to process event: (triggering_tid: %" PRIu64 ")",
+                __FUNCTION__, triggering_tid);
     }
 
-    std::string
-    GetDescription () override
+    DoCallAfterThreadsStop(PendingNotificationUP(new PendingNotification(
+                triggering_tid,
+                request_thread_stop_function,
+                call_after_function,
+                error_function)));
+
+    if (m_log_event_processing)
     {
-        std::ostringstream description;
-        description << "EventThreadCreate (tid=" << m_tid << ", " << (m_is_stopped ? "stopped" : "running") << ")";
-        return description.str ();
+        Log ("ThreadStateCoordinator::%s event processing done", __FUNCTION__);
     }
+}
 
-private:
-
-    const lldb::tid_t m_tid;
-    const bool m_is_stopped;
-    ErrorFunction m_error_function;
-};
-
-//===----------------------------------------------------------------------===//
-
-class ThreadStateCoordinator::EventThreadDeath : public ThreadStateCoordinator::EventBase
+void
+ThreadStateCoordinator::CallAfterRunningThreadsStopWithSkipTIDs (lldb::tid_t triggering_tid,
+                                                                 const ThreadIDSet &skip_stop_request_tids,
+                                                                 const StopThreadFunction &request_thread_stop_function,
+                                                                 const ThreadIDFunction &call_after_function,
+                                                                 const ErrorFunction &error_function)
 {
-public:
-    EventThreadDeath (lldb::tid_t tid,
-                      const ErrorFunction &error_function):
-    EventBase (),
-    m_tid (tid),
-    m_error_function (error_function)
-    {
-    }
+    std::lock_guard<std::mutex> lock(m_event_mutex);
 
-    EventLoopResult
-    ProcessEvent(ThreadStateCoordinator &coordinator) override
+    if (m_log_event_processing)
     {
-        coordinator.ThreadDidDie (m_tid, m_error_function);
-        return eventLoopResultContinue;
+        Log ("ThreadStateCoordinator::%s about to process event: (triggering_tid: %" PRIu64 ", skip_stop_request_tids.size(): %zd)",
+                __FUNCTION__, triggering_tid, skip_stop_request_tids.size());
     }
 
-    std::string
-    GetDescription () override
+    DoCallAfterThreadsStop(PendingNotificationUP(new PendingNotification(
+                triggering_tid,
+                request_thread_stop_function,
+                call_after_function,
+                skip_stop_request_tids,
+                error_function)));
+
+    if (m_log_event_processing)
     {
-        std::ostringstream description;
-        description << "EventThreadDeath (tid=" << m_tid << ")";
-        return description.str ();
+        Log ("ThreadStateCoordinator::%s event processing done", __FUNCTION__);
     }
+}
 
-private:
-
-    const lldb::tid_t m_tid;
-    ErrorFunction m_error_function;
-};
-
-//===----------------------------------------------------------------------===//
-
-class ThreadStateCoordinator::EventRequestResume : public ThreadStateCoordinator::EventBase
+void
+ThreadStateCoordinator::SignalIfRequirementsSatisfied()
 {
-public:
-    EventRequestResume (lldb::tid_t tid,
-                        const ResumeThreadFunction &request_thread_resume_function,
-                        const ErrorFunction &error_function,
-                        bool error_when_already_running):
-    EventBase (),
-    m_tid (tid),
-    m_request_thread_resume_function (request_thread_resume_function),
-    m_error_function (error_function),
-    m_error_when_already_running (error_when_already_running)
+    if (m_pending_notification_up && m_pending_notification_up->wait_for_stop_tids.empty ())
     {
+        m_pending_notification_up->call_after_function(m_pending_notification_up->triggering_tid);
+        m_pending_notification_up.reset();
     }
+}
 
-    EventLoopResult
-    ProcessEvent(ThreadStateCoordinator &coordinator) override
-    {
-        // Ensure we know about the thread.
-        auto find_it = coordinator.m_tid_map.find (m_tid);
-        if (find_it == coordinator.m_tid_map.end ())
-        {
-            // We don't know about this thread.  This is an error condition.
+bool
+ThreadStateCoordinator::RequestStopOnAllSpecifiedThreads()
+{
+    // Request a stop for all the thread stops that need to be stopped
+    // and are not already known to be stopped.  Keep a list of all the
+    // threads from which we still need to hear a stop reply.
+
+    ThreadIDSet sent_tids;
+    for (auto tid : m_pending_notification_up->wait_for_stop_tids)
+    {
+        // Validate we know about all tids for which we must first receive a stop before
+        // triggering the deferred stop notification.
+        auto find_it = m_tid_map.find (tid);
+        if (find_it == m_tid_map.end ())
+        {
+            // This is an error.  We shouldn't be asking for waiting pids that aren't known.
+            // NOTE: we may be stripping out the specification of wait tids and handle this
+            // automatically, in which case this state can never occur.
             std::ostringstream error_message;
-            error_message << "error: tid " << m_tid << " asked to resume but tid is unknown";
-            m_error_function (error_message.str ());
-            return eventLoopResultContinue;
-        }
-        auto& context = find_it->second;
-        // Tell the thread to resume if we don't already think it is running.
-        const bool is_stopped = context.m_state == ThreadState::Stopped;
-        if (!is_stopped)
-        {
-            // It's not an error, just a log, if the m_already_running_no_error flag is set.
-            // This covers cases where, for instance, we're just trying to resume all threads
-            // from the user side.
-            if (!m_error_when_already_running)
-            {
-                coordinator.Log ("EventRequestResume::%s tid %" PRIu64 " optional resume skipped since it is already running",
-                                 __FUNCTION__,
-                                 m_tid);
-            }
-            else
-            {
-                // Skip the resume call - we have tracked it to be running.  And we unconditionally
-                // expected to resume this thread.  Flag this as an error.
-                std::ostringstream error_message;
-                error_message << "error: tid " << m_tid << " asked to resume but we think it is already running";
-                m_error_function (error_message.str ());
-            }
+            error_message << "error: deferred notification for tid " << m_pending_notification_up->triggering_tid << " specified an unknown/untracked pending stop tid " << m_pending_notification_up->triggering_tid;
+            m_pending_notification_up->error_function (error_message.str ());
 
-            // Error or not, we're done.
-            return eventLoopResultContinue;
-        }
-
-        // Before we do the resume below, first check if we have a pending
-        // stop notification this is currently or was previously waiting for
-        // this thread to stop.  This is potentially a buggy situation since
-        // we're ostensibly waiting for threads to stop before we send out the
-        // pending notification, and here we are resuming one before we send
-        // out the pending stop notification.
-        const EventCallAfterThreadsStop *const pending_stop_notification = coordinator.GetPendingThreadStopNotification ();
-        if (pending_stop_notification)
-        {
-            if (pending_stop_notification->GetRemainingWaitTIDs ().count (m_tid) > 0)
-            {
-                coordinator.Log ("EventRequestResume::%s about to resume tid %" PRIu64 " per explicit request but we have a pending stop notification (tid %" PRIu64 ") that is actively waiting for this thread to stop. Valid sequence of events?", __FUNCTION__, m_tid, pending_stop_notification->GetTriggeringTID ());
-            }
-            else if (pending_stop_notification->GetInitialWaitTIDs ().count (m_tid) > 0)
-            {
-                coordinator.Log ("EventRequestResume::%s about to resume tid %" PRIu64 " per explicit request but we have a pending stop notification (tid %" PRIu64 ") that hasn't fired yet and this is one of the threads we had been waiting on (and already marked satisfied for this tid). Valid sequence of events?", __FUNCTION__, m_tid, pending_stop_notification->GetTriggeringTID ());
-                for (auto tid : pending_stop_notification->GetRemainingWaitTIDs ())
-                {
-                    coordinator.Log ("EventRequestResume::%s tid %" PRIu64 " deferred stop notification still waiting on tid  %" PRIu64,
-                                     __FUNCTION__,
-                                     pending_stop_notification->GetTriggeringTID (),
-                                     tid);
-                }
-            }
+            // Bail out here.
+            return false;
         }
 
-        // Request a resume.  We expect this to be synchronous and the system
-        // to reflect it is running after this completes.
-        const auto error = m_request_thread_resume_function (m_tid, false);
-        if (error.Success ())
-        {
-            // Now mark it is running.
-            context.m_state = ThreadState::Running;
-            context.m_request_resume_function = m_request_thread_resume_function;
-        }
-        else
+        // If the pending stop thread is currently running, we need to send it a stop request.
+        auto& context = find_it->second;
+        if (context.m_state == ThreadState::Running)
         {
-            coordinator.Log ("EventRequestResume::%s failed to resume thread tid  %" PRIu64 ": %s",
-                             __FUNCTION__, m_tid, error.AsCString ());
+            RequestThreadStop (tid, context);
+            sent_tids.insert (tid);
         }
-
-        return eventLoopResultContinue;
     }
+    // We only need to wait for the sent_tids - so swap our wait set
+    // to the sent tids.  The rest are already stopped and we won't
+    // be receiving stop notifications for them.
+    m_pending_notification_up->wait_for_stop_tids.swap (sent_tids);
 
-    std::string
-    GetDescription () override
-    {
-        std::ostringstream description;
-        description << "EventRequestResume (tid=" << m_tid << ")";
-        return description.str ();
-    }
-
-private:
-
-    const lldb::tid_t m_tid;
-    ResumeThreadFunction m_request_thread_resume_function;
-    ErrorFunction m_error_function;
-    const bool m_error_when_already_running;
-};
-
-//===----------------------------------------------------------------------===//
-
-ThreadStateCoordinator::ThreadStateCoordinator (const LogFunction &log_function) :
-    m_log_function (log_function),
-    m_tid_map (),
-    m_log_event_processing (false)
-{
+    // Succeeded, keep running.
+    return true;
 }
 
 void
-ThreadStateCoordinator::SetPendingNotification (const EventBaseSP &event_sp)
+ThreadStateCoordinator::RequestStopOnAllRunningThreads()
 {
-    assert (event_sp && "null event_sp");
-    if (!event_sp)
-        return;
-
-    const EventCallAfterThreadsStop *new_call_after_event = static_cast<EventCallAfterThreadsStop*> (event_sp.get ());
+    // Request a stop for all the thread stops that need to be stopped
+    // and are not already known to be stopped.  Keep a list of all the
+    // threads from which we still need to hear a stop reply.
 
-    EventCallAfterThreadsStop *const prev_call_after_event = GetPendingThreadStopNotification ();
-    if (prev_call_after_event)
+    ThreadIDSet sent_tids;
+    for (auto it = m_tid_map.begin(); it != m_tid_map.end(); ++it)
     {
-        // Yikes - we've already got a pending signal notification in progress.
-        // Log this info.  We lose the pending notification here.
-        Log ("ThreadStateCoordinator::%s dropping existing pending signal notification for tid %" PRIu64 ", to be replaced with signal for tid %" PRIu64,
-                   __FUNCTION__,
-                   prev_call_after_event->GetTriggeringTID (),
-                   new_call_after_event->GetTriggeringTID ());
-    }
+        // We only care about threads not stopped.
+        const bool running = it->second.m_state == ThreadState::Running;
+        if (running)
+        {
+            const lldb::tid_t tid = it->first;
 
-    m_pending_notification_sp = event_sp;
-}
+            // Request this thread stop if the tid stop request is not explicitly ignored.
+            const bool skip_stop_request = m_pending_notification_up->skip_stop_request_tids.count (tid) > 0;
+            if (!skip_stop_request)
+                RequestThreadStop (tid, it->second);
 
-void
-ThreadStateCoordinator::CallAfterThreadsStop (const lldb::tid_t triggering_tid,
-                                              const ThreadIDSet &wait_for_stop_tids,
-                                              const StopThreadFunction &request_thread_stop_function,
-                                              const ThreadIDFunction &call_after_function,
-                                              const ErrorFunction &error_function)
-{
-    ProcessEvent(EventBaseSP(new EventCallAfterThreadsStop (triggering_tid,
-                wait_for_stop_tids,
-                request_thread_stop_function,
-                call_after_function,
-                error_function)));
-}
+            // Even if we skipped sending the stop request for other reasons (like stepping),
+            // we still need to wait for that stepping thread to notify completion/stop.
+            sent_tids.insert (tid);
+        }
+    }
 
-void
-ThreadStateCoordinator::CallAfterRunningThreadsStop (const lldb::tid_t triggering_tid,
-                                                     const StopThreadFunction &request_thread_stop_function,
-                                                     const ThreadIDFunction &call_after_function,
-                                                     const ErrorFunction &error_function)
-{
-    ProcessEvent(EventBaseSP(new EventCallAfterThreadsStop (triggering_tid,
-                request_thread_stop_function,
-                call_after_function,
-                error_function)));
+    // Set the wait list to the set of tids for which we requested stops.
+    m_pending_notification_up->wait_for_stop_tids.swap (sent_tids);
 }
 
 void
-ThreadStateCoordinator::CallAfterRunningThreadsStopWithSkipTIDs (lldb::tid_t triggering_tid,
-                                                                 const ThreadIDSet &skip_stop_request_tids,
-                                                                 const StopThreadFunction &request_thread_stop_function,
-                                                                 const ThreadIDFunction &call_after_function,
-                                                                 const ErrorFunction &error_function)
+ThreadStateCoordinator::RequestThreadStop (lldb::tid_t tid, ThreadContext& context)
 {
-    ProcessEvent(EventBaseSP(new EventCallAfterThreadsStop (triggering_tid,
-                request_thread_stop_function,
-                call_after_function,
-                skip_stop_request_tids,
-                error_function)));
+    const auto error = m_pending_notification_up->request_thread_stop_function (tid);
+    if (error.Success ())
+        context.m_stop_requested = true;
+    else
+    {
+        Log ("ThreadStateCoordinator::%s failed to request thread stop tid  %" PRIu64 ": %s",
+                         __FUNCTION__, tid, error.AsCString ());
+    }
 }
 
 
 void
-ThreadStateCoordinator::ThreadDidStop (lldb::tid_t tid, bool initiated_by_llgs, ErrorFunction &error_function)
+ThreadStateCoordinator::ThreadDidStop (lldb::tid_t tid, bool initiated_by_llgs, const ErrorFunction &error_function)
 {
     // Ensure we know about the thread.
     auto find_it = m_tid_map.find (tid);
@@ -655,15 +318,10 @@ ThreadStateCoordinator::ThreadDidStop (l
     context.m_stop_requested = false;
 
     // If we have a pending notification, remove this from the set.
-    EventCallAfterThreadsStop *const call_after_event = GetPendingThreadStopNotification ();
-    if (call_after_event)
+    if (m_pending_notification_up)
     {
-        const bool pending_stops_remain = call_after_event->RemoveThreadStopRequirementAndMaybeSignal (tid);
-        if (!pending_stops_remain)
-        {
-            // Clear the pending notification now.
-            m_pending_notification_sp.reset ();
-        }
+        m_pending_notification_up->wait_for_stop_tids.erase(tid);
+        SignalIfRequirementsSatisfied();
     }
 
     if (initiated_by_llgs && context.m_request_resume_function && !stop_was_requested)
@@ -685,7 +343,49 @@ ThreadStateCoordinator::ThreadDidStop (l
 }
 
 void
-ThreadStateCoordinator::ThreadWasCreated (lldb::tid_t tid, bool is_stopped, ErrorFunction &error_function)
+ThreadStateCoordinator::DoCallAfterThreadsStop(PendingNotificationUP &&notification_up)
+{
+    // Validate we know about the deferred trigger thread.
+    if (!IsKnownThread (notification_up->triggering_tid))
+    {
+        // We don't know about this thread.  This is an error condition.
+        std::ostringstream error_message;
+        error_message << "error: deferred notification tid " << notification_up->triggering_tid << " is unknown";
+        notification_up->error_function (error_message.str ());
+
+        // We bail out here.
+        return;
+    }
+
+    if (m_pending_notification_up)
+    {
+        // Yikes - we've already got a pending signal notification in progress.
+        // Log this info.  We lose the pending notification here.
+        Log ("ThreadStateCoordinator::%s dropping existing pending signal notification for tid %" PRIu64 ", to be replaced with signal for tid %" PRIu64,
+                   __FUNCTION__,
+                   m_pending_notification_up->triggering_tid,
+                   notification_up->triggering_tid);
+    }
+    m_pending_notification_up = std::move(notification_up);
+
+    if (m_pending_notification_up->request_stop_on_all_unstopped_threads)
+        RequestStopOnAllRunningThreads();
+    else
+    {
+        if (!RequestStopOnAllSpecifiedThreads())
+            return;
+    }
+
+    if (m_pending_notification_up->wait_for_stop_tids.empty ())
+    {
+        // We're not waiting for any threads.  Fire off the deferred signal delivery event.
+        m_pending_notification_up->call_after_function(m_pending_notification_up->triggering_tid);
+        m_pending_notification_up.reset();
+    }
+}
+
+void
+ThreadStateCoordinator::ThreadWasCreated (lldb::tid_t tid, bool is_stopped, const ErrorFunction &error_function)
 {
     // Ensure we don't already know about the thread.
     auto find_it = m_tid_map.find (tid);
@@ -703,17 +403,17 @@ ThreadStateCoordinator::ThreadWasCreated
     ctx.m_state = (is_stopped) ? ThreadState::Stopped : ThreadState::Running;
     m_tid_map[tid] = std::move(ctx);
 
-    EventCallAfterThreadsStop *const call_after_event = GetPendingThreadStopNotification ();
-    if (call_after_event && !is_stopped)
+    if (m_pending_notification_up && !is_stopped)
     {
-        // Tell the pending notification that we need to wait
-        // for this new thread to stop.
-        call_after_event->AddThreadStopRequirement (tid);
+        // We will need to wait for this new thread to stop as well before firing the
+        // notification.
+        m_pending_notification_up->wait_for_stop_tids.insert(tid);
+        m_pending_notification_up->request_thread_stop_function(tid);
     }
 }
 
 void
-ThreadStateCoordinator::ThreadDidDie (lldb::tid_t tid, ErrorFunction &error_function)
+ThreadStateCoordinator::ThreadDidDie (lldb::tid_t tid, const ErrorFunction &error_function)
 {
     // Ensure we know about the thread.
     auto find_it = m_tid_map.find (tid);
@@ -732,32 +432,14 @@ ThreadStateCoordinator::ThreadDidDie (ll
     m_tid_map.erase (find_it);
 
     // If we have a pending notification, remove this from the set.
-    EventCallAfterThreadsStop *const call_after_event = GetPendingThreadStopNotification ();
-    if (call_after_event)
+    if (m_pending_notification_up)
     {
-        const bool pending_stops_remain = call_after_event->RemoveThreadStopRequirementAndMaybeSignal (tid);
-        if (!pending_stops_remain)
-        {
-            // Clear the pending notification now.
-            m_pending_notification_sp.reset ();
-        }
+        m_pending_notification_up->wait_for_stop_tids.erase(tid);
+        SignalIfRequirementsSatisfied();
     }
 }
 
 void
-ThreadStateCoordinator::ResetNow ()
-{
-    // Clear the pending notification if there was one.
-    m_pending_notification_sp.reset ();
-
-    // Clear the stop map - we no longer know anything about any thread state.
-    // The caller is expected to reset thread states for all threads, and we
-    // will assume anything we haven't heard about is running and requires a
-    // stop.
-    m_tid_map.clear ();
-}
-
-void
 ThreadStateCoordinator::Log (const char *format, ...)
 {
     va_list args;
@@ -773,7 +455,20 @@ ThreadStateCoordinator::NotifyThreadStop
                                           bool initiated_by_llgs,
                                           const ErrorFunction &error_function)
 {
-    ProcessEvent(EventBaseSP(new EventThreadStopped (tid, initiated_by_llgs, error_function)));
+    std::lock_guard<std::mutex> lock(m_event_mutex);
+
+    if (m_log_event_processing)
+    {
+        Log ("ThreadStateCoordinator::%s about to process event: (tid: %" PRIu64 ", %sinitiated by llgs)",
+                __FUNCTION__, tid, initiated_by_llgs?"":"not ");
+    }
+
+    ThreadDidStop (tid, initiated_by_llgs, error_function);
+
+    if (m_log_event_processing)
+    {
+        Log ("ThreadStateCoordinator::%s event processing done", __FUNCTION__);
+    }
 }
 
 void
@@ -781,7 +476,20 @@ ThreadStateCoordinator::RequestThreadRes
                                              const ResumeThreadFunction &request_thread_resume_function,
                                              const ErrorFunction &error_function)
 {
-    ProcessEvent(EventBaseSP(new EventRequestResume (tid, request_thread_resume_function, error_function, true)));
+    std::lock_guard<std::mutex> lock(m_event_mutex);
+
+    if (m_log_event_processing)
+    {
+        Log ("ThreadStateCoordinator::%s about to process event: (tid: %" PRIu64 ")",
+                __FUNCTION__, tid);
+    }
+
+    DoResume(tid, request_thread_resume_function, error_function, true);
+
+    if (m_log_event_processing)
+    {
+        Log ("ThreadStateCoordinator::%s event processing done", __FUNCTION__);
+    }
 }
 
 void
@@ -789,7 +497,20 @@ ThreadStateCoordinator::RequestThreadRes
                                                      const ResumeThreadFunction &request_thread_resume_function,
                                                      const ErrorFunction &error_function)
 {
-    ProcessEvent(EventBaseSP(new EventRequestResume (tid, request_thread_resume_function, error_function, false)));
+    std::lock_guard<std::mutex> lock(m_event_mutex);
+
+    if (m_log_event_processing)
+    {
+        Log ("ThreadStateCoordinator::%s about to process event: (tid: %" PRIu64 ")",
+                __FUNCTION__, tid);
+    }
+
+    DoResume (tid, request_thread_resume_function, error_function, false);
+
+    if (m_log_event_processing)
+    {
+        Log ("ThreadStateCoordinator::%s event processing done", __FUNCTION__);
+    }
 }
 
 void
@@ -797,53 +518,71 @@ ThreadStateCoordinator::NotifyThreadCrea
                                             bool is_stopped,
                                             const ErrorFunction &error_function)
 {
-    ProcessEvent(EventBaseSP(new EventThreadCreate (tid, is_stopped, error_function)));
+    std::lock_guard<std::mutex> lock(m_event_mutex);
+
+    if (m_log_event_processing)
+    {
+        Log ("ThreadStateCoordinator::%s about to process event: (tid: %" PRIu64 ", is %sstopped)",
+                __FUNCTION__, tid, is_stopped?"":"not ");
+    }
+
+    ThreadWasCreated (tid, is_stopped, error_function);
+
+    if (m_log_event_processing)
+    {
+        Log ("ThreadStateCoordinator::%s event processing done", __FUNCTION__);
+    }
 }
 
 void
 ThreadStateCoordinator::NotifyThreadDeath (lldb::tid_t tid,
                                            const ErrorFunction &error_function)
 {
-    ProcessEvent(EventBaseSP(new EventThreadDeath (tid, error_function)));
-}
+    std::lock_guard<std::mutex> lock(m_event_mutex);
 
-void
-ThreadStateCoordinator::ResetForExec ()
-{
-    ProcessEvent(EventBaseSP(new EventReset()));
+    if (m_log_event_processing)
+    {
+        Log ("ThreadStateCoordinator::%s about to process event: (tid: %" PRIu64 ")", __FUNCTION__, tid);
+    }
+
+    ThreadDidDie(tid, error_function);
+
+    if (m_log_event_processing)
+    {
+        Log ("ThreadStateCoordinator::%s event processing done", __FUNCTION__);
+    }
 }
 
 void
-ThreadStateCoordinator::ProcessEvent (const EventBaseSP &event_sp)
+ThreadStateCoordinator::ResetForExec ()
 {
     std::lock_guard<std::mutex> lock(m_event_mutex);
 
     if (m_log_event_processing)
     {
-        Log ("ThreadStateCoordinator::%s about to process event: %s", __FUNCTION__, event_sp->GetDescription ().c_str ());
+        Log ("ThreadStateCoordinator::%s about to process event", __FUNCTION__);
     }
 
-    // Process the event.
-    event_sp->ProcessEvent (*this);
+    // Clear the pending notification if there was one.
+    m_pending_notification_up.reset ();
+
+    // Clear the stop map - we no longer know anything about any thread state.
+    // The caller is expected to reset thread states for all threads, and we
+    // will assume anything we haven't heard about is running and requires a
+    // stop.
+    m_tid_map.clear ();
 
     if (m_log_event_processing)
     {
         Log ("ThreadStateCoordinator::%s event processing done", __FUNCTION__);
     }
 }
-
 void
 ThreadStateCoordinator::LogEnableEventProcessing (bool enabled)
 {
     m_log_event_processing = enabled;
 }
 
-ThreadStateCoordinator::EventCallAfterThreadsStop *
-ThreadStateCoordinator::GetPendingThreadStopNotification ()
-{
-    return static_cast<EventCallAfterThreadsStop*> (m_pending_notification_sp.get ());
-}
-
 bool
 ThreadStateCoordinator::IsKnownThread (lldb::tid_t tid) const
 {

Modified: lldb/trunk/source/Plugins/Process/Linux/ThreadStateCoordinator.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Linux/ThreadStateCoordinator.h?rev=236576&r1=236575&r2=236576&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/Linux/ThreadStateCoordinator.h (original)
+++ lldb/trunk/source/Plugins/Process/Linux/ThreadStateCoordinator.h Wed May  6 03:23:47 2015
@@ -29,12 +29,6 @@ namespace process_linux {
         // Typedefs.
         typedef std::unordered_set<lldb::tid_t> ThreadIDSet;
 
-        enum EventLoopResult
-        {
-            eventLoopResultContinue,
-            eventLoopResultStop
-        };
-
         // Callback/block definitions.
         typedef std::function<void (lldb::tid_t tid)> ThreadIDFunction;
         typedef std::function<void (const char *format, va_list args)> LogFunction;
@@ -133,19 +127,6 @@ namespace process_linux {
 
     private:
 
-        // Typedefs.
-        class EventBase;
-
-        class EventCallAfterThreadsStop;
-        class EventThreadStopped;
-        class EventThreadCreate;
-        class EventThreadDeath;
-        class EventRequestResume;
-
-        class EventReset;
-
-        typedef std::shared_ptr<EventBase> EventBaseSP;
-
         enum class ThreadState
         {
             Running,
@@ -160,26 +141,95 @@ namespace process_linux {
         };
         typedef std::unordered_map<lldb::tid_t, ThreadContext> TIDContextMap;
 
+        struct PendingNotification
+        {
+            PendingNotification (lldb::tid_t triggering_tid,
+                                       const ThreadIDSet &wait_for_stop_tids,
+                                       const StopThreadFunction &request_thread_stop_function,
+                                       const ThreadIDFunction &call_after_function,
+                                       const ErrorFunction &error_function):
+            triggering_tid (triggering_tid),
+            wait_for_stop_tids (wait_for_stop_tids),
+            original_wait_for_stop_tids (wait_for_stop_tids),
+            request_thread_stop_function (request_thread_stop_function),
+            call_after_function (call_after_function),
+            error_function (error_function),
+            request_stop_on_all_unstopped_threads (false),
+            skip_stop_request_tids ()
+            {
+            }
+
+            PendingNotification (lldb::tid_t triggering_tid,
+                                       const StopThreadFunction &request_thread_stop_function,
+                                       const ThreadIDFunction &call_after_function,
+                                       const ErrorFunction &error_function) :
+            triggering_tid (triggering_tid),
+            wait_for_stop_tids (),
+            original_wait_for_stop_tids (),
+            request_thread_stop_function (request_thread_stop_function),
+            call_after_function (call_after_function),
+            error_function (error_function),
+            request_stop_on_all_unstopped_threads (true),
+            skip_stop_request_tids ()
+            {
+            }
+
+            PendingNotification (lldb::tid_t triggering_tid,
+                                       const StopThreadFunction &request_thread_stop_function,
+                                       const ThreadIDFunction &call_after_function,
+                                       const ThreadIDSet &skip_stop_request_tids,
+                                       const ErrorFunction &error_function) :
+            triggering_tid (triggering_tid),
+            wait_for_stop_tids (),
+            original_wait_for_stop_tids (),
+            request_thread_stop_function (request_thread_stop_function),
+            call_after_function (call_after_function),
+            error_function (error_function),
+            request_stop_on_all_unstopped_threads (true),
+            skip_stop_request_tids (skip_stop_request_tids)
+            {
+            }
+
+            const lldb::tid_t  triggering_tid;
+            ThreadIDSet        wait_for_stop_tids;
+            const ThreadIDSet  original_wait_for_stop_tids;
+            StopThreadFunction request_thread_stop_function;
+            ThreadIDFunction   call_after_function;
+            ErrorFunction      error_function;
+            const bool         request_stop_on_all_unstopped_threads;
+            ThreadIDSet        skip_stop_request_tids;
+        };
+        typedef std::unique_ptr<PendingNotification> PendingNotificationUP;
+
+        // Fire pending notification if no pending thread stops remain.
+        void SignalIfRequirementsSatisfied();
+
+        bool
+        RequestStopOnAllSpecifiedThreads();
 
-        std::mutex m_event_mutex; // Serializes execution of ProcessEvent.
+        void
+        RequestStopOnAllRunningThreads();
 
         void
-        ProcessEvent (const EventBaseSP &event_sp);
+        RequestThreadStop (lldb::tid_t tid, ThreadContext& context);
+
+        std::mutex m_event_mutex; // Serializes execution of TSC operations.
 
         void
-        SetPendingNotification (const EventBaseSP &event_sp);
+        ThreadDidStop (lldb::tid_t tid, bool initiated_by_llgs, const ErrorFunction &error_function);
 
         void
-        ThreadDidStop (lldb::tid_t tid, bool initiated_by_llgs, ErrorFunction &error_function);
+        DoResume(lldb::tid_t tid, ResumeThreadFunction request_thread_resume_function,
+                ErrorFunction error_function, bool error_when_already_running);
 
         void
-        ThreadWasCreated (lldb::tid_t tid, bool is_stopped, ErrorFunction &error_function);
+        DoCallAfterThreadsStop(PendingNotificationUP &&notification_up);
 
         void
-        ThreadDidDie (lldb::tid_t tid, ErrorFunction &error_function);
+        ThreadWasCreated (lldb::tid_t tid, bool is_stopped, const ErrorFunction &error_function);
 
         void
-        ResetNow ();
+        ThreadDidDie (lldb::tid_t tid, const ErrorFunction &error_function);
 
         bool
         IsKnownThread(lldb::tid_t tid) const;
@@ -187,13 +237,9 @@ namespace process_linux {
         void
         Log (const char *format, ...);
 
-        EventCallAfterThreadsStop *
-        GetPendingThreadStopNotification ();
-
         // Member variables.
         LogFunction m_log_function;
-
-        EventBaseSP m_pending_notification_sp;
+        PendingNotificationUP m_pending_notification_up;
 
         // Maps known TIDs to ThreadContext.
         TIDContextMap m_tid_map;





More information about the lldb-commits mailing list