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.
This commit is contained in:
Pedro Alves 2014-10-15 22:44:00 +01:00
parent e8032dde10
commit ab970af197
3 changed files with 50 additions and 4 deletions

View File

@ -1,3 +1,11 @@
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.
2014-10-15 Pedro Alves <palves@redhat.com>
* ada-tasks.c (print_ada_task_info, task_command_1): Adjust.

View File

@ -354,6 +354,14 @@ extern struct thread_info *iterate_over_threads (thread_callback_func, void *);
for (T = thread_list; T; T = T->next) \
if ((T)->state != THREAD_EXITED)
/* Like ALL_NON_EXITED_THREADS, but allows deleting the currently
iterated thread. */
#define ALL_NON_EXITED_THREADS_SAFE(T, TMP) \
for ((T) = thread_list; \
(T) != NULL ? ((TMP) = (T)->next, 1): 0; \
(T) = (TMP)) \
if ((T)->state != THREAD_EXITED)
extern int thread_count (void);
/* Switch from one thread to another. */

View File

@ -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;
/* Now add threads we don't know about yet to our list. */
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;
}
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);
}