[Lldb-commits] [lldb] r218629 - thread state coordinator: add exec reset support, remove empty virtual destructors.

Todd Fiala todd.fiala at gmail.com
Mon Sep 29 14:45:21 PDT 2014


Author: tfiala
Date: Mon Sep 29 16:45:21 2014
New Revision: 218629

URL: http://llvm.org/viewvc/llvm-project?rev=218629&view=rev
Log:
thread state coordinator: add exec reset support, remove empty virtual destructors.

Also added a test for the reset handling.  The reset/state clearing happens
as a processed queue event.  The only diff vs. standard processing is that
the exec clears the queue before queueing the activity to clear internal state.
i.e. once we get an exec, we really stop doing any other queue-based activity.

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

Modified: lldb/trunk/gtest/unittest/Plugins/Process/Linux/ThreadStateCoordinatorTest.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/gtest/unittest/Plugins/Process/Linux/ThreadStateCoordinatorTest.cpp?rev=218629&r1=218628&r2=218629&view=diff
==============================================================================
--- lldb/trunk/gtest/unittest/Plugins/Process/Linux/ThreadStateCoordinatorTest.cpp (original)
+++ lldb/trunk/gtest/unittest/Plugins/Process/Linux/ThreadStateCoordinatorTest.cpp Mon Sep 29 16:45:21 2014
@@ -403,3 +403,33 @@ TEST(ThreadStateCoordinatorTest, Existin
     ASSERT_EQ (TRIGGERING_TID, reported_firing_tid);
 }
 
+TEST(ThreadStateCoordinatorTest, DeferredNotificationRemovedByResetForExec)
+{
+    ThreadStateCoordinator coordinator(NOPLogger);
+
+    const lldb::tid_t TRIGGERING_TID = 4105;
+    bool call_after_fired = false;
+    lldb::tid_t reported_firing_tid = 0;
+
+    // Notify we have a trigger that needs to be fired when all threads in the wait tid set have stopped.
+    coordinator.CallAfterThreadsStop (TRIGGERING_TID,
+                                      EMPTY_THREAD_ID_SET,
+                                      [](lldb::tid_t tid) {},
+                                      [&](lldb::tid_t tid) {
+                                          call_after_fired = true;
+                                          reported_firing_tid = tid;
+                                      });
+
+    // Notification trigger shouldn't go off yet.
+    ASSERT_EQ (false, call_after_fired);
+
+    // Now indicate an exec occurred, which will invalidate all state about the process and threads.
+    coordinator.ResetForExec ();
+
+    // Verify the deferred stop notification does *not* fire with the next
+    // process.  It will handle the reset and not the deferred signaling, which
+    // should now be removed.
+    ASSERT_EQ (true, coordinator.ProcessNextEvent ());
+    ASSERT_EQ (false, call_after_fired);
+}
+

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=218629&r1=218628&r2=218629&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/Linux/ThreadStateCoordinator.cpp (original)
+++ lldb/trunk/source/Plugins/Process/Linux/ThreadStateCoordinator.cpp Mon Sep 29 16:45:21 2014
@@ -49,10 +49,6 @@ public:
     {
     }
 
