[NativeProcessLinux] fold ThreadStateCoordinator into NPL
authorPavel Labath <labath@google.com>
Wed, 6 May 2015 10:46:34 +0000 (10:46 +0000)
committerPavel Labath <labath@google.com>
Wed, 6 May 2015 10:46:34 +0000 (10:46 +0000)
Summary:
Since all TSC operations are now executed synchronously, TSC has become a little more than a
messenger between different parts of NativeProcessLinux. Therefore, the reason for its existance
has disappeared.

This commit moves the contents of the TSC into the NPL class. This will enable us to remove all
the boilerplate code in NPL (as it stands now, this is most of the class), which I plan to do in
subsequent commits.

Unfortunately, this also means we will lose the unit tests for the TSC. However, since the size
of the TSC has diminished, the unit tests were not testing much at this point anyway, so it's not
a big loss.

No functional change.

Test Plan: All tests continue to pass.

Reviewers: vharron, chaoren

Subscribers: lldb-commits

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

llvm-svn: 236587

12 files changed:
lldb/lldb.xcodeproj/project.pbxproj
lldb/source/Plugins/Process/Linux/CMakeLists.txt
lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp
lldb/source/Plugins/Process/Linux/NativeProcessLinux.h
lldb/source/Plugins/Process/Linux/ThreadStateCoordinator.cpp [deleted file]
lldb/source/Plugins/Process/Linux/ThreadStateCoordinator.h [deleted file]
lldb/unittests/CMakeLists.txt
lldb/unittests/Plugins/CMakeLists.txt [deleted file]
lldb/unittests/Plugins/Process/CMakeLists.txt [deleted file]
lldb/unittests/Plugins/Process/Linux/CMakeLists.txt [deleted file]
lldb/unittests/Plugins/Process/Linux/Makefile [deleted file]
lldb/unittests/Plugins/Process/Linux/ThreadStateCoordinatorTest.cpp [deleted file]

index 2e5c646..7fd9217 100644 (file)
@@ -85,7 +85,6 @@
                236124A41986B4E2004EFC37 /* IOObject.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 236124A21986B4E2004EFC37 /* IOObject.cpp */; };
                236124A51986B4E2004EFC37 /* Socket.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 236124A31986B4E2004EFC37 /* Socket.cpp */; };
                2377C2F819E613C100737875 /* PipePosix.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2377C2F719E613C100737875 /* PipePosix.cpp */; };
-               23CDD8FB19D47B3600461DDC /* ThreadStateCoordinator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 23CDD8E819D3E13200461DDC /* ThreadStateCoordinator.cpp */; };
                23DDF226196C3EE600BB8417 /* CommandOptionValidators.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 23DDF224196C3EE600BB8417 /* CommandOptionValidators.cpp */; };
                23EDE33319269E7C00F6A132 /* NativeRegisterContext.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 23EDE3301926839700F6A132 /* NativeRegisterContext.cpp */; };
                23EFE389193D1ABC00E54E54 /* SBTypeEnumMember.h in Headers */ = {isa = PBXBuildFile; fileRef = 23EFE388193D1ABC00E54E54 /* SBTypeEnumMember.h */; settings = {ATTRIBUTES = (Public, ); }; };
                23AB0530199FF639003B8084 /* ProcessFreeBSD.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ProcessFreeBSD.h; sourceTree = "<group>"; };
                23AB0531199FF639003B8084 /* ProcessMonitor.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = ProcessMonitor.cpp; sourceTree = "<group>"; };
                23AB0532199FF639003B8084 /* ProcessMonitor.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ProcessMonitor.h; sourceTree = "<group>"; };
-               23B6FF4119D38D48004CC8C3 /* ThreadStateCoordinator.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ThreadStateCoordinator.h; sourceTree = "<group>"; };
-               23CDD8E819D3E13200461DDC /* ThreadStateCoordinator.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = ThreadStateCoordinator.cpp; sourceTree = "<group>"; };
                23DDF224196C3EE600BB8417 /* CommandOptionValidators.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CommandOptionValidators.cpp; path = source/Interpreter/CommandOptionValidators.cpp; sourceTree = "<group>"; };
                23EDE3301926839700F6A132 /* NativeRegisterContext.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = NativeRegisterContext.cpp; path = source/Host/common/NativeRegisterContext.cpp; sourceTree = "<group>"; };
                23EDE3311926843600F6A132 /* NativeRegisterContext.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = NativeRegisterContext.h; path = include/lldb/Host/common/NativeRegisterContext.h; sourceTree = "<group>"; };
                                233B009319610B1F0090E598 /* ProcessMonitor.h */,
                                233B00A2196113730090E598 /* ProcFileReader.h */,
                                233B00A1196113730090E598 /* ProcFileReader.cpp */,
-                               23B6FF4119D38D48004CC8C3 /* ThreadStateCoordinator.h */,
-                               23CDD8E819D3E13200461DDC /* ThreadStateCoordinator.cpp */,
                        );
                        path = Linux;
                        sourceTree = "<group>";
                                AF26703B1852D01E00B6CC36 /* QueueList.cpp in Sources */,
                                267C012B136880DF006E963E /* OptionGroupValueObjectDisplay.cpp in Sources */,
                                26BCFC521368AE38006DC050 /* OptionGroupFormat.cpp in Sources */,
-                               23CDD8FB19D47B3600461DDC /* ThreadStateCoordinator.cpp in Sources */,
                                AF81DEFA1828A23F0042CF19 /* SystemRuntime.cpp in Sources */,
                                267C01371368C49C006E963E /* OptionGroupOutputFile.cpp in Sources */,
                                260E07C6136FA69E00CF21D3 /* OptionGroupUUID.cpp in Sources */,
index c0899ce..f3f5576 100644 (file)
@@ -15,6 +15,5 @@ add_lldb_library(lldbPluginProcessLinux
   ProcessLinux.cpp
   ProcessMonitor.cpp
   ProcFileReader.cpp
-  ThreadStateCoordinator.cpp
   )
 
index d46505e..b57e30d 100644 (file)
@@ -20,6 +20,7 @@
 
 // C++ Includes
 #include <fstream>
+#include <sstream>
 #include <string>
 
 // Other libraries and framework includes
@@ -49,7 +50,6 @@
 #include "NativeThreadLinux.h"
 #include "ProcFileReader.h"
 #include "Procfs.h"
-#include "ThreadStateCoordinator.h"
 
 // System includes - They have to be included after framework includes because they define some
 // macros which collide with variable names in other modules
@@ -153,7 +153,7 @@ namespace
         return signals;
     }
 
-    ThreadStateCoordinator::LogFunction
+    NativeProcessLinux::LogFunction
     GetThreadLoggerFunction ()
     {
         return [](const char *format, va_list args)
@@ -170,7 +170,7 @@ namespace
         Log *const log = GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD);
         if (log)
             log->Printf ("NativeProcessLinux::%s %s", __FUNCTION__, error_message.c_str ());
-        assert (false && "ThreadStateCoordinator error reported");
+        assert (false && "NativeProcessLinux error reported");
     }
 
     Error
@@ -1673,7 +1673,9 @@ NativeProcessLinux::NativeProcessLinux () :
     m_supports_mem_region (eLazyBoolCalculate),
     m_mem_region_cache (),
     m_mem_region_cache_mutex (),
-    m_coordinator_up (new ThreadStateCoordinator (GetThreadLoggerFunction ()))
+    m_log_function (GetThreadLoggerFunction()),
+    m_tid_map (),
+    m_log_event_processing (false)
 {
 }
 
@@ -2351,7 +2353,7 @@ NativeProcessLinux::WaitForNewThread(::pid_t tid)
     new_thread_sp = AddThread(tid);
     std::static_pointer_cast<NativeThreadLinux> (new_thread_sp)->SetRunning ();
     Resume (tid, LLDB_INVALID_SIGNAL_NUMBER);
-    m_coordinator_up->NotifyThreadCreate (tid, false, CoordinatorErrorHandler);
+    NotifyThreadCreate (tid, false, CoordinatorErrorHandler);
 }
 
 void
@@ -2407,7 +2409,7 @@ NativeProcessLinux::MonitorSIGTRAP(const siginfo_t *info, lldb::pid_t pid)
             log->Printf ("NativeProcessLinux::%s() received exec event, code = %d", __FUNCTION__, info->si_code ^ SIGTRAP);
 
         // The thread state coordinator needs to reset due to the exec.
-        m_coordinator_up->ResetForExec ();
+        ResetForExec ();
 
         // Remove all but the main thread here.  Linux fork creates a new process which only copies the main thread.  Mutexes are in undefined state.
         if (log)
@@ -2493,13 +2495,13 @@ NativeProcessLinux::MonitorSIGTRAP(const siginfo_t *info, lldb::pid_t pid)
         }
 
         const int signo = static_cast<int> (data);
-        m_coordinator_up->RequestThreadResume (pid,
-                                               [=](lldb::tid_t tid_to_resume, bool supress_signal)
-                                               {
-                                                   std::static_pointer_cast<NativeThreadLinux> (thread_sp)->SetRunning ();
-                                                   return Resume (tid_to_resume, (supress_signal) ? LLDB_INVALID_SIGNAL_NUMBER : signo);
-                                               },
-                                               CoordinatorErrorHandler);
+        RequestThreadResume (pid,
+                [=](lldb::tid_t tid_to_resume, bool supress_signal)
+                {
+                    std::static_pointer_cast<NativeThreadLinux> (thread_sp)->SetRunning ();
+                    return Resume (tid_to_resume, (supress_signal) ? LLDB_INVALID_SIGNAL_NUMBER : signo);
+                },
+                CoordinatorErrorHandler);
 
         break;
     }
@@ -2544,13 +2546,13 @@ NativeProcessLinux::MonitorSIGTRAP(const siginfo_t *info, lldb::pid_t pid)
 
             
         // Ignore these signals until we know more about them.
-        m_coordinator_up->RequestThreadResume (pid,
-                                               [=](lldb::tid_t tid_to_resume, bool supress_signal)
-                                               {
-                                                   std::static_pointer_cast<NativeThreadLinux> (thread_sp)->SetRunning ();
-                                                   return Resume (tid_to_resume, LLDB_INVALID_SIGNAL_NUMBER);
-                                               },
-                                               CoordinatorErrorHandler);
+        RequestThreadResume (pid,
+                [=](lldb::tid_t tid_to_resume, bool supress_signal)
+                {
+                    std::static_pointer_cast<NativeThreadLinux> (thread_sp)->SetRunning ();
+                    return Resume (tid_to_resume, LLDB_INVALID_SIGNAL_NUMBER);
+                },
+                CoordinatorErrorHandler);
         break;
 
     default:
@@ -2728,7 +2730,7 @@ NativeProcessLinux::MonitorSignal(const siginfo_t *info, lldb::pid_t pid, bool e
         // We can now resume the newly created thread.
         std::static_pointer_cast<NativeThreadLinux> (thread_sp)->SetRunning ();
         Resume (pid, LLDB_INVALID_SIGNAL_NUMBER);
-        m_coordinator_up->NotifyThreadCreate (pid, false, CoordinatorErrorHandler);
+        NotifyThreadCreate (pid, false, CoordinatorErrorHandler);
         // Done handling.
         return;
     }
