Re: [Lldb-commits] [PATCH] Add Read Thread to GDBRemoteCommunication.

2015-06-16 Thread Ewan Crawford
REPOSITORY
  rL LLVM

http://reviews.llvm.org/D10085

Files:
  lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
  lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h
  lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
  lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp

EMAIL PREFERENCES
  http://reviews.llvm.org/settings/panel/emailpreferences/
Index: lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
===
--- lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
+++ lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
@@ -145,7 +145,7 @@
 PacketResult packet_result = PacketResult::Success;
 const uint32_t timeout_usec = 10 * 1000; // Wait for 10 ms for a response
 while (packet_result == PacketResult::Success)
-packet_result = WaitForPacketWithTimeoutMicroSecondsNoLock (response, timeout_usec, false);
+packet_result = ReadPacket (response, timeout_usec, false);
 
 // The return value from QueryNoAckModeSupported() is true if the packet
 // was sent and _any_ response (including UNIMPLEMENTED) was received),
@@ -654,7 +654,7 @@
 {
 PacketResult packet_result = SendPacketNoLock (payload, payload_length);
 if (packet_result == PacketResult::Success)
-packet_result = WaitForPacketWithTimeoutMicroSecondsNoLock (response, GetPacketTimeoutInMicroSeconds (), true);
+packet_result = ReadPacket (response, GetPacketTimeoutInMicroSeconds (), true);
 return packet_result;
 }
 
@@ -670,6 +670,12 @@
 PacketResult packet_result = PacketResult::ErrorSendFailed;
 Mutex::Locker locker;
 Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PROCESS));
+
+// In order to stop async notifications from being processed in the middle of the
+// send/recieve sequence Hijack the broadcast. Then rebroadcast any events when we are done.
+static Listener hijack_listener("lldb.NotifyHijacker");
+HijackBroadcaster(&hijack_listener, eBroadcastBitGdbReadThreadGotNotify);
+
 if (GetSequenceMutex (locker))
 {
 packet_result = SendPacketAndWaitForResponseNoLock (payload, payload_length, response);
@@ -761,6 +767,15 @@
 log->Printf("error: failed to get packet sequence mutex, not sending packet '%*s'", (int) payload_length, payload);
 }
 }
+
+// Remove our Hijacking listner from the broadcast.
+RestoreBroadcaster();
+
+// If a notification event occured, rebroadcast since it can now be processed safely.  
+EventSP event_sp;
+if (hijack_listener.GetNextEvent(event_sp))
+BroadcastEvent(event_sp);
+
 return packet_result;
 }
 
@@ -902,9 +917,9 @@
 got_async_packet = false;
 
 if (log)
-log->Printf ("GDBRemoteCommunicationClient::%s () WaitForPacket(%s)", __FUNCTION__, continue_packet.c_str());
+log->Printf ("GDBRemoteCommunicationClient::%s () ReadPacket(%s)", __FUNCTION__, continue_packet.c_str());
 