-    ~EventStopCoordinator () override
-    {
-    }
-
     bool
     ProcessEvent(ThreadStateCoordinator &coordinator) override
     {
@@ -77,10 +73,6 @@ public:
     {
     }
 
-    ~EventCallAfterThreadsStop () override
-    {
-    }
-
     lldb::tid_t GetTriggeringTID () const
     {
         return m_triggering_tid;
@@ -181,6 +173,24 @@ private:
 
 //===----------------------------------------------------------------------===//
 
+class ThreadStateCoordinator::EventReset : public ThreadStateCoordinator::EventBase
+{
+public:
+    EventReset ():
+    EventBase ()
+    {
+    }
+
+    bool
+    ProcessEvent(ThreadStateCoordinator &coordinator) override
+    {
+        coordinator.ResetNow ();
+        return true;
+    }
+};
+
+//===----------------------------------------------------------------------===//
+
 class ThreadStateCoordinator::EventThreadStopped : public ThreadStateCoordinator::EventBase
 {
 public:
@@ -190,10 +200,6 @@ public:
     {
     }
 
-    ~EventThreadStopped () override
-    {
-    }
-
     bool
     ProcessEvent(ThreadStateCoordinator &coordinator) override
     {
@@ -217,10 +223,6 @@ public:
     {
     }
 
-    ~EventThreadCreate () override
-    {
-    }
-
     bool
     ProcessEvent(ThreadStateCoordinator &coordinator) override
     {
@@ -244,10 +246,6 @@ public:
     {
     }
 
-    ~EventThreadDeath () override
-    {
-    }
-
     bool
     ProcessEvent(ThreadStateCoordinator &coordinator) override
     {
@@ -387,6 +385,19 @@ ThreadStateCoordinator::ThreadDidDie (ll
 }
 
 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_stop_map.clear ();
+}
+
+void
 ThreadStateCoordinator::Log (const char *format, ...)
 {
     va_list args;
@@ -416,6 +427,26 @@ ThreadStateCoordinator::NotifyThreadDeat
 }
 
 void
+ThreadStateCoordinator::ResetForExec ()
+{
+    std::lock_guard<std::mutex> lock (m_queue_mutex);
+
+    // Remove everything from the queue.  This is the only
+    // state mutation that takes place outside the processing
+    // loop.
+    QueueType empty_queue;
+    m_event_queue.swap (empty_queue);
+
+    // Do the real clear behavior on the the queue to eliminate
+    // the chance that processing of a dequeued earlier event is
+    // overlapping with the clearing of state here.  Push it
+    // directly because we need to have this happen with the lock,
+    // and so far I only have this one place that needs a no-lock
+    // variant.
+    m_event_queue.push (EventBaseSP (new EventReset ()));
+}
+
+void
 ThreadStateCoordinator::StopCoordinator ()
 {
     EnqueueEvent (EventBaseSP (new EventStopCoordinator ()));

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=218629&r1=218628&r2=218629&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/Linux/ThreadStateCoordinator.h (original)
+++ lldb/trunk/source/Plugins/Process/Linux/ThreadStateCoordinator.h Mon Sep 29 16:45:21 2014
@@ -59,6 +59,14 @@ namespace lldb_private
         void
         NotifyThreadDeath (lldb::tid_t tid);
 
+        // Indicate the calling process did an exec and that the thread state
+        // should be 100% cleared.
+        //
+        // Note this will clear out any pending notifications, but will not stop
+        // a notification currently in progress via ProcessNextEvent().
+        void
+        ResetForExec ();
+
         // Indicate when the coordinator should shut down.
         void
         StopCoordinator ();
@@ -77,11 +85,13 @@ namespace lldb_private
         class EventBase;
 
         class EventCallAfterThreadsStop;
-        class EventStopCoordinator;
         class EventThreadStopped;
         class EventThreadCreate;
         class EventThreadDeath;
 
+        class EventStopCoordinator;
+        class EventReset;
+
         typedef std::shared_ptr<EventBase> EventBaseSP;
 
         typedef std::queue<EventBaseSP> QueueType;
@@ -109,6 +119,9 @@ namespace lldb_private
         ThreadDidDie (lldb::tid_t tid);
 
         void
+        ResetNow ();
+
+        void
         Log (const char *format, ...);
 
         // Member variables.
@@ -116,7 +129,7 @@ namespace lldb_private
 
         QueueType m_event_queue;
         // For now we do simple read/write lock strategy with efficient wait-for-data.
-        // We can replace with entirely non-blocking queue later but we still want the
+        // We can replace with an entirely non-blocking queue later but we still want the
         // reader to sleep when nothing is available - this will be a bursty but infrequent
         // event mechanism.
         std::condition_variable m_queue_condition;





More information about the lldb-commits mailing list