[Lldb-commits] [lldb] r218578 - thread state coordinator: added new thread support.
Todd Fiala
todd.fiala at gmail.com
Sat Sep 27 23:50:48 PDT 2014
Author: tfiala
Date: Sun Sep 28 01:50:47 2014
New Revision: 218578
URL: http://llvm.org/viewvc/llvm-project?rev=218578&view=rev
Log:
thread state coordinator: added new thread support.
A new thread arriving while a pending signal notification
is outstanding will (1) add the new thread to the list of
stops expected before the deferred signal notification is
fired, (2) send a stop request for the new thread, and
(3) track the new thread as currently running.
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=218578&r1=218577&r2=218578&view=diff
==============================================================================
--- lldb/trunk/gtest/unittest/Plugins/Process/Linux/ThreadStateCoordinatorTest.cpp (original)
+++ lldb/trunk/gtest/unittest/Plugins/Process/Linux/ThreadStateCoordinatorTest.cpp Sun Sep 28 01:50:47 2014
@@ -318,7 +318,7 @@ TEST(ThreadStateCoordinatorTest, CallAft
ASSERT_EQ (true, request_thread_stop_called);
ASSERT_EQ (PENDING_STOP_TID, request_thread_stop_tid);
- // But we still shouldn't have the deferred signal call go off yet. Need to wait for the stop to be reported.
+ // But we still shouldn't have the deferred signal call go off yet. Need to wait for the death to be reported.
ASSERT_EQ (false, call_after_fired);
// Now report the that the thread with pending stop dies.
@@ -331,6 +331,74 @@ TEST(ThreadStateCoordinatorTest, CallAft
ASSERT_EQ (true, coordinator.ProcessNextEvent ());
// Deferred signal notification should have fired now.
+ ASSERT_EQ (true, call_after_fired);
+ ASSERT_EQ (TRIGGERING_TID, reported_firing_tid);
+}
+
+TEST(ThreadStateCoordinatorTest, ExistingPendingNotificationRequiresStopFromNewThread)
+{
+ ThreadStateCoordinator coordinator(NOPLogger);
+
+ const lldb::tid_t TRIGGERING_TID = 4105;
+ const lldb::tid_t PENDING_STOP_TID = 3;
+
+ ThreadStateCoordinator::ThreadIDSet pending_stop_tids { PENDING_STOP_TID };
+
+ bool call_after_fired = false;
+ lldb::tid_t reported_firing_tid = 0;
+
+ int request_thread_stop_calls = 0;
+ ThreadStateCoordinator::ThreadIDSet request_thread_stop_tids;
+
+ // Notify we have a trigger that needs to be fired when all threads in the wait tid set have stopped.
+ coordinator.CallAfterThreadsStop (TRIGGERING_TID,
+ pending_stop_tids,
+ [&](lldb::tid_t tid) {
+ ++request_thread_stop_calls;
+ request_thread_stop_tids.insert (tid);
+
+ },
+ [&](lldb::tid_t tid) {
+ call_after_fired = true;
+ reported_firing_tid = tid;
+ });
+
+ // Neither trigger should have gone off yet.
+ ASSERT_EQ (false, call_after_fired);
+ ASSERT_EQ (0, request_thread_stop_calls);
+
+ // Process next event.
+ ASSERT_EQ (true, coordinator.ProcessNextEvent ());
+
+ // Now the request thread stop should have been called for the pending stop.
+ ASSERT_EQ (1, request_thread_stop_calls);
+ ASSERT_EQ (true, request_thread_stop_tids.count (PENDING_STOP_TID));
+
+ // But we still shouldn't have the deferred signal call go off yet.
+ ASSERT_EQ (false, call_after_fired);
+
+ // Indicate a new thread has just been created.
+ const lldb::tid_t NEW_THREAD_TID = 1234;
+
+ coordinator.NotifyThreadCreate (NEW_THREAD_TID);
+ ASSERT_EQ (true, coordinator.ProcessNextEvent ());
+
+ // We should have just received a stop request for the new thread id.
+ ASSERT_EQ (2, request_thread_stop_calls);
+ ASSERT_EQ (true, request_thread_stop_tids.count (NEW_THREAD_TID));
+
+ // Now report the original pending tid stopped. This should no longer
+ // trigger the pending notification because we should now require the
+ // new thread to stop too.
+ coordinator.NotifyThreadStop (PENDING_STOP_TID);
+ ASSERT_EQ (true, coordinator.ProcessNextEvent ());
+ ASSERT_EQ (false, call_after_fired);
+
+ // Now notify the new thread stopped.
+ coordinator.NotifyThreadStop (NEW_THREAD_TID);
+ ASSERT_EQ (true, coordinator.ProcessNextEvent ());
+
+ // Deferred signal notification should have fired now.
ASSERT_EQ (true, call_after_fired);
ASSERT_EQ (TRIGGERING_TID, reported_firing_tid);
}
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=218578&r1=218577&r2=218578&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/Linux/ThreadStateCoordinator.cpp (original)
+++ lldb/trunk/source/Plugins/Process/Linux/ThreadStateCoordinator.cpp Sun Sep 28 01:50:47 2014
@@ -153,6 +153,17 @@ public:
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_func (tid);
+ }
+
private:
void
@@ -196,6 +207,33 @@ private:
//===----------------------------------------------------------------------===//
+class ThreadStateCoordinator::EventThreadCreate : public ThreadStateCoordinator::EventBase
+{
+public:
+ EventThreadCreate (lldb::tid_t tid):
+ EventBase (),
+ m_tid (tid)
+ {
+ }
+
+ ~EventThreadCreate () override
+ {
+ }
+
+ bool
+ ProcessEvent(ThreadStateCoordinator &coordinator) override
+ {
+ coordinator.ThreadWasCreated (m_tid);
+ return true;
+ }
+
+private:
+
+ const lldb::tid_t m_tid;
+};
+
+//===----------------------------------------------------------------------===//
+
class ThreadStateCoordinator::EventThreadDeath : public ThreadStateCoordinator::EventBase
{
public:
@@ -311,6 +349,22 @@ ThreadStateCoordinator::ThreadDidStop (l
}
void
+ThreadStateCoordinator::ThreadWasCreated (lldb::tid_t tid)
+{
+ // Add the new thread to the stop map.
+ // We assume a created thread is not stopped.
+ m_tid_stop_map[tid] = false;
+
+ if (m_pending_notification_sp)
+ {
+ // Tell the pending notification that we need to wait
+ // for this new thread to stop.
+ EventCallAfterThreadsStop *const call_after_event = static_cast<EventCallAfterThreadsStop*> (m_pending_notification_sp.get ());
+ call_after_event->AddThreadStopRequirement (tid);
+ }
+}
+
+void
ThreadStateCoordinator::ThreadDidDie (lldb::tid_t tid)
{
// Update the global list of known thread states. While this one is stopped, it is also dead.
@@ -349,6 +403,12 @@ ThreadStateCoordinator::NotifyThreadStop
}
void
+ThreadStateCoordinator::NotifyThreadCreate (lldb::tid_t tid)
+{
+ EnqueueEvent (EventBaseSP (new EventThreadCreate (tid)));
+}
+
+void
ThreadStateCoordinator::NotifyThreadDeath (lldb::tid_t tid)
{
EnqueueEvent (EventBaseSP (new EventThreadDeath (tid)));
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=218578&r1=218577&r2=218578&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/Linux/ThreadStateCoordinator.h (original)
+++ lldb/trunk/source/Plugins/Process/Linux/ThreadStateCoordinator.h Sun Sep 28 01:50:47 2014
@@ -79,6 +79,7 @@ namespace lldb_private
class EventCallAfterThreadsStop;
class EventStopCoordinator;
class EventThreadStopped;
+ class EventThreadCreate;
class EventThreadDeath;
typedef std::shared_ptr<EventBase> EventBaseSP;
@@ -102,6 +103,9 @@ namespace lldb_private
ThreadDidStop (lldb::tid_t tid);
void
+ ThreadWasCreated (lldb::tid_t tid);
+
+ void
ThreadDidDie (lldb::tid_t tid);
void
More information about the lldb-commits
mailing list