@@ -171,6 +171,12 @@ GDBRemoteCommunication::~GDBRemoteCommunication()
171
171
{
172
172
Disconnect ();
173
173
}
174
+
175
+ // Stop the communications read thread which is used to parse all
176
+ // incoming packets. This function will block until the read
177
+ // thread returns.
178
+ if (m_read_thread_enabled)
179
+ StopReadThread ();
174
180
}
175
181
176
182
char
@@ -295,7 +301,7 @@ GDBRemoteCommunication::PacketResult
295
301
GDBRemoteCommunication::GetAck ()
296
302
{
297
303
StringExtractorGDBRemote packet;
298
- PacketResult result = WaitForPacketWithTimeoutMicroSecondsNoLock (packet, GetPacketTimeoutInMicroSeconds (), false );
304
+ PacketResult result = ReadPacket (packet, GetPacketTimeoutInMicroSeconds (), false );
299
305
if (result == PacketResult::Success)
300
306
{
301
307
if (packet.GetResponseType () == StringExtractorGDBRemote::ResponseType::eAck)
@@ -323,6 +329,62 @@ GDBRemoteCommunication::WaitForNotRunningPrivate (const TimeValue *timeout_ptr)
323
329
return m_private_is_running.WaitForValueEqualTo (false , timeout_ptr, NULL );
324
330
}
325
331
332
+ GDBRemoteCommunication::PacketResult
333
+ GDBRemoteCommunication::ReadPacket (StringExtractorGDBRemote &response, uint32_t timeout_usec, bool sync_on_timeout)
334
+ {
335
+ if (m_read_thread_enabled)
336
+ return PopPacketFromQueue (response, timeout_usec);
337
+ else
338
+ return WaitForPacketWithTimeoutMicroSecondsNoLock (response, timeout_usec, sync_on_timeout);
339
+ }
340
+
341
+
342
+ // This function is called when a packet is requested.
343
+ // A whole packet is popped from the packet queue and returned to the caller.
344
+ // Packets are placed into this queue from the communication read thread.
345
+ // See GDBRemoteCommunication::AppendBytesToCache.
346
+ GDBRemoteCommunication::PacketResult
347
+ GDBRemoteCommunication::PopPacketFromQueue (StringExtractorGDBRemote &response, uint32_t timeout_usec)
348
+ {
349
+ // Calculate absolute timeout value
350
+ TimeValue timeout = TimeValue::Now ();
351
+ timeout.OffsetWithMicroSeconds (timeout_usec);
352
+
353
+ do
354
+ {
355
+ // scope for the mutex
356
+ {
357
+ // lock down the packet queue
358
+ Mutex::Locker locker (m_packet_queue_mutex);
359
+
360
+ // Wait on condition variable.
361
+ if (m_packet_queue.size () == 0 )
362
+ m_condition_queue_not_empty.Wait (m_packet_queue_mutex, &timeout);
363
+
364
+ if (m_packet_queue.size () > 0 )
365
+ {
366
+ // get the front element of the queue
367
+ response = m_packet_queue.front ();
368
+
369
+ // remove the front element
370
+ m_packet_queue.pop ();
371
+
372
+ // we got a packet
373
+ return PacketResult::Success;
374
+ }
375
+ }
376
+
377
+ // Disconnected
378
+ if (!IsConnected ())
379
+ return PacketResult::ErrorDisconnected;
380
+
381
+ // Loop while not timed out
382
+ } while (TimeValue::Now () < timeout);
383
+
384
+ return PacketResult::ErrorReplyTimeout;
385
+ }
386
+
387
+
326
388
GDBRemoteCommunication::PacketResult
327
389
GDBRemoteCommunication::WaitForPacketWithTimeoutMicroSecondsNoLock (StringExtractorGDBRemote &packet, uint32_t timeout_usec, bool sync_on_timeout)
328
390
{
@@ -1094,3 +1156,53 @@ GDBRemoteCommunication::ScopedTimeout::~ScopedTimeout ()
1094
1156
{
1095
1157
m_gdb_comm.SetPacketTimeout (m_saved_timeout);
1096
1158
}
1159
+
1160
+ // This function is called via the Communications class read thread when bytes become available
1161
+ // for this connection. This function will consume all incoming bytes and try to parse whole
1162
+ // packets as they become available. Full packets are placed in a queue, so that all packet
1163
+ // requests can simply pop from this queue. Async notification packets will be dispatched
1164
+ // immediately to the ProcessGDBRemote Async thread via an event.
1165
+ void GDBRemoteCommunication::AppendBytesToCache (const uint8_t * bytes, size_t len, bool broadcast, lldb::ConnectionStatus status)
1166
+ {
1167
+ StringExtractorGDBRemote packet;
1168
+
1169
+ while (true )
1170
+ {
1171
+ PacketType type = CheckForPacket (bytes, len, packet);
1172
+
1173
+ // scrub the data so we do not pass it back to CheckForPacket
1174
+ // on future passes of the loop
1175
+ bytes = nullptr ;
1176
+ len = 0 ;
1177
+
1178
+ // we may have received no packet so lets bail out
1179
+ if (type == PacketType::Invalid)
1180
+ break ;
1181
+
1182
+ if (type == PacketType::Standard)
1183
+ {
1184
+ // scope for the mutex
1185
+ {
1186
+ // lock down the packet queue
1187
+ Mutex::Locker locker (m_packet_queue_mutex);
1188
+ // push a new packet into the queue
1189
+ m_packet_queue.push (packet);
1190
+ // Signal condition variable that we have a packet
1191
+ m_condition_queue_not_empty.Signal ();
1192
+
1193
+ }
1194
+ }
1195
+
1196
+ if (type == PacketType::Notify)
1197
+ {
1198
+ // put this packet into an event
1199
+ const char *pdata = packet.GetStringRef ().c_str ();
1200
+
1201
+ // as the communication class, we are a broadcaster and the
1202
+ // async thread is tuned to listen to us
1203
+ BroadcastEvent (
1204
+ eBroadcastBitGdbReadThreadGotNotify,
1205
+ new EventDataBytes (pdata));
1206
+ }
1207
+ }
1208
+ }
0 commit comments