@@ -2762,7 +2764,7 @@ NativeProcessLinux::MonitorSignal(const siginfo_t *info, lldb::pid_t pid, bool e
                 // stop signal as 0 to let lldb know this isn't the important stop.
                 linux_thread_sp->SetStoppedBySignal (0);
                 SetCurrentThreadID (thread_sp->GetID ());
-                m_coordinator_up->NotifyThreadStop (thread_sp->GetID (), true, CoordinatorErrorHandler);
+                NotifyThreadStop (thread_sp->GetID (), true, CoordinatorErrorHandler);
             }
             else
             {
@@ -2812,14 +2814,14 @@ NativeProcessLinux::MonitorSignal(const siginfo_t *info, lldb::pid_t pid, bool e
 
             // Resume this thread to get the group-stop mechanism to fire off the true group stops.
             // This thread will get stopped again as part of the group-stop completion.
-            m_coordinator_up->RequestThreadResume (pid,
-                                                   [=](lldb::tid_t tid_to_resume, bool supress_signal)
-                                                   {
-                                                       std::static_pointer_cast<NativeThreadLinux> (thread_sp)->SetRunning ();
-                                                       // Pass this signal number on to the inferior to handle.
-                                                       return Resume (tid_to_resume, (supress_signal) ? LLDB_INVALID_SIGNAL_NUMBER : signo);
-                                                   },
-                                                   CoordinatorErrorHandler);
+            RequestThreadResume (pid,
+                    [=](lldb::tid_t tid_to_resume, bool supress_signal)
+                    {
+                        std::static_pointer_cast<NativeThreadLinux> (thread_sp)->SetRunning ();
+                        // Pass this signal number on to the inferior to handle.
+                        return Resume (tid_to_resume, (supress_signal) ? LLDB_INVALID_SIGNAL_NUMBER : signo);
+                    },
+                    CoordinatorErrorHandler);
         }
         break;
     case SIGSEGV:
@@ -3092,17 +3094,17 @@ NativeProcessLinux::Resume (const ResumeActionList &resume_actions)
         {
             // Run the thread, possibly feeding it the signal.
             const int signo = action->signal;
-            m_coordinator_up->RequestThreadResumeAsNeeded (thread_sp->GetID (),
-                                                           [=](lldb::tid_t tid_to_resume, bool supress_signal)
-                                                           {
-                                                               std::static_pointer_cast<NativeThreadLinux> (thread_sp)->SetRunning ();
-                                                               // Pass this signal number on to the inferior to handle.
-                                                               const auto resume_result = Resume (tid_to_resume, (signo > 0 && !supress_signal) ? signo : LLDB_INVALID_SIGNAL_NUMBER);
-                                                               if (resume_result.Success())
-                                                                   SetState(eStateRunning, true);
-                                                               return resume_result;
-                                                           },
-                                                           CoordinatorErrorHandler);
+            RequestThreadResumeAsNeeded (thread_sp->GetID (),
+                    [=](lldb::tid_t tid_to_resume, bool supress_signal)
+                    {
+                        std::static_pointer_cast<NativeThreadLinux> (thread_sp)->SetRunning ();
+                        // Pass this signal number on to the inferior to handle.
+                        const auto resume_result = Resume (tid_to_resume, (signo > 0 && !supress_signal) ? signo : LLDB_INVALID_SIGNAL_NUMBER);
+                        if (resume_result.Success())
+                            SetState(eStateRunning, true);
+                        return resume_result;
+                    },
+                    CoordinatorErrorHandler);
             break;
         }
 
@@ -3110,23 +3112,23 @@ NativeProcessLinux::Resume (const ResumeActionList &resume_actions)
         {
             // Request the step.
             const int signo = action->signal;
-            m_coordinator_up->RequestThreadResume (thread_sp->GetID (),
-                                                   [=](lldb::tid_t tid_to_step, bool supress_signal)
-                                                   {
-                                                       std::static_pointer_cast<NativeThreadLinux> (thread_sp)->SetStepping ();
-
-                                                       Error step_result;
-                                                       if (software_single_step)
-                                                           step_result = Resume (tid_to_step, (signo > 0 && !supress_signal) ? signo : LLDB_INVALID_SIGNAL_NUMBER);
-                                                       else
-                                                           step_result = SingleStep (tid_to_step,(signo > 0 && !supress_signal) ? signo : LLDB_INVALID_SIGNAL_NUMBER);
-
-                                                       assert (step_result.Success() && "SingleStep() failed");
-                                                       if (step_result.Success())
-                                                           SetState(eStateStepping, true);
-                                                       return step_result;
-                                                   },
-                                                   CoordinatorErrorHandler);
+            RequestThreadResume (thread_sp->GetID (),
+                    [=](lldb::tid_t tid_to_step, bool supress_signal)
+                    {
+                        std::static_pointer_cast<NativeThreadLinux> (thread_sp)->SetStepping ();
+
+                        Error step_result;
+                        if (software_single_step)
+                            step_result = Resume (tid_to_step, (signo > 0 && !supress_signal) ? signo : LLDB_INVALID_SIGNAL_NUMBER);
+                        else
+                            step_result = SingleStep (tid_to_step,(signo > 0 && !supress_signal) ? signo : LLDB_INVALID_SIGNAL_NUMBER);
+
+                        assert (step_result.Success() && "SingleStep() failed");
+                        if (step_result.Success())
+                            SetState(eStateStepping, true);
+                        return step_result;
+                    },
+                    CoordinatorErrorHandler);
             stepping = true;
             break;
         }
@@ -4242,19 +4244,19 @@ void
 NativeProcessLinux::NotifyThreadCreateStopped (lldb::tid_t tid)
 {
     const bool is_stopped = true;
-    m_coordinator_up->NotifyThreadCreate (tid, is_stopped, CoordinatorErrorHandler);
+    NotifyThreadCreate (tid, is_stopped, CoordinatorErrorHandler);
 }
 
 void
 NativeProcessLinux::NotifyThreadDeath (lldb::tid_t tid)
 {
-    m_coordinator_up->NotifyThreadDeath (tid, CoordinatorErrorHandler);
+    NotifyThreadDeath (tid, CoordinatorErrorHandler);
 }
 
 void
 NativeProcessLinux::NotifyThreadStop (lldb::tid_t tid)
 {
-    m_coordinator_up->NotifyThreadStop (tid, false, CoordinatorErrorHandler);
+    NotifyThreadStop (tid, false, CoordinatorErrorHandler);
 }
 
 void
@@ -4266,7 +4268,7 @@ NativeProcessLinux::CallAfterRunningThreadsStop (lldb::tid_t tid,
         log->Printf("NativeProcessLinux::%s tid %" PRIu64, __FUNCTION__, tid);
 
     const lldb::pid_t pid = GetID ();
-    m_coordinator_up->CallAfterRunningThreadsStop (tid,
+    CallAfterRunningThreadsStop (tid,
                                                    [=](lldb::tid_t request_stop_tid)
                                                    {
                                                        return RequestThreadStop(pid, request_stop_tid);
@@ -4285,14 +4287,11 @@ NativeProcessLinux::CallAfterRunningThreadsStopWithSkipTID (lldb::tid_t deferred
         log->Printf("NativeProcessLinux::%s deferred_signal_tid %" PRIu64 ", skip_stop_request_tid %" PRIu64, __FUNCTION__, deferred_signal_tid, skip_stop_request_tid);
 
     const lldb::pid_t pid = GetID ();
-    m_coordinator_up->CallAfterRunningThreadsStopWithSkipTIDs (deferred_signal_tid,
-                                                               skip_stop_request_tid != LLDB_INVALID_THREAD_ID ? ThreadStateCoordinator::ThreadIDSet {skip_stop_request_tid} : ThreadStateCoordinator::ThreadIDSet (),
-                                                               [=](lldb::tid_t request_stop_tid)
-                                                               {
-                                                                   return RequestThreadStop(pid, request_stop_tid);
-                                                               },
-                                                               call_after_function,
-                                                               CoordinatorErrorHandler);
+    CallAfterRunningThreadsStopWithSkipTIDs (deferred_signal_tid,
+            skip_stop_request_tid != LLDB_INVALID_THREAD_ID ? NativeProcessLinux::ThreadIDSet {skip_stop_request_tid} : NativeProcessLinux::ThreadIDSet (),
+            [=](lldb::tid_t request_stop_tid) { return RequestThreadStop(pid, request_stop_tid); },
+            call_after_function,
+            CoordinatorErrorHandler);
 }
 
 Error
@@ -4352,3 +4351,561 @@ NativeProcessLinux::GetLoadedModuleFileSpec(const char* module_path, FileSpec& f
     return Error("Module file (%s) not found in /proc/%" PRIu64 "/maps file!",
                  module_file_spec.GetFilename().AsCString(), GetID());
 }
+
+void
+NativeProcessLinux::DoResume(
+        lldb::tid_t tid,
+        ResumeThreadFunction request_thread_resume_function,
+        ErrorFunction error_function,
+        bool error_when_already_running)
+{
+    // Ensure we know about the thread.
+    auto find_it = m_tid_map.find (tid);
+    if (find_it == m_tid_map.end ())
+    {
+        // 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;
+    }
+    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)
+        {
+            TSCLog ("NativeProcessLinux::%s tid %" PRIu64 " optional resume skipped since it is already running",
+                             __FUNCTION__,
+                             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 " << tid << " asked to resume but we think it is already running";
+            error_function (error_message.str ());
+        }
+
+        // Error or not, we're done.
+        return;
+    }
+
+    // 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)
+    {
+        if (m_pending_notification_up->wait_for_stop_tids.count (tid) > 0)
+        {
+            TSCLog ("NativeProcessLinux::%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);
+        }
+        else if (m_pending_notification_up->original_wait_for_stop_tids.count (tid) > 0)
+        {
+            TSCLog ("NativeProcessLinux::%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)
+            {
+                TSCLog ("NativeProcessLinux::%s tid %" PRIu64 " deferred stop notification still waiting on tid  %" PRIu64,
+                                 __FUNCTION__,
+                                 m_pending_notification_up->triggering_tid,
+                                 tid);
+            }
+        }
+    }
+
+    // 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 ())
+    {
+        // Now mark it is running.
+        context.m_state = ThreadState::Running;
+        context.m_request_resume_function = request_thread_resume_function;
+    }
+    else
+    {
+        TSCLog ("NativeProcessLinux::%s failed to resume thread tid  %" PRIu64 ": %s",
+                         __FUNCTION__, tid, error.AsCString ());
+    }
+
+    return;
+}
+
+//===----------------------------------------------------------------------===//
+
+void
+NativeProcessLinux::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)
+{
+    std::lock_guard<std::mutex> lock(m_event_mutex);
+
+    if (m_log_event_processing)
+    {
+        TSCLog ("NativeProcessLinux::%s about to process event: (triggering_tid: %" PRIu64 ", wait_for_stop_tids.size(): %zd)",
+                __FUNCTION__, triggering_tid, wait_for_stop_tids.size());
+    }
+
+    DoCallAfterThreadsStop(PendingNotificationUP(new PendingNotification(
+                triggering_tid, wait_for_stop_tids, request_thread_stop_function,
+                call_after_function, error_function)));
+
+    if (m_log_event_processing)
+    {
+        TSCLog ("NativeProcessLinux::%s event processing done", __FUNCTION__);
+    }
+}
+
+void
+NativeProcessLinux::CallAfterRunningThreadsStop (const lldb::tid_t triggering_tid,
+                                                     const StopThreadFunction &request_thread_stop_function,
+                                                     const ThreadIDFunction &call_after_function,
+                                                     const ErrorFunction &error_function)
+{
+    std::lock_guard<std::mutex> lock(m_event_mutex);
+
+    if (m_log_event_processing)
+    {
+        TSCLog ("NativeProcessLinux::%s about to process event: (triggering_tid: %" PRIu64 ")",
+                __FUNCTION__, triggering_tid);
+    }
+
+    DoCallAfterThreadsStop(PendingNotificationUP(new PendingNotification(
+                triggering_tid,
+                request_thread_stop_function,
+                call_after_function,
+                error_function)));
+
+    if (m_log_event_processing)
+    {
+        TSCLog ("NativeProcessLinux::%s event processing done", __FUNCTION__);
+    }
+}
+
+void
+NativeProcessLinux::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)
+{
+    std::lock_guard<std::mutex> lock(m_event_mutex);
+
+    if (m_log_event_processing)
+    {
+        TSCLog ("NativeProcessLinux::%s about to process event: (triggering_tid: %" PRIu64 ", skip_stop_request_tids.size(): %zd)",
+                __FUNCTION__, triggering_tid, skip_stop_request_tids.size());
+    }
+
+    DoCallAfterThreadsStop(PendingNotificationUP(new PendingNotification(
+                triggering_tid,
+                request_thread_stop_function,
+                call_after_function,
+                skip_stop_request_tids,
+                error_function)));
+
+    if (m_log_event_processing)
+    {
+        TSCLog ("NativeProcessLinux::%s event processing done", __FUNCTION__);
+    }
+}
+
+void
+NativeProcessLinux::SignalIfRequirementsSatisfied()
+{
+    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();
+    }
+}
+
+bool
+NativeProcessLinux::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: 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 ());
+
+            // 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, context);
+            sent_tids.insert (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_pending_notification_up->wait_for_stop_tids.swap (sent_tids);
+
+    // Succeeded, keep running.
+    return true;
+}
+
+void
+NativeProcessLinux::RequestStopOnAllRunningThreads()
+{
+    // 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 = m_tid_map.begin(); it != 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_pending_notification_up->skip_stop_request_tids.count (tid) > 0;
+            if (!skip_stop_request)
+                RequestThreadStop (tid, 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_pending_notification_up->wait_for_stop_tids.swap (sent_tids);
+}
+
+void
+NativeProcessLinux::RequestThreadStop (lldb::tid_t tid, ThreadContext& context)
+{
+    const auto error = m_pending_notification_up->request_thread_stop_function (tid);
+    if (error.Success ())
+        context.m_stop_requested = true;
+    else
+    {
+        TSCLog ("NativeProcessLinux::%s failed to request thread stop tid  %" PRIu64 ": %s",
+                         __FUNCTION__, tid, error.AsCString ());
+    }
+}
+
+
+void
+NativeProcessLinux::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);
+    if (find_it == m_tid_map.end ())
+    {
+        // We don't know about this thread.  This is an error condition.
+        std::ostringstream error_message;
+        error_message << "error: tid " << tid << " asked to stop but tid is unknown";
+        error_function (error_message.str ());
+        return;
+    }
+
+    // Update the global list of known thread states.  This one is definitely stopped.
+    auto& context = find_it->second;
+    const auto stop_was_requested = context.m_stop_requested;
+    context.m_state = ThreadState::Stopped;
+    context.m_stop_requested = false;
+
+    // If we have a pending notification, remove this from the set.
+    if (m_pending_notification_up)
+    {
+        m_pending_notification_up->wait_for_stop_tids.erase(tid);
+        SignalIfRequirementsSatisfied();
+    }
+
+    if (initiated_by_llgs && context.m_request_resume_function && !stop_was_requested)
+    {
+        // We can end up here if stop was initiated by LLGS but by this time a
+        // thread stop has occurred - maybe initiated by another event.
+        TSCLog ("Resuming thread %"  PRIu64 " since stop wasn't requested", tid);
+        const auto error = context.m_request_resume_function (tid, true);
+        if (error.Success ())
+        {
+            context.m_state = ThreadState::Running;
+        }
+        else
+        {
+            TSCLog ("NativeProcessLinux::%s failed to resume thread tid  %" PRIu64 ": %s",
+                 __FUNCTION__, tid, error.AsCString ());
+        }
+    }
+}
+
+void
+NativeProcessLinux::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.
+        TSCLog ("NativeProcessLinux::%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
+NativeProcessLinux::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);
+    if (find_it != m_tid_map.end ())
+    {
+        // We already know about this thread.  This is an error condition.
+        std::ostringstream error_message;
+        error_message << "error: notified tid " << tid << " created but we already know about this thread";
+        error_function (error_message.str ());
+        return;
+    }
+
+    // Add the new thread to the stop map.
+    ThreadContext ctx;
+    ctx.m_state = (is_stopped) ? ThreadState::Stopped : ThreadState::Running;
+    m_tid_map[tid] = std::move(ctx);
+
+    if (m_pending_notification_up && !is_stopped)
+    {
+        // 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
+NativeProcessLinux::ThreadDidDie (lldb::tid_t tid, const ErrorFunction &error_function)
+{
+    // Ensure we know about the thread.
+    auto find_it = m_tid_map.find (tid);
+    if (find_it == m_tid_map.end ())
+    {
+        // We don't know about this thread.  This is an error condition.
+        std::ostringstream error_message;
+        error_message << "error: notified tid " << tid << " died but tid is unknown";
+        error_function (error_message.str ());
+        return;
+    }
+
+    // Update the global list of known thread states.  While this one is stopped, it is also dead.
+    // So stop tracking it.  We assume the user of this coordinator will not keep trying to add
+    // dependencies on a thread after it is known to be dead.
+    m_tid_map.erase (find_it);
+
+    // If we have a pending notification, remove this from the set.
+    if (m_pending_notification_up)
+    {
+        m_pending_notification_up->wait_for_stop_tids.erase(tid);
+        SignalIfRequirementsSatisfied();
+    }
+}
+
+void
+NativeProcessLinux::TSCLog (const char *format, ...)
+{
+    va_list args;
+    va_start (args, format);
+
+    m_log_function (format, args);
+
+    va_end (args);
+}
+
+void
+NativeProcessLinux::NotifyThreadStop (lldb::tid_t tid,
+                                          bool initiated_by_llgs,
+                                          const ErrorFunction &error_function)
+{
+    std::lock_guard<std::mutex> lock(m_event_mutex);
+
+    if (m_log_event_processing)
+    {
+        TSCLog ("NativeProcessLinux::%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)
+    {
+        TSCLog ("NativeProcessLinux::%s event processing done", __FUNCTION__);
+    }
+}
+
+void
+NativeProcessLinux::RequestThreadResume (lldb::tid_t tid,
+                                             const ResumeThreadFunction &request_thread_resume_function,
+                                             const ErrorFunction &error_function)
+{
+    std::lock_guard<std::mutex> lock(m_event_mutex);
+
+    if (m_log_event_processing)
+    {
+        TSCLog ("NativeProcessLinux::%s about to process event: (tid: %" PRIu64 ")",
+                __FUNCTION__, tid);
+    }
+
+    DoResume(tid, request_thread_resume_function, error_function, true);
+
+    if (m_log_event_processing)
+    {
+        TSCLog ("NativeProcessLinux::%s event processing done", __FUNCTION__);
+    }
+}
+
+void
+NativeProcessLinux::RequestThreadResumeAsNeeded (lldb::tid_t tid,
+                                                     const ResumeThreadFunction &request_thread_resume_function,
+                                                     const ErrorFunction &error_function)
+{
+    std::lock_guard<std::mutex> lock(m_event_mutex);
+
+    if (m_log_event_processing)
+    {
+        TSCLog ("NativeProcessLinux::%s about to process event: (tid: %" PRIu64 ")",
+                __FUNCTION__, tid);
+    }
+
+    DoResume (tid, request_thread_resume_function, error_function, false);
+
+    if (m_log_event_processing)
+    {
+        TSCLog ("NativeProcessLinux::%s event processing done", __FUNCTION__);
+    }
+}
+
+void
+NativeProcessLinux::NotifyThreadCreate (lldb::tid_t tid,
+                                            bool is_stopped,
+                                            const ErrorFunction &error_function)
+{
+    std::lock_guard<std::mutex> lock(m_event_mutex);
+
+    if (m_log_event_processing)
+    {
+        TSCLog ("NativeProcessLinux::%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)
+    {
+        TSCLog ("NativeProcessLinux::%s event processing done", __FUNCTION__);
+    }
+}
+
+void
+NativeProcessLinux::NotifyThreadDeath (lldb::tid_t tid,
+                                           const ErrorFunction &error_function)
+{
+    std::lock_guard<std::mutex> lock(m_event_mutex);
+
+    if (m_log_event_processing)
+    {
+        TSCLog ("NativeProcessLinux::%s about to process event: (tid: %" PRIu64 ")", __FUNCTION__, tid);
+    }
+
+    ThreadDidDie(tid, error_function);
+
+    if (m_log_event_processing)
+    {
+        TSCLog ("NativeProcessLinux::%s event processing done", __FUNCTION__);
+    }
+}
+
+void
+NativeProcessLinux::ResetForExec ()
+{
+    std::lock_guard<std::mutex> lock(m_event_mutex);
+
+    if (m_log_event_processing)
+    {
+        TSCLog ("NativeProcessLinux::%s about to process event", __FUNCTION__);
+    }
+
+    // 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)
+    {
+        TSCLog ("NativeProcessLinux::%s event processing done", __FUNCTION__);
+    }
+}
+void
+NativeProcessLinux::LogEnableEventProcessing (bool enabled)
+{
+    m_log_event_processing = enabled;
+}
+
+bool
+NativeProcessLinux::IsKnownThread (lldb::tid_t tid) const
+{
+    return m_tid_map.find (tid) != m_tid_map.end ();
+}
index a35f0a7..886d077 100644 (file)
@@ -15,6 +15,8 @@
 #include <signal.h>
 
 // C++ Includes
+#include <mutex>
+#include <unordered_map>
 #include <unordered_set>
 
 // Other libraries and framework includes
@@ -33,8 +35,6 @@ namespace lldb_private {
     class Scalar;
 
 namespace process_linux {
-    class ThreadStateCoordinator;
-
     /// @class NativeProcessLinux
     /// @brief Manages communication with the inferior (debugee) process.
     ///
@@ -190,8 +190,6 @@ namespace process_linux {
         std::vector<MemoryRegionInfo> m_mem_region_cache;
         Mutex m_mem_region_cache_mutex;
 
-        std::unique_ptr<ThreadStateCoordinator> m_coordinator_up;
-
         // List of thread ids stepping with a breakpoint with the address of
         // the relevan breakpoint
         std::map<lldb::tid_t, lldb::addr_t> m_threads_stepping_with_breakpoint;
@@ -374,6 +372,226 @@ namespace process_linux {
 
         Error
         RequestThreadStop (const lldb::pid_t pid, const lldb::tid_t tid);
+
+
+    public:
+        // Typedefs.
+        typedef std::unordered_set<lldb::tid_t> ThreadIDSet;
+
+        // Callback/block definitions.
+        typedef std::function<void (lldb::tid_t tid)> ThreadIDFunction;
+        typedef std::function<void (const char *format, va_list args)> LogFunction;
+        typedef std::function<void (const std::string &error_message)> ErrorFunction;
+        typedef std::function<Error (lldb::tid_t tid)> StopThreadFunction;
+        typedef std::function<Error (lldb::tid_t tid, bool supress_signal)> ResumeThreadFunction;
+
+    private:
+        // Notify the coordinator when a thread is created and/or starting to be
+        // tracked.  is_stopped should be true if the thread is currently stopped;
+        // otherwise, it should be set false if it is already running.  Will
+        // call the error function if the thread id is already tracked.
+        void
+        NotifyThreadCreate (lldb::tid_t tid,
+                            bool is_stopped,
+                            const ErrorFunction &error_function);
+
+        // Notify the coordinator when a previously-existing thread should no
+        // longer be tracked.  The error_function will trigger if the thread
+        // is not being tracked.
+        void
+        NotifyThreadDeath (lldb::tid_t tid,
+                           const ErrorFunction &error_function);
+
+
+        // This method is the main purpose of the class: triggering a deferred
+        // action after a given set of threads stop.  The triggering_tid is the
+        // thread id passed to the call_after_function.  The error_function will
+        // be fired if either the triggering tid or any of the wait_for_stop_tids
+        // are unknown at the time the method is processed.
+        void
+        CallAfterThreadsStop (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);
+
+        // This method is the main purpose of the class: triggering a deferred
+        // action after all non-stopped threads stop.  The triggering_tid is the
+        // thread id passed to the call_after_function.  The error_function will
+        // be fired if the triggering tid is unknown at the time of execution.
+        void
+        CallAfterRunningThreadsStop (lldb::tid_t triggering_tid,
+                                     const StopThreadFunction &request_thread_stop_function,
+                                     const ThreadIDFunction &call_after_function,
+                                     const ErrorFunction &error_function);
+
+        // This method is the main purpose of the class: triggering a deferred
+        // action after all non-stopped threads stop.  The triggering_tid is the
+        // thread id passed to the call_after_function.  The error_function will
+        // be fired if the triggering tid is unknown at the time of execution.
+        // This variant will send stop requests to all non-stopped threads except
+        // for any contained in skip_stop_request_tids.
+        void
+        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);
+
+        // Notify the thread stopped.  Will trigger error at time of execution if we
+        // already think it is stopped.
+        void
+        NotifyThreadStop (lldb::tid_t tid,
+                          bool initiated_by_llgs,
+                          const ErrorFunction &error_function);
+
+        // Request that the given thread id should have the request_thread_resume_function
+        // called.  Will trigger the error_function if the thread is thought to be running
+        // already at that point.  This call signals an error if the thread resume is for
+        // a thread that is already in a running state.
+        void
+        RequestThreadResume (lldb::tid_t tid,
+                             const ResumeThreadFunction &request_thread_resume_function,
+                             const ErrorFunction &error_function);
+
+        // Request that the given thread id should have the request_thread_resume_function
+        // called.  Will trigger the error_function if the thread is thought to be running
+        // already at that point.  This call ignores threads that are already running and
+        // does not trigger an error in that case.
+        void
+        RequestThreadResumeAsNeeded (lldb::tid_t tid,
+                                     const ResumeThreadFunction &request_thread_resume_function,
+                                     const ErrorFunction &error_function);
+
+        // Indicate the calling process did an exec and that the thread state
+        // should be 100% cleared.
+        void
+        ResetForExec ();
+
+        // Enable/disable verbose logging of event processing.
+        void
+        LogEnableEventProcessing (bool enabled);
+
+    private:
+
+        enum class ThreadState
+        {
+            Running,
+            Stopped
+        };
+
+        struct ThreadContext
+        {
+            ThreadState m_state;
+            bool m_stop_requested = false;
+            ResumeThreadFunction m_request_resume_function;
+        };
+        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();
+
+        void
+        RequestStopOnAllRunningThreads();
+
+        void
+        RequestThreadStop (lldb::tid_t tid, ThreadContext& context);
+
+        std::mutex m_event_mutex; // Serializes execution of ProcessEvent. XXX
+
+        void
+        ThreadDidStop (lldb::tid_t tid, bool initiated_by_llgs, const ErrorFunction &error_function);
+
+        void
+        DoResume(lldb::tid_t tid, ResumeThreadFunction request_thread_resume_function,
+                ErrorFunction error_function, bool error_when_already_running);
+
+        void
+        DoCallAfterThreadsStop(PendingNotificationUP &&notification_up);
+
+        void
+        ThreadWasCreated (lldb::tid_t tid, bool is_stopped, const ErrorFunction &error_function);
+
+        void
+        ThreadDidDie (lldb::tid_t tid, const ErrorFunction &error_function);
+
+        bool
+        IsKnownThread(lldb::tid_t tid) const;
+
+        void
+        TSCLog (const char *format, ...);
+
+        // Member variables.
+        LogFunction m_log_function;
+        PendingNotificationUP m_pending_notification_up;
+
+        // Maps known TIDs to ThreadContext.
+        TIDContextMap m_tid_map;
+
+        bool m_log_event_processing;
     };
 
 } // namespace process_linux
diff --git a/lldb/source/Plugins/Process/Linux/ThreadStateCoordinator.cpp b/lldb/source/Plugins/Process/Linux/ThreadStateCoordinator.cpp
deleted file mode 100644 (file)
index 1d7affc..0000000
+++ /dev/null
@@ -1,590 +0,0 @@
-//===-- ThreadStateCoordinator.cpp ------------------------------*- C++ -*-===//
-//
-//                     The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-
-#if !defined (__STDC_FORMAT_MACROS)
-#define __STDC_FORMAT_MACROS 1
-#endif
-
-#include <inttypes.h>
-
-#include "ThreadStateCoordinator.h"
-#include <memory>
-#include <cstdarg>
-#include <sstream>
-
-using namespace lldb_private;
-using namespace lldb_private::process_linux;
-
-//===----------------------------------------------------------------------===//
-
-void
-ThreadStateCoordinator::DoResume(
-        lldb::tid_t tid,
-        ResumeThreadFunction request_thread_resume_function,
-        ErrorFunction error_function,
-        bool error_when_already_running)
-{
-    // Ensure we know about the thread.
-    auto find_it = m_tid_map.find (tid);
-    if (find_it == m_tid_map.end ())
-    {
-        // 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;
-    }
-    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
-        {
-            // 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 ());
-        }
-
-        // Error or not, we're done.
-        return;
-    }
-
-    // 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)
-    {
-        if (m_pending_notification_up->wait_for_stop_tids.count (tid) > 0)
-        {
-            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);
-        }
-        else if (m_pending_notification_up->original_wait_for_stop_tids.count (tid) > 0)
-        {
-            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)
-            {
-                Log ("ThreadStateCoordinator::%s tid %" PRIu64 " deferred stop notification still waiting on tid  %" PRIu64,
-                                 __FUNCTION__,
-                                 m_pending_notification_up->triggering_tid,
-                                 tid);
-            }
-        }
-    }
-
-    // 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 ())
-    {
-        // Now mark it is running.
-        context.m_state = ThreadState::Running;
-        context.m_request_resume_function = request_thread_resume_function;
-    }
-    else
-    {
-        Log ("ThreadStateCoordinator::%s failed to resume thread tid  %" PRIu64 ": %s",
-                         __FUNCTION__, tid, error.AsCString ());
-    }
-
-    return;
-}
-
-//===----------------------------------------------------------------------===//
-
-ThreadStateCoordinator::ThreadStateCoordinator (const LogFunction &log_function) :
-    m_log_function (log_function),
-    m_tid_map (),
-    m_log_event_processing (false)
-{
-}
-
-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)
-{
-    std::lock_guard<std::mutex> lock(m_event_mutex);
-
-    if (m_log_event_processing)
-    {
-        Log ("ThreadStateCoordinator::%s about to process event: (triggering_tid: %" PRIu64 ", wait_for_stop_tids.size(): %zd)",
-                __FUNCTION__, triggering_tid, wait_for_stop_tids.size());
-    }
-
-    DoCallAfterThreadsStop(PendingNotificationUP(new PendingNotification(
-                triggering_tid, wait_for_stop_tids, request_thread_stop_function,
-                call_after_function, error_function)));
-
-    if (m_log_event_processing)
-    {
-        Log ("ThreadStateCoordinator::%s event processing done", __FUNCTION__);
-    }
-}
-
-void
-ThreadStateCoordinator::CallAfterRunningThreadsStop (const lldb::tid_t triggering_tid,
-                                                     const StopThreadFunction &request_thread_stop_function,
-                                                     const ThreadIDFunction &call_after_function,
-                                                     const ErrorFunction &error_function)
-{
-    std::lock_guard<std::mutex> lock(m_event_mutex);
-
-    if (m_log_event_processing)
-    {
-        Log ("ThreadStateCoordinator::%s about to process event: (triggering_tid: %" PRIu64 ")",
-                __FUNCTION__, triggering_tid);
-    }
-
-    DoCallAfterThreadsStop(PendingNotificationUP(new PendingNotification(
-                triggering_tid,
-                request_thread_stop_function,
-                call_after_function,
-                error_function)));
-
-    if (m_log_event_processing)
-    {
-        Log ("ThreadStateCoordinator::%s event processing done", __FUNCTION__);
-    }
-}
-
-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)
-{
-    std::lock_guard<std::mutex> lock(m_event_mutex);
-
-    if (m_log_event_processing)
-    {
-        Log ("ThreadStateCoordinator::%s about to process event: (triggering_tid: %" PRIu64 ", skip_stop_request_tids.size(): %zd)",
-                __FUNCTION__, triggering_tid, skip_stop_request_tids.size());
-    }
-
-    DoCallAfterThreadsStop(PendingNotificationUP(new PendingNotification(
-                triggering_tid,
-                request_thread_stop_function,
-                call_after_function,
-                skip_stop_request_tids,
-                error_function)));
-
-    if (m_log_event_processing)
-    {
-        Log ("ThreadStateCoordinator::%s event processing done", __FUNCTION__);
-    }
-}
-
-void
-ThreadStateCoordinator::SignalIfRequirementsSatisfied()
-{
-    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();
-    }
-}
-
-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: 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 ());
-
-            // 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, context);
-            sent_tids.insert (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_pending_notification_up->wait_for_stop_tids.swap (sent_tids);
-
-    // Succeeded, keep running.
-    return true;
-}
-
-void
-ThreadStateCoordinator::RequestStopOnAllRunningThreads()
-{
-    // 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 = m_tid_map.begin(); it != 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_pending_notification_up->skip_stop_request_tids.count (tid) > 0;
-            if (!skip_stop_request)
-                RequestThreadStop (tid, 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_pending_notification_up->wait_for_stop_tids.swap (sent_tids);
-}
-
-void
-ThreadStateCoordinator::RequestThreadStop (lldb::tid_t tid, ThreadContext& context)
-{
-    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, const ErrorFunction &error_function)
-{
-    // Ensure we know about the thread.
-    auto find_it = m_tid_map.find (tid);
-    if (find_it == m_tid_map.end ())
-    {
-        // We don't know about this thread.  This is an error condition.
-        std::ostringstream error_message;
-        error_message << "error: tid " << tid << " asked to stop but tid is unknown";
-        error_function (error_message.str ());
-        return;
-    }
-
-    // Update the global list of known thread states.  This one is definitely stopped.
-    auto& context = find_it->second;
-    const auto stop_was_requested = context.m_stop_requested;
-    context.m_state = ThreadState::Stopped;
-    context.m_stop_requested = false;
-
-    // If we have a pending notification, remove this from the set.
-    if (m_pending_notification_up)
-    {
-        m_pending_notification_up->wait_for_stop_tids.erase(tid);
-        SignalIfRequirementsSatisfied();
-    }
-
-    if (initiated_by_llgs && context.m_request_resume_function && !stop_was_requested)
-    {
-        // We can end up here if stop was initiated by LLGS but by this time a
-        // thread stop has occurred - maybe initiated by another event.
-        Log ("Resuming thread %"  PRIu64 " since stop wasn't requested", tid);
-        const auto error = context.m_request_resume_function (tid, true);
-        if (error.Success ())
-        {
-            context.m_state = ThreadState::Running;
-        }
-        else
-        {
-            Log ("ThreadStateCoordinator::%s failed to resume thread tid  %" PRIu64 ": %s",
-                 __FUNCTION__, tid, error.AsCString ());
-        }
-    }
-}
-
-void
-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);
-    if (find_it != m_tid_map.end ())
-    {
-        // We already know about this thread.  This is an error condition.
-        std::ostringstream error_message;
-        error_message << "error: notified tid " << tid << " created but we already know about this thread";
-        error_function (error_message.str ());
-        return;
-    }
-
-    // Add the new thread to the stop map.
-    ThreadContext ctx;
-    ctx.m_state = (is_stopped) ? ThreadState::Stopped : ThreadState::Running;
-    m_tid_map[tid] = std::move(ctx);
-
-    if (m_pending_notification_up && !is_stopped)
-    {
-        // 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, const ErrorFunction &error_function)
-{
-    // Ensure we know about the thread.
-    auto find_it = m_tid_map.find (tid);
-    if (find_it == m_tid_map.end ())
-    {
-        // We don't know about this thread.  This is an error condition.
-        std::ostringstream error_message;
-        error_message << "error: notified tid " << tid << " died but tid is unknown";
-        error_function (error_message.str ());
-        return;
-    }
-
-    // Update the global list of known thread states.  While this one is stopped, it is also dead.
-    // So stop tracking it.  We assume the user of this coordinator will not keep trying to add
-    // dependencies on a thread after it is known to be dead.
-    m_tid_map.erase (find_it);
-
-    // If we have a pending notification, remove this from the set.
-    if (m_pending_notification_up)
-    {
-        m_pending_notification_up->wait_for_stop_tids.erase(tid);
-        SignalIfRequirementsSatisfied();
-    }
-}
-
-void
-ThreadStateCoordinator::Log (const char *format, ...)
-{
-    va_list args;
-    va_start (args, format);
-
-    m_log_function (format, args);
-
-    va_end (args);
-}
-
-void
-ThreadStateCoordinator::NotifyThreadStop (lldb::tid_t tid,
-                                          bool initiated_by_llgs,
-                                          const ErrorFunction &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
-ThreadStateCoordinator::RequestThreadResume (lldb::tid_t tid,
-                                             const ResumeThreadFunction &request_thread_resume_function,
-                                             const ErrorFunction &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 ")",
-                __FUNCTION__, tid);
-    }
-
-    DoResume(tid, request_thread_resume_function, error_function, true);
-
-    if (m_log_event_processing)
-    {
-        Log ("ThreadStateCoordinator::%s event processing done", __FUNCTION__);
-    }
-}
-
-void
-ThreadStateCoordinator::RequestThreadResumeAsNeeded (lldb::tid_t tid,
-                                                     const ResumeThreadFunction &request_thread_resume_function,
-                                                     const ErrorFunction &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 ")",
-                __FUNCTION__, tid);
-    }
-
-    DoResume (tid, request_thread_resume_function, error_function, false);
-
-    if (m_log_event_processing)
-    {
-        Log ("ThreadStateCoordinator::%s event processing done", __FUNCTION__);
-    }
-}
-
-void
-ThreadStateCoordinator::NotifyThreadCreate (lldb::tid_t tid,
-                                            bool is_stopped,
-                                            const ErrorFunction &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)
-{
-    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);
-    }
-
-    ThreadDidDie(tid, error_function);
-
-    if (m_log_event_processing)
-    {
-        Log ("ThreadStateCoordinator::%s event processing done", __FUNCTION__);
-    }
-}
-
-void
-ThreadStateCoordinator::ResetForExec ()
-{
-    std::lock_guard<std::mutex> lock(m_event_mutex);
-
-    if (m_log_event_processing)
-    {
-        Log ("ThreadStateCoordinator::%s about to process event", __FUNCTION__);
-    }
-
-    // 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;
-}
-
-bool
-ThreadStateCoordinator::IsKnownThread (lldb::tid_t tid) const
-{
-    return m_tid_map.find (tid) != m_tid_map.end ();
-}
diff --git a/lldb/source/Plugins/Process/Linux/ThreadStateCoordinator.h b/lldb/source/Plugins/Process/Linux/ThreadStateCoordinator.h
deleted file mode 100644 (file)
index 6ad87fc..0000000
+++ /dev/null
@@ -1,253 +0,0 @@
-//===-- ThreadStateCoordinator.h --------------------------------*- C++ -*-===//
-//
-//                     The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef lldb_ThreadStateCoordinator_h
-#define lldb_ThreadStateCoordinator_h
-
-#include <functional>
-#include <mutex>
-#include <unordered_map>
-#include <unordered_set>
-
-#include "lldb/lldb-types.h"
-
-#include "lldb/Core/Error.h"
-
-namespace lldb_private {
-namespace process_linux {
-
-    class ThreadStateCoordinator
-    {
-    public:
-
-        // Typedefs.
-        typedef std::unordered_set<lldb::tid_t> ThreadIDSet;
-
-        // Callback/block definitions.
-        typedef std::function<void (lldb::tid_t tid)> ThreadIDFunction;
-        typedef std::function<void (const char *format, va_list args)> LogFunction;
-        typedef std::function<void (const std::string &error_message)> ErrorFunction;
-        typedef std::function<Error (lldb::tid_t tid)> StopThreadFunction;
-        typedef std::function<Error (lldb::tid_t tid, bool supress_signal)> ResumeThreadFunction;
-
-        // Constructors.
-        ThreadStateCoordinator (const LogFunction &log_function);
-
-        // Notify the coordinator when a thread is created and/or starting to be
-        // tracked.  is_stopped should be true if the thread is currently stopped;
-        // otherwise, it should be set false if it is already running.  Will
-        // call the error function if the thread id is already tracked.
-        void
-        NotifyThreadCreate (lldb::tid_t tid,
-                            bool is_stopped,
-                            const ErrorFunction &error_function);
-
-        // Notify the coordinator when a previously-existing thread should no
-        // longer be tracked.  The error_function will trigger if the thread
-        // is not being tracked.
-        void
-        NotifyThreadDeath (lldb::tid_t tid,
-                           const ErrorFunction &error_function);
-
-
-        // This method is the main purpose of the class: triggering a deferred
-        // action after a given set of threads stop.  The triggering_tid is the
-        // thread id passed to the call_after_function.  The error_function will
-        // be fired if either the triggering tid or any of the wait_for_stop_tids
-        // are unknown at the time the method is processed.
-        void
-        CallAfterThreadsStop (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);
-
-        // This method is the main purpose of the class: triggering a deferred
-        // action after all non-stopped threads stop.  The triggering_tid is the
-        // thread id passed to the call_after_function.  The error_function will
-        // be fired if the triggering tid is unknown at the time of execution.
-        void
-        CallAfterRunningThreadsStop (lldb::tid_t triggering_tid,
-                                     const StopThreadFunction &request_thread_stop_function,
-                                     const ThreadIDFunction &call_after_function,
-                                     const ErrorFunction &error_function);
-
-        // This method is the main purpose of the class: triggering a deferred
-        // action after all non-stopped threads stop.  The triggering_tid is the
-        // thread id passed to the call_after_function.  The error_function will
-        // be fired if the triggering tid is unknown at the time of execution.
-        // This variant will send stop requests to all non-stopped threads except
-        // for any contained in skip_stop_request_tids.
-        void
-        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);
-
-        // Notify the thread stopped.  Will trigger error at time of execution if we
-        // already think it is stopped.
-        void
-        NotifyThreadStop (lldb::tid_t tid,
-                          bool initiated_by_llgs,
-                          const ErrorFunction &error_function);
-
-        // Request that the given thread id should have the request_thread_resume_function
-        // called.  Will trigger the error_function if the thread is thought to be running
-        // already at that point.  This call signals an error if the thread resume is for
-        // a thread that is already in a running state.
-        void
-        RequestThreadResume (lldb::tid_t tid,
-                             const ResumeThreadFunction &request_thread_resume_function,
-                             const ErrorFunction &error_function);
-
-        // Request that the given thread id should have the request_thread_resume_function
-        // called.  Will trigger the error_function if the thread is thought to be running
-        // already at that point.  This call ignores threads that are already running and
-        // does not trigger an error in that case.
-        void
-        RequestThreadResumeAsNeeded (lldb::tid_t tid,
-                                     const ResumeThreadFunction &request_thread_resume_function,
-                                     const ErrorFunction &error_function);
-
-        // Indicate the calling process did an exec and that the thread state
-        // should be 100% cleared.
-        void
-        ResetForExec ();
-
-        // Enable/disable verbose logging of event processing.
-        void
-        LogEnableEventProcessing (bool enabled);
-
-    private:
-
-        enum class ThreadState
-        {
-            Running,
-            Stopped
-        };
-
-        struct ThreadContext
-        {
-            ThreadState m_state;
-            bool m_stop_requested = false;
-            ResumeThreadFunction m_request_resume_function;
-        };
-        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();
-
-        void
-        RequestStopOnAllRunningThreads();
-
-        void
-        RequestThreadStop (lldb::tid_t tid, ThreadContext& context);
-
-        std::mutex m_event_mutex; // Serializes execution of TSC operations.
-
-        void
-        ThreadDidStop (lldb::tid_t tid, bool initiated_by_llgs, const ErrorFunction &error_function);
-
-        void
-        DoResume(lldb::tid_t tid, ResumeThreadFunction request_thread_resume_function,
-                ErrorFunction error_function, bool error_when_already_running);
-
-        void
-        DoCallAfterThreadsStop(PendingNotificationUP &&notification_up);
-
-        void
-        ThreadWasCreated (lldb::tid_t tid, bool is_stopped, const ErrorFunction &error_function);
-
-        void
-        ThreadDidDie (lldb::tid_t tid, const ErrorFunction &error_function);
-
-        bool
-        IsKnownThread(lldb::tid_t tid) const;
-
-        void
-        Log (const char *format, ...);
-
-        // Member variables.
-        LogFunction m_log_function;
-        PendingNotificationUP m_pending_notification_up;
-
-        // Maps known TIDs to ThreadContext.
-        TIDContextMap m_tid_map;
-
-        bool m_log_event_processing;
-    };
-
-} // namespace process_linux
-} // namespace lldb_private
-
-#endif
index 10aa54a..a641b33 100644 (file)
@@ -29,5 +29,4 @@ endfunction()
 
 add_subdirectory(Host)
 add_subdirectory(Interpreter)
