Thread safety changes in debugserver and also in the process GDB remote plugin.
I added support for asking if the GDB remote server supports thread suffixes
for packets that should be thread specific (register read/write packets) because
the way the GDB remote protocol does it right now is to have a notion of a
current thread for register and memory reads/writes (set via the "$Hg%x" packet)
and a current thread for running ("$Hc%x"). Now we ask the remote GDB server
if it supports adding the thread ID to the register packets and we enable
that feature in LLDB if supported. This stops us from having to send a bunch
of packets that update the current thread ID to some value which is prone to
error, or extra packets.



git-svn-id: https://llvm.org/svn/llvm-project/llvdb/trunk@123762 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
index 5925812..1a7b27b 100644
--- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
+++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
@@ -34,6 +34,7 @@
 GDBRemoteCommunication::GDBRemoteCommunication() :
     Communication("gdb-remote.packets"),
     m_send_acks (true),
+    m_thread_suffix_supported (false),
     m_rx_packet_listener ("gdbremote.rx_packet"),
     m_sequence_mutex (Mutex::eMutexTypeRecursive),
     m_is_running (false),
diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h b/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h
index 7bc795d..c0d8685 100644
--- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h
+++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h
@@ -100,6 +100,18 @@
     }
 
     bool
+    GetThreadSuffixSupported () const
+    {
+        return m_thread_suffix_supported;
+    }
+    
+    void
+    SetThreadSuffixSupported (bool enabled)
+    {
+        m_thread_suffix_supported = enabled;
+    }
+
+    bool
     SendAsyncSignal (int signo);
 
     bool
@@ -244,7 +256,8 @@
     //------------------------------------------------------------------
     // Classes that inherit from GDBRemoteCommunication can see and modify these
     //------------------------------------------------------------------
-    bool m_send_acks;
+    bool m_send_acks:1,
+         m_thread_suffix_supported:1;
     lldb_private::Listener m_rx_packet_listener;
     lldb_private::Mutex m_sequence_mutex;    // Restrict access to sending/receiving packets to a single thread at a time
     lldb_private::Predicate<bool> m_is_running;
diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp
index eaf91eb..2c00b9a 100644
--- a/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp
+++ b/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp
@@ -217,15 +217,19 @@
         Mutex::Locker locker;
         if (gdb_comm.GetSequenceMutex (locker))
         {
-            if (GetGDBProcess().SetCurrentGDBRemoteThread(m_thread.GetID()))
+            const bool thread_suffix_supported = gdb_comm.GetThreadSuffixSupported();
+            if (thread_suffix_supported || GetGDBProcess().SetCurrentGDBRemoteThread(m_thread.GetID()))
             {
-                char packet[32];
+                char packet[64];
                 StringExtractorGDBRemote response;
-                int packet_len;
+                int packet_len = 0;
                 if (m_read_all_at_once)
                 {
                     // Get all registers in one packet
-                    packet_len = ::snprintf (packet, sizeof(packet), "g");
+                    if (thread_suffix_supported)
+                        packet_len = ::snprintf (packet, sizeof(packet), "g;thread:%4.4x;", m_thread.GetID());
+                    else
+                        packet_len = ::snprintf (packet, sizeof(packet), "g");
                     assert (packet_len < (sizeof(packet) - 1));
                     if (gdb_comm.SendPacketAndWaitForResponse(packet, response, 1, false))
                     {
@@ -237,7 +241,10 @@
                 else
                 {
                     // Get each register individually
-                    packet_len = ::snprintf (packet, sizeof(packet), "p%x", reg);
+                    if (thread_suffix_supported)
+                        packet_len = ::snprintf (packet, sizeof(packet), "p%x;thread:%4.4x;", reg, m_thread.GetID());
+                    else
+                        packet_len = ::snprintf (packet, sizeof(packet), "p%x", reg);
                     assert (packet_len < (sizeof(packet) - 1));
                     if (gdb_comm.SendPacketAndWaitForResponse(packet, response, 1, false))
                         PrivateSetRegisterValue (reg, response);
@@ -319,7 +326,8 @@
         Mutex::Locker locker;
         if (gdb_comm.GetSequenceMutex (locker))
         {
-            if (GetGDBProcess().SetCurrentGDBRemoteThread(m_thread.GetID()))
+            const bool thread_suffix_supported = gdb_comm.GetThreadSuffixSupported();
+            if (thread_suffix_supported || GetGDBProcess().SetCurrentGDBRemoteThread(m_thread.GetID()))
             {
                 uint32_t offset, end_offset;
                 StreamString packet;
@@ -336,6 +344,9 @@
                                               eByteOrderHost,
                                               eByteOrderHost);
                     
+                    if (thread_suffix_supported)
+                        packet.Printf (";thread:%4.4x;", m_thread.GetID());
+
                     // Invalidate all register values
                     InvalidateIfNeeded (true);
 
@@ -361,6 +372,9 @@
                                               eByteOrderHost,
                                               eByteOrderHost);
 
+                    if (thread_suffix_supported)
+                        packet.Printf (";thread:%4.4x;", m_thread.GetID());
+
                     // Invalidate just this register
                     m_reg_valid[reg] = false;
                     if (gdb_comm.SendPacketAndWaitForResponse(packet.GetString().c_str(),
@@ -391,16 +405,31 @@
     Mutex::Locker locker;
     if (gdb_comm.GetSequenceMutex (locker))
     {
-        if (GetGDBProcess().SetCurrentGDBRemoteThread(m_thread.GetID()))
+        char packet[32];
+        const bool thread_suffix_supported = gdb_comm.GetThreadSuffixSupported();
+        if (thread_suffix_supported || GetGDBProcess().SetCurrentGDBRemoteThread(m_thread.GetID()))
         {
-            if (gdb_comm.SendPacketAndWaitForResponse("g", response, 1, false))
+            int packet_len = 0;
+            if (thread_suffix_supported)
+                packet_len = ::snprintf (packet, sizeof(packet), "g;thread:%4.4x", m_thread.GetID());
+            else
+                packet_len = ::snprintf (packet, sizeof(packet), "g");
+            assert (packet_len < (sizeof(packet) - 1));
+
+            if (gdb_comm.SendPacketAndWaitForResponse(packet, packet_len, response, 1, false))
             {
                 if (response.IsErrorPacket())
                     return false;
-                    
+                
                 response.GetStringRef().insert(0, 1, 'G');
-                data_sp.reset (new DataBufferHeap(response.GetStringRef().c_str(), 
-                                                  response.GetStringRef().size()));
+                if (thread_suffix_supported)
+                {
+                    char thread_id_cstr[64];
+                    ::snprintf (thread_id_cstr, sizeof(thread_id_cstr), ";thread:%4.4x;", m_thread.GetID());
+                    response.GetStringRef().append (thread_id_cstr);
+                }
+                data_sp.reset (new DataBufferHeap (response.GetStringRef().c_str(), 
+                                                   response.GetStringRef().size()));
                 return true;
             }
         }
@@ -419,7 +448,8 @@
     Mutex::Locker locker;
     if (gdb_comm.GetSequenceMutex (locker))
     {
-        if (GetGDBProcess().SetCurrentGDBRemoteThread(m_thread.GetID()))
+        const bool thread_suffix_supported = gdb_comm.GetThreadSuffixSupported();
+        if (thread_suffix_supported || GetGDBProcess().SetCurrentGDBRemoteThread(m_thread.GetID()))
         {
             if (gdb_comm.SendPacketAndWaitForResponse((const char *)data_sp->GetBytes(), 
                                                       data_sp->GetByteSize(), 
diff --git a/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp b/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
index 80580f8..26aa456 100644
--- a/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
+++ b/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
@@ -554,6 +554,13 @@
             if (response.IsOKPacket())
                 m_gdb_comm.SetAckMode (false);
         }
+
+        if (m_gdb_comm.SendPacketAndWaitForResponse("QThreadSuffixSupported", response, 1, false))
+        {
+            if (response.IsOKPacket())
+                m_gdb_comm.SetThreadSuffixSupported (true);
+        }
+
     }
     return error;
 }
@@ -2021,7 +2028,7 @@
         return true;
 
     char packet[32];
-    const int packet_len = ::snprintf (packet, sizeof(packet), "Hg%x", tid);
+    const int packet_len = ::snprintf (packet, sizeof(packet), "Hc%x", tid);
     assert (packet_len + 1 < sizeof(packet));
     StringExtractorGDBRemote response;
     if (m_gdb_comm.SendPacketAndWaitForResponse(packet, packet_len, response, 2, false))