-if (WaitForPacketWithTimeoutMicroSecondsNoLock(response, UINT32_MAX, false) == PacketResult::Success)
+if (ReadPacket(response, UINT32_MAX, false) == PacketResult::Success)
 {
 if (response.Empty())
 state = eStateInvalid;
@@ -961,7 +976,7 @@
 // packet to make sure it doesn't get in the way
 StringExtractorGDBRemote extra_stop_reply_packet;
 uint32_t timeout_usec = 1000;
-if (WaitForPacketWithTimeoutMicroSecondsNoLock (extra_stop_reply_packet, timeout_usec, false) == PacketResult::Success)
+if (ReadPacket (extra_stop_reply_packet, timeout_usec, false) == PacketResult::Success)
 {
 switch (extra_stop_reply_packet.GetChar())
 {
@@ -1139,7 +1154,7 @@
 else
 {
 if (log)
-log->Printf ("GDBRemoteCommunicationClient::%s () WaitForPacket(...) => false", __FUNCTION__);
+log->Printf ("GDBRemoteCommunicationClient::%s () ReadPacket(...) => false", __FUNCTION__);
 state = eStateInvalid;
 }
 }
Index: lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
===
--- lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
+++ lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
@@ -171,6 +171,12 @@
 {
 Disconnect();
 }
+
+// Stop the communications read thread which is used to parse all
+// incoming packets.  This function will block until the read
+// thread retu

Re: [Lldb-commits] [PATCH] Add Read Thread to GDBRemoteCommunication.

2015-06-15 Thread Greg Clayton
Looks fine as long as all tests still pass on MacOSX and there is no regression 
is packet speed test.


REPOSITORY
  rL LLVM

http://reviews.llvm.org/D10085

EMAIL PREFERENCES
  http://reviews.llvm.org/settings/panel/emailpreferences/



___
lldb-commits mailing list
lldb-commits@cs.uiuc.edu
http://lists.cs.uiuc.edu/mailman/listinfo/lldb-commits


Re: [Lldb-commits] [PATCH] Add Read Thread to GDBRemoteCommunication.

2015-06-11 Thread Ewan Crawford
I looked into how GDB processes async packets with only one thread. Essentially 
GDB has a high level event loop which listens for events from multiple sources. 
Events are queued and only processed later by calling the appropriate handler, 
allowing the event loop to continue listening for more events. There is an 
event for async notification packets which is generated when the notify packet 
is received, but only responded later so that it doesn't interfere with regular 
synchronous communication.  The event itself is generated from either polling 
the serial connection or looking for a synchronous response after a send.

For our purposes polling isn't the best solution since we can spawn a thread 
from Communication easily. However delaying the notify processing does address 
a race condition I didn't previously cover.

(a)  ---> m
 (b) <--- %notify
 (c)  [broadcast notify packet received]
 (d)  ---> vStopped [broadcast is handled by listener in AysncThread before 
reply to (a) is received]
 (e)  <--- memory reply to (a), unexpected response to vStopped.

This patch fixes this by getting SendPacketAndWaitForResponse() to Hijack the 
notify broadcast, then rebroadcasting after the synchronous response has been 
seen. Avoiding interference with regular synchronous communication.


REPOSITORY
  rL LLVM

http://reviews.llvm.org/D10085

Files:
  source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
  source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h
  source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
  source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp

EMAIL PREFERENCES
  http://reviews.llvm.org/settings/panel/emailpreferences/
Index: source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
===
--- source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
+++ source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
@@ -171,6 +171,12 @@
 {
 Disconnect();
 }
+
+// Stop the communications read thread which is used to parse all
+// incoming packets.  This function will block until the read
+// thread returns.
+if (m_read_thread_enabled)
+StopReadThread();
 }
 
 char
@@ -295,7 +301,7 @@
 GDBRemoteCommunication::GetAck ()
 {
 StringExtractorGDBRemote packet;
-PacketResult result = WaitForPacketWithTimeoutMicroSecondsNoLock (packet, GetPacketTimeoutInMicroSeconds (), false);
+PacketResult result = ReadPacket (packet, GetPacketTimeoutInMicroSeconds (), false);
 if (result == PacketResult::Success)
 {
 if (packet.GetResponseType() == StringExtractorGDBRemote::ResponseType::eAck)
@@ -324,6 +330,62 @@
 }
 
 GDBRemoteCommunication::PacketResult
+GDBRemoteCommunication::ReadPacket (StringExtractorGDBRemote &response, uint32_t timeout_usec, bool sync_on_timeout)
+{
+   if (m_read_thread_enabled)
+   return PopPacketFromQueue (response, timeout_usec);
+   else
+   return WaitForPacketWithTimeoutMicroSecondsNoLock (response, timeout_usec, sync_on_timeout);
+}
+
+
+// This function is called when a packet is requested.
+// A whole packet is popped from the packet queue and returned to the caller.
+// Packets are placed into this queue from the communication read thread.
+// See GDBRemoteCommunication::AppendBytesToCache.
+GDBRemoteCommunication::PacketResult
+GDBRemoteCommunication::PopPacketFromQueue (StringExtractorGDBRemote &response, uint32_t timeout_usec)
+{
+// Calculate absolute timeout value
+TimeValue timeout = TimeValue::Now();
+timeout.OffsetWithMicroSeconds(timeout_usec);
+
+do
+{
+// scope for the mutex
+{
+// lock down the packet queue
+Mutex::Locker locker(m_packet_queue_mutex);
+
+// Wait on condition variable.
+if (m_packet_queue.size() == 0)
+m_condition_queue_not_empty.Wait(m_packet_queue_mutex, &timeout);
+
+if (m_packet_queue.size() > 0)
+{
+// get the front element of the queue
+response = m_packet_queue.front();
+
+// remove the front element
+m_packet_queue.pop();
+
+// we got a packet
+return PacketResult::Success;
+}
+ }
+
+ // Disconnected
+ if (!IsConnected())
+ return PacketResult::ErrorDisconnected;
+
+  // Loop while not timed out
+} while (TimeValue::Now() < timeout);
+
+return PacketResult::ErrorReplyTimeout;
+}
+
+
+GDBRemoteCommunication::PacketResult
 GDBRemoteCommunication::WaitForPacketWithTimeoutMicroSecondsNoLock (StringExtractorGDBRemote &packet, uint32_t timeout_usec, bool sync_on_timeout)
 {
 uint8_t buffer[8192];
@@ -1094,3 +1156,53 @@
 {
 m_gdb_comm.SetPacketTimeout (m_saved_timeout);
 }
+
+// This function is called via the Communications class read thread when bytes become available
+// for this connection. Th

Re: [Lldb-commits] [PATCH] Add Read Thread to GDBRemoteCommunication.

2015-06-01 Thread Vince Harron
Ewan, has your non-stop mode implementation been tested against gdbserver?
On Jun 1, 2015 11:01 AM, "Greg Clayton"  wrote:

> My main concern with any threading is pairing the correct response to a
> the person that sent the packet. Are async packets marked so they
> absolutely can't be confused with any other response packets? I really
> don't like the fact that there are no sequence numbers in the sent/received
> packets because this makes it hard to know when you get the right response
> if a previous packet times out. I recently added "qEcho" to support making
> sure we stay on track and would like to ensure that any of the code added
> above won't let any packets receive the wrong reply packet.
>
>
> REPOSITORY
>   rL LLVM
>
> http://reviews.llvm.org/D10085
>
> EMAIL PREFERENCES
>   http://reviews.llvm.org/settings/panel/emailpreferences/
>
>
>
___
lldb-commits mailing list
lldb-commits@cs.uiuc.edu
http://lists.cs.uiuc.edu/mailman/listinfo/lldb-commits