diff options
author | Pedro Alves <palves@redhat.com> | 2014-10-15 22:44:00 +0100 |
---|---|---|
committer | Pedro Alves <palves@redhat.com> | 2014-10-15 22:55:14 +0100 |
commit | ab970af19746364a4f236bebc238ebb036adc898 (patch) | |
tree | 2302e629784df51901815310ee0e961185c6140b | |
parent | e8032dde10b743253125d7defb5f5503b21c1d26 (diff) | |
download | gdb-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.
-rw-r--r-- | gdb/ChangeLog | 8 | ||||
-rw-r--r-- | gdb/gdbthread.h | 8 | ||||
-rw-r--r-- | gdb/remote.c | 38 |
3 files changed, 50 insertions, 4 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 3a6bffd..abad945 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,5 +1,13 @@ 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. * bsd-uthread.c (bsd_uthread_find_new_threads): Rename to ... (bsd_uthread_update_thread_list): ... this. Call prune_threads. diff --git a/gdb/gdbthread.h b/gdb/gdbthread.h index 1ed98a2..937bd55 100644 --- a/gdb/gdbthread.h +++ b/gdb/gdbthread.h @@ -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. */ 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); } |