-add_subdirectory(Plugins)
 add_subdirectory(Utility)
diff --git a/lldb/unittests/Plugins/CMakeLists.txt b/lldb/unittests/Plugins/CMakeLists.txt
deleted file mode 100644 (file)
index d98183b..0000000
+++ /dev/null
@@ -1 +0,0 @@
-add_subdirectory(Process)
diff --git a/lldb/unittests/Plugins/Process/CMakeLists.txt b/lldb/unittests/Plugins/Process/CMakeLists.txt
deleted file mode 100644 (file)
index 9b4e784..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-if (CMAKE_SYSTEM_NAME MATCHES "Linux")
-  add_subdirectory(Linux)
-endif()
diff --git a/lldb/unittests/Plugins/Process/Linux/CMakeLists.txt b/lldb/unittests/Plugins/Process/Linux/CMakeLists.txt
deleted file mode 100644 (file)
index d5bedfb..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-add_lldb_unittest(ProcessLinuxTests
-  ThreadStateCoordinatorTest.cpp
-  )
diff --git a/lldb/unittests/Plugins/Process/Linux/Makefile b/lldb/unittests/Plugins/Process/Linux/Makefile
deleted file mode 100644 (file)
index 6817352..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-THIS_FILE_DIR := $(shell dirname $(realpath $(lastword $(MAKEFILE_LIST))))/
-
-LEVEL := $(realpath $(THIS_FILE_DIR)../../../../make)
-
-CFLAGS_EXTRAS := -D__STDC_LIMIT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_CONSTANT_MACROS
-ENABLE_THREADS := YES
-CXX_SOURCES := $(wildcard *.cpp) \
-       $(realpath $(LEVEL)/../../source/Plugins/Process/Linux/ThreadStateCoordinator.cpp) \
-       $(realpath $(LEVEL)/../../source/Core/Error.cpp)
-MAKE_DSYM := NO
-
-OS := $(shell uname -s)
-
-# $(info OS $(OS))
-ifeq ($(OS),Linux)
-    LD_EXTRAS := -lncurses -ldl
-endif
-
-include $(LEVEL)/Makefile.rules
diff --git a/lldb/unittests/Plugins/Process/Linux/ThreadStateCoordinatorTest.cpp b/lldb/unittests/Plugins/Process/Linux/ThreadStateCoordinatorTest.cpp
deleted file mode 100644 (file)
index 5ddf0f5..0000000
+++ /dev/null
@@ -1,714 +0,0 @@
-#include <limits.h>
-#include "gtest/gtest.h"
-
-#include "lldb/Core/Error.h"
-#include "Plugins/Process/Linux/ThreadStateCoordinator.h"
-
-using namespace lldb_private;
-using namespace process_linux;
-
-namespace
-{
-    const ThreadStateCoordinator::ThreadIDSet EMPTY_THREAD_ID_SET;
-
-    void
-    StdoutLogger (const char *format, va_list args)
-    {
-        // Print to stdout.
-        vprintf (format, args);
-        printf ("\n");
-    }
-
-    // These are single-line macros so that IDE integration of gtest results puts
-    // the error markers on the correct failure point within the gtest.
-
-#define ASSERT_PROCESS_EVENT_SUCCEEDED() do { \
-if (HasError ()) { printf ("unexpected error in processing of event, error: %s\n", m_error_string.c_str ()); } \
-ASSERT_EQ (false, HasError ()); } while(0)
-
-#define ASSERT_PROCESS_EVENT_FAILED() ASSERT_EQ (true, HasError ())
-
-    class ThreadStateCoordinatorTest: public ::testing::Test
-    {
-    protected:
-        // Constants.
-        const lldb::tid_t TRIGGERING_TID      = 4105;
-        const lldb::tid_t PENDING_STOP_TID    = 3;
-        const lldb::tid_t PENDING_STOP_TID_02 = 29016;
-        const lldb::tid_t NEW_THREAD_TID      = 1234;
-
-        // Member variables.
-        bool m_error_called = false;
-        std::string m_error_string;
-
-        ThreadStateCoordinator m_coordinator;
-
-        bool m_deferred_notification_called;
-        lldb::tid_t m_deferred_notification_tid;
-
-        ThreadStateCoordinator::ThreadIDSet m_requested_stop_tids;
-
-        // Constructors.
-        ThreadStateCoordinatorTest () :
-        m_error_called (false),
-        m_error_string (),
-        m_coordinator (StdoutLogger),
-        m_deferred_notification_called (false),
-        m_deferred_notification_tid (0),
-        m_requested_stop_tids ()
-        {
-        }
-
-        // Member functions.
-
-        // Error handling.
-        ThreadStateCoordinator::ErrorFunction
-        GetErrorFunction ()
-        {
-            return [this] (const std::string &error_string)
-            {
-                m_error_called = true;
-                m_error_string = error_string;
-                printf ("received error: %s (test might be expecting)\n", error_string.c_str ());
-            };
-        }
-
-        bool
-        HasError () const
-        {
-            return m_error_called;
-        }
-
-        // Deferred notification reception.
-        ThreadStateCoordinator::ThreadIDFunction
-        GetDeferredStopNotificationFunction ()
-        {
-            return [this] (lldb::tid_t triggered_tid)
-            {
-                m_deferred_notification_called = true;
-                m_deferred_notification_tid = triggered_tid;
-            };
-        }
-
-        bool
-        DidFireDeferredNotification () const
-        {
-            return m_deferred_notification_called;
-        }
-
-        lldb::tid_t
-        GetDeferredNotificationTID () const
-        {
-            return m_deferred_notification_tid;
-        }
-
-        // Stop request call reception.
-        ThreadStateCoordinator::StopThreadFunction
-        GetStopRequestFunction ()
-        {
-            return [this] (lldb::tid_t stop_tid)
-            {
-                m_requested_stop_tids.insert (stop_tid);
-                return Error();
-            };
-        }
-
-        ThreadStateCoordinator::ThreadIDSet::size_type
-        GetRequestedStopCount () const
-        {
-            return m_requested_stop_tids.size();
-        }
-
-        ThreadStateCoordinator::ResumeThreadFunction
-        GetResumeThreadFunction (lldb::tid_t& resumed_tid, int& resume_call_count)
-        {
-            return [this, &resumed_tid, &resume_call_count] (lldb::tid_t tid, bool)
-            {
-                resumed_tid = tid;
-                ++resume_call_count;
-                return Error();
-            };
-        }
-
-        bool
-        DidRequestStopForTid (lldb::tid_t tid)
-        {
-            return m_requested_stop_tids.find (tid) != m_requested_stop_tids.end ();
-        }
-
-        // Test state initialization helpers.
-        void
-        SetupKnownRunningThread (lldb::tid_t tid)
-        {
-            NotifyThreadCreate (tid, false);
-            ASSERT_PROCESS_EVENT_SUCCEEDED ();
-        }
-
-        void
-        SetupKnownStoppedThread (lldb::tid_t tid)
-        {
-            NotifyThreadCreate (tid, true);
-            ASSERT_PROCESS_EVENT_SUCCEEDED ();
-        }
-
-        // Convenience wrappers for ThreadStateCoordinator, using defaults for expected arguments
-        // that plug into the test case handlers.
-        void
-        CallAfterThreadsStop (lldb::tid_t deferred_tid,
-                              const ThreadStateCoordinator::ThreadIDSet &pending_stop_wait_tids)
-        {
-            m_coordinator.CallAfterThreadsStop (deferred_tid,
-                                                pending_stop_wait_tids,
-                                                GetStopRequestFunction (),
-                                                GetDeferredStopNotificationFunction (),
-                                                GetErrorFunction ());
-        }
-
-        void
-        CallAfterRunningThreadsStop (lldb::tid_t deferred_tid)
-        {
-            m_coordinator.CallAfterRunningThreadsStop (deferred_tid,
-                                                       GetStopRequestFunction (),
-                                                       GetDeferredStopNotificationFunction (),
-                                                       GetErrorFunction ());
-        }
-
-        void
-        NotifyThreadCreate (lldb::tid_t stopped_tid, bool thread_is_stopped)
-        {
-            m_coordinator.NotifyThreadCreate (stopped_tid, thread_is_stopped, GetErrorFunction ());
-        }
-
-        void
-        NotifyThreadStop (lldb::tid_t stopped_tid)
-        {
-            m_coordinator.NotifyThreadStop (stopped_tid, false, GetErrorFunction ());
-        }
-
-        void
-        NotifyThreadDeath (lldb::tid_t tid)
-        {
-            m_coordinator.NotifyThreadDeath (tid, GetErrorFunction ());
-        }
-    };
-}
-
-TEST_F (ThreadStateCoordinatorTest, NotifyThreadCreateSignalsErrorOnAlreadyKnownThread)
-{
-    // Let the coordinator know about our thread.
-    SetupKnownStoppedThread (TRIGGERING_TID);
-
-    // Notify the thread was created - again.
-    NotifyThreadCreate (TRIGGERING_TID, true);
-
-    // This should error out.
-    ASSERT_PROCESS_EVENT_FAILED ();
-}
-
-
-TEST_F (ThreadStateCoordinatorTest, NotifyThreadDeathSignalsErrorOnUnknownThread)
-{
-    const lldb::tid_t UNKNOWN_TID = 678;
-
-    // Notify an unknown thread has died.
-    NotifyThreadDeath (UNKNOWN_TID);
-
-    // This should error out.
-    ASSERT_PROCESS_EVENT_FAILED ();
-}
-
-TEST_F (ThreadStateCoordinatorTest, NotifyThreadStopSignalsErrorOnUnknownThread)
-{
-    const lldb::tid_t UNKNOWN_TID = 678;
-
-    // Notify an unknown thread has stopped.
-    NotifyThreadStop (UNKNOWN_TID);
-    ASSERT_PROCESS_EVENT_FAILED ();
-}
-
-TEST_F (ThreadStateCoordinatorTest, CallAfterTheadsStopSignalsErrorOnUnknownDeferredThread)
-{
-    const lldb::tid_t UNKNOWN_TRIGGER_TID = 678;
-
-    // Defer notify for an unknown thread.
-    CallAfterThreadsStop (UNKNOWN_TRIGGER_TID,
-                          EMPTY_THREAD_ID_SET);
-
-    // Shouldn't have fired yet.
-    ASSERT_EQ (false, DidFireDeferredNotification ());
-
-    // Event should fail because trigger tid is unknown.
-    ASSERT_PROCESS_EVENT_FAILED ();
-
-    // Shouldn't have fired due to error.
-    ASSERT_EQ (false, DidFireDeferredNotification ());
-}
-
-TEST_F (ThreadStateCoordinatorTest, CallAfterTheadsStopSignalsErrorOnUnknownPendingStopThread)
-{
-    // Let the coordinator know about our thread.
-    SetupKnownStoppedThread (TRIGGERING_TID);
-
-    // Defer notify for an unknown thread.
-    const lldb::tid_t UNKNOWN_PENDING_STOP_TID = 7890;
-    ThreadStateCoordinator::ThreadIDSet pending_stop_tids { UNKNOWN_PENDING_STOP_TID };
-
-    CallAfterThreadsStop (TRIGGERING_TID,
-                          pending_stop_tids);
-
-    // Shouldn't have fired yet.
-    ASSERT_EQ (false, DidFireDeferredNotification ());
-
-    // Event should fail because trigger tid is unknown.
-    ASSERT_PROCESS_EVENT_FAILED ();
-
-    // Shouldn't have triggered deferred notification due to error.
-    ASSERT_EQ (false, DidFireDeferredNotification ());
-
-    // Shouldn't have triggered stop request due to unknown tid.
-    ASSERT_EQ (0u, GetRequestedStopCount ());
-}
-
-TEST_F (ThreadStateCoordinatorTest, CallAfterThreadsStopFiresWhenNoPendingStops)
-{
-    // Let the coordinator know about our thread.
-    SetupKnownStoppedThread (TRIGGERING_TID);
-
-    // Notify we have a trigger that needs to be fired when all threads in the wait tid set have stopped.
-    CallAfterThreadsStop (TRIGGERING_TID,
-                          EMPTY_THREAD_ID_SET);
-    ASSERT_PROCESS_EVENT_SUCCEEDED ();
-
-    // The trigger should have fired, since there were no threads that needed to first stop.
-    ASSERT_EQ (true, DidFireDeferredNotification ());
-    ASSERT_EQ (TRIGGERING_TID, GetDeferredNotificationTID ());
-}
-
-TEST_F (ThreadStateCoordinatorTest, CallAfterThreadsStopFiresWhenOnePendingStop)
-{
-    // Let the coordinator know about our thread.
-    SetupKnownStoppedThread (TRIGGERING_TID);
-
-    // Let the coordinator know about a currently-running thread we'll wait on.
-    SetupKnownRunningThread (PENDING_STOP_TID);
-
-    ThreadStateCoordinator::ThreadIDSet pending_stop_tids { PENDING_STOP_TID };
-
-    // Notify we have a trigger that needs to be fired when all threads in the wait tid set have stopped.
-    CallAfterThreadsStop (TRIGGERING_TID,
-                          pending_stop_tids);
-    ASSERT_PROCESS_EVENT_SUCCEEDED ();
-
-    // The request thread stop should have been called for the pending stop.
-    ASSERT_EQ (true, DidRequestStopForTid (PENDING_STOP_TID));
-
-    // But we still shouldn't have the deferred signal call go off yet.  Need to wait for the stop to be reported.
-    ASSERT_EQ (false, DidFireDeferredNotification ());
-
-    // Now report the that the pending stop occurred.
-    NotifyThreadStop (PENDING_STOP_TID);
-    ASSERT_PROCESS_EVENT_SUCCEEDED ();
-
-    // Deferred signal notification should have fired now.
-    ASSERT_EQ (true, DidFireDeferredNotification ());
-    ASSERT_EQ (TRIGGERING_TID, GetDeferredNotificationTID ());
-}
-
-TEST_F (ThreadStateCoordinatorTest, CallAfterThreadsStopFiresWhenTwoPendingStops)
-{
-    // Setup threads.
-    SetupKnownStoppedThread (TRIGGERING_TID);
-    SetupKnownRunningThread (PENDING_STOP_TID);
-    SetupKnownRunningThread (PENDING_STOP_TID_02);
-
-    ThreadStateCoordinator::ThreadIDSet pending_stop_tids { PENDING_STOP_TID, PENDING_STOP_TID_02 };
-
-    // Notify we have a trigger that needs to be fired when all threads in the wait tid set have stopped.
-    CallAfterThreadsStop (TRIGGERING_TID,
-                          pending_stop_tids);
-    ASSERT_PROCESS_EVENT_SUCCEEDED ();
-
-    // The request thread stops should have been called for the pending stop tids.
-    ASSERT_EQ (2u, GetRequestedStopCount ());
-    ASSERT_EQ (true, DidRequestStopForTid (PENDING_STOP_TID));
-    ASSERT_EQ (true, DidRequestStopForTid (PENDING_STOP_TID_02));
-
-    // But we still shouldn't have the deferred signal call go off yet.  Need to wait for the stop to be reported.
-    ASSERT_EQ (false, DidFireDeferredNotification ());
-
-    // Report the that the first pending stop occurred.
-    NotifyThreadStop (PENDING_STOP_TID);
-    ASSERT_PROCESS_EVENT_SUCCEEDED ();
-
-    // Shouldn't take effect until after both pending threads are notified.
-    ASSERT_EQ (false, DidFireDeferredNotification ());
-
-    // Report the that the first pending stop occurred.
-    NotifyThreadStop (PENDING_STOP_TID_02);
-    ASSERT_PROCESS_EVENT_SUCCEEDED ();
-
-    // Deferred signal notification should have fired now.
-    ASSERT_EQ (true, DidFireDeferredNotification ());
-    ASSERT_EQ (TRIGGERING_TID, GetDeferredNotificationTID ());
-}
-
-TEST_F (ThreadStateCoordinatorTest, CallAfterThreadsStopFiresWhenPendingAlreadyStopped)
-{
-    // Setup threads.
-    SetupKnownStoppedThread (TRIGGERING_TID);
-    SetupKnownRunningThread (PENDING_STOP_TID);
-
-    ThreadStateCoordinator::ThreadIDSet pending_stop_tids { PENDING_STOP_TID };
-
-    // Tell m_coordinator the pending stop tid is already stopped.
-    NotifyThreadStop (PENDING_STOP_TID);
-    ASSERT_PROCESS_EVENT_SUCCEEDED ();
-
-    // Notify we have a trigger that needs to be fired when all threads in the wait tid set have stopped.
-    CallAfterThreadsStop (TRIGGERING_TID,
-                          pending_stop_tids);
-    ASSERT_PROCESS_EVENT_SUCCEEDED ();
-
-    // The pending stop should *not* fire because the m_coordinator knows it has already stopped.
-    ASSERT_EQ (false, DidRequestStopForTid (PENDING_STOP_TID));
-
-    // The deferred signal notification should have fired since all requirements were met.
-    ASSERT_EQ (true, DidFireDeferredNotification ());
-    ASSERT_EQ (TRIGGERING_TID, GetDeferredNotificationTID ());
-}
-
-TEST_F (ThreadStateCoordinatorTest, CallAfterThreadsStopFiresWhenTwoPendingOneAlreadyStopped)
-{
-    SetupKnownStoppedThread (TRIGGERING_TID);
-    SetupKnownRunningThread (PENDING_STOP_TID);
-    SetupKnownRunningThread (PENDING_STOP_TID_02);
-
-    ThreadStateCoordinator::ThreadIDSet pending_stop_tids { PENDING_STOP_TID, PENDING_STOP_TID_02 };
-
-    // Tell coordinator the pending stop tid is already stopped.
-    NotifyThreadStop (PENDING_STOP_TID);
-    ASSERT_PROCESS_EVENT_SUCCEEDED ();
-
-    // Notify we have a trigger that needs to be fired when all threads in the wait tid set have stopped.
-    CallAfterThreadsStop (TRIGGERING_TID,
-                          pending_stop_tids);
-    ASSERT_PROCESS_EVENT_SUCCEEDED ();
-
-    // The pending stop should only fire for one of the threads, the one that wasn't already stopped.
-    ASSERT_EQ (true, DidRequestStopForTid (PENDING_STOP_TID_02));
-    ASSERT_EQ (false, DidRequestStopForTid (PENDING_STOP_TID));
-
-    // The deferred signal notification should not yet have fired since all pending thread stops have not yet occurred.
-    ASSERT_EQ (false, DidFireDeferredNotification ());
-
-    // Notify final thread has stopped.
-    NotifyThreadStop (PENDING_STOP_TID_02);
-    ASSERT_PROCESS_EVENT_SUCCEEDED ();
-
-    // The deferred signal notification should have fired since all requirements were met.
-    ASSERT_EQ (true, DidFireDeferredNotification ());
-    ASSERT_EQ (TRIGGERING_TID, GetDeferredNotificationTID ());
-}
-
-TEST_F (ThreadStateCoordinatorTest, CallAfterThreadsStopFiresWhenOnePendingThreadDies)
-{
-    SetupKnownStoppedThread (TRIGGERING_TID);
-    SetupKnownRunningThread (PENDING_STOP_TID);
-
-    ThreadStateCoordinator::ThreadIDSet pending_stop_tids { PENDING_STOP_TID };
-
-    // Notify we have a trigger that needs to be fired when all threads in the wait tid set have stopped.
-    CallAfterThreadsStop (TRIGGERING_TID,
-                          pending_stop_tids);
-    ASSERT_PROCESS_EVENT_SUCCEEDED ();
-
-    // The request thread stop should have been called for the pending stop.
-    ASSERT_EQ (true, DidRequestStopForTid (PENDING_STOP_TID));
-
-    // 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, DidFireDeferredNotification ());
-
-    // Now report the that the thread with pending stop dies.
-    NotifyThreadDeath (PENDING_STOP_TID);
-    ASSERT_PROCESS_EVENT_SUCCEEDED ();
-
-    // Deferred signal notification should have fired now.
-    ASSERT_EQ (true, DidFireDeferredNotification ());
-    ASSERT_EQ (TRIGGERING_TID, GetDeferredNotificationTID ());
-}
-
-TEST_F (ThreadStateCoordinatorTest, ExistingPendingNotificationRequiresStopFromNewThread)
-{
-    SetupKnownStoppedThread (TRIGGERING_TID);
-    SetupKnownRunningThread (PENDING_STOP_TID);
-
-    ThreadStateCoordinator::ThreadIDSet pending_stop_tids { PENDING_STOP_TID };
-
-    // Notify we have a trigger that needs to be fired when all threads in the wait tid set have stopped.
-    CallAfterThreadsStop (TRIGGERING_TID,
-                          pending_stop_tids);
-    ASSERT_PROCESS_EVENT_SUCCEEDED ();
-
-    // Now the request thread stop should have been called for the pending stop.
-    ASSERT_EQ (true, DidRequestStopForTid (PENDING_STOP_TID));
-
-    // But we still shouldn't have the deferred signal call go off yet.
-    ASSERT_EQ (false, DidFireDeferredNotification ());
-
-    // Indicate a new thread has just been created.
-    SetupKnownRunningThread (NEW_THREAD_TID);
-
-    // We should have just received a stop request for the new thread id.
-    ASSERT_EQ (2u, GetRequestedStopCount ());
-    ASSERT_EQ (true, DidRequestStopForTid (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.
-    NotifyThreadStop (PENDING_STOP_TID);
-    ASSERT_PROCESS_EVENT_SUCCEEDED ();
-    ASSERT_EQ (false, DidFireDeferredNotification ());
-
-    // Now notify the new thread stopped.
-    NotifyThreadStop (NEW_THREAD_TID);
-    ASSERT_PROCESS_EVENT_SUCCEEDED ();
-
-    // Deferred signal notification should have fired now.
-    ASSERT_EQ (true, DidFireDeferredNotification ());
-    ASSERT_EQ (TRIGGERING_TID, GetDeferredNotificationTID ());
-}
-
-TEST_F (ThreadStateCoordinatorTest, RequestThreadResumeSignalsErrorOnUnknownThread)
-{
-    const lldb::tid_t UNKNOWN_TID = 411;
-
-    // Request a resume.
-    lldb::tid_t resumed_tid = 0;
-    int resume_call_count = 0;
-
-    m_coordinator.RequestThreadResume (UNKNOWN_TID,
-                                       GetResumeThreadFunction(resumed_tid, resume_call_count),
-                                       GetErrorFunction ());
-    // Shouldn't be called yet.
-    ASSERT_EQ (0, resume_call_count);
-
-    // Process next event.  This should fail since the coordinator doesn't know about the thread.
-    ASSERT_PROCESS_EVENT_FAILED ();
-    ASSERT_EQ (0, resume_call_count);
-}
-
-TEST_F (ThreadStateCoordinatorTest, RequestThreadResumeCallsCallbackWhenThreadIsStopped)
-{
-    // Initialize thread to be in stopped state.
-    SetupKnownStoppedThread (NEW_THREAD_TID);
-
-    // Request a resume.
-    lldb::tid_t resumed_tid = 0;
-    int resume_call_count = 0;
-
-    m_coordinator.RequestThreadResume (NEW_THREAD_TID,
-                                       GetResumeThreadFunction(resumed_tid, resume_call_count),
-                                       GetErrorFunction ());
-    ASSERT_PROCESS_EVENT_SUCCEEDED ();
-    ASSERT_EQ (1, resume_call_count);
-    ASSERT_EQ (NEW_THREAD_TID, resumed_tid);
-}
-
-TEST_F (ThreadStateCoordinatorTest, RequestThreadResumeSkipsCallbackOnSecondResumeAttempt)
-{
-    // Initialize thread to be in stopped state.
-    SetupKnownStoppedThread (NEW_THREAD_TID);
-
-    // Request a resume.
-    lldb::tid_t resumed_tid = 0;
-    int resume_call_count = 0;
-
-    m_coordinator.RequestThreadResume (NEW_THREAD_TID,
-                                       GetResumeThreadFunction(resumed_tid, resume_call_count),
-                                       GetErrorFunction ());
-    ASSERT_PROCESS_EVENT_SUCCEEDED ();
-    ASSERT_EQ (1, resume_call_count);
-    ASSERT_EQ (NEW_THREAD_TID, resumed_tid);
-
-    // Make a second resume request.
-    const int initial_resume_call_count = resume_call_count;
-    m_coordinator.RequestThreadResume (NEW_THREAD_TID,
-                                       GetResumeThreadFunction(resumed_tid, resume_call_count),
-                                       GetErrorFunction ());
-
-    // This should fail since the thread should already be running.
-    ASSERT_PROCESS_EVENT_FAILED ();
-
-    // And the resume count should not have increased.
-    ASSERT_EQ (initial_resume_call_count, resume_call_count);
-}
-
-TEST_F (ThreadStateCoordinatorTest, RequestThreadResumeSignalsErrorOnAlreadyRunningThread)
-{
-    const lldb::tid_t TEST_TID = 1234;
-    SetupKnownRunningThread (NEW_THREAD_TID);
-
-    // Request a resume.
-    lldb::tid_t resumed_tid = 0;
-    int resume_call_count = 0;
-
-    m_coordinator.RequestThreadResume (TEST_TID,
-                                       GetResumeThreadFunction(resumed_tid, resume_call_count),
-                                       GetErrorFunction ());
-
-    // Shouldn't be called yet.
-    ASSERT_EQ (0, resume_call_count);
-
-    // Process next event.  Should be an error.
-    ASSERT_PROCESS_EVENT_FAILED ();
-
-    // The resume request should not have gone off because we think it is already running.
-    ASSERT_EQ (0, resume_call_count);
-}
-
-TEST_F (ThreadStateCoordinatorTest, ResumedThreadAlreadyMarkedDoesNotHoldUpPendingStopNotification)
-{
-    // We're going to test this scenario:
-    //   * Deferred notification waiting on two threads, A and B.  A and B currently running.
-    //   * Thread A stops.
-    //   * Thread A resumes.
-    //   * Thread B stops.
-    //
-    //   Here we could have forced A to stop again (after the Thread A resumes) because we had a pending stop nofication awaiting
-    //   all those threads to stop.  However, we are going to explicitly not try to restop A - somehow
-    //   that seems wrong and possibly buggy since for that to happen, we would have intentionally called
-    //   a resume after the stop.  Instead, we'll just log and indicate this looks suspicous.  We can revisit
-    //   that decision after we see if/when that happens.
-    const lldb::tid_t PENDING_TID_A = 2;
-    const lldb::tid_t PENDING_TID_B = 89;
-
-    SetupKnownStoppedThread (TRIGGERING_TID);
-    SetupKnownRunningThread (PENDING_TID_A);
-    SetupKnownRunningThread (PENDING_TID_B);
-
-    ThreadStateCoordinator::ThreadIDSet pending_stop_tids { PENDING_TID_A, PENDING_TID_B };
-
-    // Notify we have a trigger that needs to be fired when all threads in the wait tid set have stopped.
-    CallAfterThreadsStop (TRIGGERING_TID,
-                          pending_stop_tids);
-    ASSERT_PROCESS_EVENT_SUCCEEDED ();
-
-    // Both TID A and TID B should have had stop requests made.
-    ASSERT_EQ (2u, GetRequestedStopCount ());
-    ASSERT_EQ (true, DidRequestStopForTid (PENDING_TID_A));
-    ASSERT_EQ (true, DidRequestStopForTid (PENDING_TID_B));
-
-    // But we still shouldn't have the deferred signal call go off yet.
-    ASSERT_EQ (false, DidFireDeferredNotification ());
-
-    // Report thread A stopped.
-    NotifyThreadStop (PENDING_TID_A);
-    ASSERT_PROCESS_EVENT_SUCCEEDED ();
-    ASSERT_EQ (false, DidFireDeferredNotification ());
-
-    // Now report thread A is resuming.  Ensure the resume is called.
-    lldb::tid_t resumed_tid = 0;
-    int resume_call_count = 0;
-    m_coordinator.RequestThreadResume (PENDING_TID_A,
-                                       GetResumeThreadFunction(resumed_tid, resume_call_count),
-                                       GetErrorFunction ());
-    ASSERT_PROCESS_EVENT_SUCCEEDED ();
-    ASSERT_EQ (1, resume_call_count);
-    ASSERT_EQ (PENDING_TID_A, resumed_tid);
-
-    // Report thread B stopped.
-    NotifyThreadStop (PENDING_TID_B);
-    ASSERT_PROCESS_EVENT_SUCCEEDED ();
-
-    // After notifying thread b stopped, we now have thread a resumed but thread b stopped.
-    // However, since thread a had stopped, we now have had both requirements stopped at some point.
-    // For now we'll expect this will fire the pending deferred stop notification.
-    ASSERT_EQ (true, DidFireDeferredNotification ());
-    ASSERT_EQ (TRIGGERING_TID, GetDeferredNotificationTID ());
-}
-
-TEST_F (ThreadStateCoordinatorTest, CallAfterRunningThreadsStopFiresWhenNoRunningThreads)
-{
-    // Let the coordinator know about our thread.
-    SetupKnownStoppedThread (TRIGGERING_TID);
-
-    // Notify we have a trigger that needs to be fired when all running threads have stopped.
-    CallAfterRunningThreadsStop (TRIGGERING_TID);
-    ASSERT_PROCESS_EVENT_SUCCEEDED ();
-
-    // The trigger should have fired, since there were no threads that needed to first stop.
-    ASSERT_EQ (true, DidFireDeferredNotification ());
-    ASSERT_EQ (TRIGGERING_TID, GetDeferredNotificationTID ());
-
-    // And no stop requests should have been made.
-    ASSERT_EQ (0u, GetRequestedStopCount ());
-}
-
-TEST_F (ThreadStateCoordinatorTest, CallAfterRunningThreadsStopRequestsTwoPendingStops)
-{
-    // Let the coordinator know about our threads.
-    SetupKnownStoppedThread (TRIGGERING_TID);
-    SetupKnownRunningThread (PENDING_STOP_TID);
-    SetupKnownRunningThread (PENDING_STOP_TID_02);
-
-    // Notify we have a trigger that needs to be fired when all running threads have stopped.
-    CallAfterRunningThreadsStop (TRIGGERING_TID);
-
-    // Notification trigger shouldn't go off yet.
-    ASSERT_EQ (false, DidFireDeferredNotification ());
-
-    // Process next event.  This will pick up the call after threads stop event.
-    ASSERT_PROCESS_EVENT_SUCCEEDED ();
-
-    // We should have two stop requests for the two threads currently running.
-    ASSERT_EQ (2u, GetRequestedStopCount ());
-    ASSERT_EQ (true, DidRequestStopForTid (PENDING_STOP_TID));
-    ASSERT_EQ (true, DidRequestStopForTid (PENDING_STOP_TID_02));
-
-    // But the deferred stop notification should not have fired yet.
-    ASSERT_EQ (false, DidFireDeferredNotification ());
-
-    // Now notify the two threads stopped.
-    NotifyThreadStop (PENDING_STOP_TID);
-    ASSERT_PROCESS_EVENT_SUCCEEDED ();
-    ASSERT_EQ (false, DidFireDeferredNotification ());
-
-    NotifyThreadStop (PENDING_STOP_TID_02);
-    ASSERT_PROCESS_EVENT_SUCCEEDED ();
-
-    // Now the trigger should have fired, since there were no threads that needed to first stop.
-    ASSERT_EQ (true, DidFireDeferredNotification ());
-    ASSERT_EQ (TRIGGERING_TID, GetDeferredNotificationTID ());
-}
-
-TEST_F (ThreadStateCoordinatorTest, CallAfterRunningThreadsStopRequestsStopTwoOtherThreadsOneRunning)
-{
-    // Let the coordinator know about our threads.  PENDING_STOP_TID_02 will already be stopped.
-    SetupKnownStoppedThread (TRIGGERING_TID);
-    SetupKnownRunningThread (PENDING_STOP_TID);
-    SetupKnownStoppedThread (PENDING_STOP_TID_02);
-
-    // Notify we have a trigger that needs to be fired when all running threads have stopped.
-    CallAfterRunningThreadsStop (TRIGGERING_TID);
-
-    // Notification trigger shouldn't go off yet.
-    ASSERT_EQ (false, DidFireDeferredNotification ());
-
-    // Process next event.  This will pick up the call after threads stop event.
-    ASSERT_PROCESS_EVENT_SUCCEEDED ();
-
-    // We should have two stop requests for the two threads currently running.
-    ASSERT_EQ (1u, GetRequestedStopCount ());
-    ASSERT_EQ (true, DidRequestStopForTid (PENDING_STOP_TID));
-
-    // But the deferred stop notification should not have fired yet.
-    ASSERT_EQ (false, DidFireDeferredNotification ());
-
-    // Now notify the two threads stopped.
-    NotifyThreadStop (PENDING_STOP_TID);
-    ASSERT_PROCESS_EVENT_SUCCEEDED ();
-
-    // Now the trigger should have fired, since there were no threads that needed to first stop.
-    ASSERT_EQ (true, DidFireDeferredNotification ());
-    ASSERT_EQ (TRIGGERING_TID, GetDeferredNotificationTID ());
-}