aboutsummaryrefslogtreecommitdiff
path: root/gdb/remote.c
diff options
context:
space:
mode:
authorPedro Alves <palves@redhat.com>2014-10-15 22:44:00 +0100
committerPedro Alves <palves@redhat.com>2014-10-15 22:55:14 +0100
commitab970af19746364a4f236bebc238ebb036adc898 (patch)
tree2302e629784df51901815310ee0e961185c6140b /gdb/remote.c
parente8032dde10b743253125d7defb5f5503b21c1d26 (diff)
downloadgdb-ab970af19746364a4f236bebc238ebb036adc898.zip
gdb-ab970af19746364a4f236bebc238ebb036adc898.tar.gz
gdb-ab970af19746364a4f236bebc238ebb036adc898.tar.bz2
remote: get rid of all the T packets when syncing the thread list
This commit avoids the prune_threads call in the remote target's target_update_thread_list's implementation, eliminating all the "thread alive" RSP traffic (one packet per thread) whenever we fetch the thread list. IOW, this: Sending packet: $Tp2141.2150#82...Packet received: OK Sending packet: $Tp2141.214f#b7...Packet received: OK Sending packet: $Tp2141.2141#82...Packet received: OK ... more T packets; it's one per previously known live thread ... Sending packet: $qXfer:threads:read::0,fff#03...Packet received: l<threads>\n<thread id="p2141.2141" core="2"/>\n<thread id="p2141.214f" core="1"/>\n<thread id="p2141.2150" core="2"/>\n</threads>\n Becomes: Sending packet: $qXfer:threads:read::0,fff#03...Packet received: l<threads>\n<thread id="p2141.2141" core="2"/>\n<thread id="p2141.214f" core="1"/>\n<thread id="p2141.2150" core="2"/>\n</threads>\n Tested on x86_64 Fedora 20, native gdbserver: - tests the qXfer:threads:read method. Tested on x86_64 Fedora 20, native gdbserver with qXfer:threads:read force-disabled in gdbserver: - So that GDB falls back to the qfThreadInfo/qsThreadInfo method. And also manually smoked tested force disabling both qXfer:threads:read and qfThreadInfo/qsThreadInfo in gdbserver. gdb/ 2014-10-15 Pedro Alves <palves@redhat.com> * gdbthread.h (ALL_NON_EXITED_THREADS_SAFE): New macro. * remote.c (remote_update_thread_list): Skip calling prune_threads if any thread listing method is supported, and instead walk over the set of remote threads listed, deleting those that are not found in GDB's thread list.
Diffstat (limited to 'gdb/remote.c')
-rw-r--r--gdb/remote.c38
1 files changed, 34 insertions, 4 deletions
diff --git a/gdb/remote.c b/gdb/remote.c
index cd85fd5..98d3f2a 100644
--- a/gdb/remote.c
+++ b/gdb/remote.c
@@ -2762,9 +2762,7 @@ remote_update_thread_list (struct target_ops *ops)
struct remote_state *rs = get_remote_state ();
struct threads_listing_context context;
struct cleanup *old_chain;
-
- /* Delete GDB-side threads no longer found on the target. */
- prune_threads ();
+ int got_list = 0;
context.items = NULL;
old_chain = make_cleanup (clear_threads_listing_context, &context);
@@ -2778,8 +2776,31 @@ remote_update_thread_list (struct target_ops *ops)
{
int i;
struct thread_item *item;
+ struct thread_info *tp, *tmp;
+
+ got_list = 1;
+
+ /* CONTEXT now holds the current thread list on the remote
+ target end. Delete GDB-side threads no longer found on the
+ target. */
+ ALL_NON_EXITED_THREADS_SAFE (tp, tmp)
+ {
+ for (i = 0;
+ VEC_iterate (thread_item_t, context.items, i, item);
+ ++i)
+ {
+ if (ptid_equal (item->ptid, tp->ptid))
+ break;
+ }
- /* Now add threads we don't know about yet to our list. */
+ if (i == VEC_length (thread_item_t, context.items))
+ {
+ /* Not found. */
+ delete_thread (tp->ptid);
+ }
+ }
+
+ /* And now add threads we don't know about yet to our list. */
for (i = 0;
VEC_iterate (thread_item_t, context.items, i, item);
++i)
@@ -2803,6 +2824,15 @@ remote_update_thread_list (struct target_ops *ops)
}
}
+ if (!got_list)
+ {
+ /* If no thread listing method is supported, then query whether
+ each known thread is alive, one by one, with the T packet.
+ If the target doesn't support threads at all, then this is a
+ no-op. See remote_thread_alive. */
+ prune_threads ();
+ }
+
do_cleanups (old_chain);
}