* [PATCH 1/4] Merge remote thread listing methods
2014-10-02 16:21 [PATCH 0/4] remote thread listing: get rid of unnecessary "thread alive?" traffic Pedro Alves
@ 2014-10-02 16:21 ` Pedro Alves
2014-10-17 8:57 ` Jiong Wang
2014-10-02 16:21 ` [PATCH 3/4] remote: get rid of all the T packets when synching the thread list Pedro Alves
` (3 subsequent siblings)
4 siblings, 1 reply; 12+ messages in thread
From: Pedro Alves @ 2014-10-02 16:21 UTC (permalink / raw)
To: gdb-patches
We have three methods to list the current remote thread list:
1. The qXfer:threads:read method (the prefered one nowadays), builds a
remote thread list while parsing the XML, and then after the XML
parsing is done, goes over the built list and adds threads GDB doesn't
know about yet to GDB's list.
2. If the qXfer method isn't available, we fallback to using the
qfThreadInfo/qsThreadInfo packets. When we do this, we adds threads
to GDB's list immediately as we parse the qfThreadInfo/qsThreadInfo
packet replies.
3. And then if the previous method isn't available either, we try the
old deprecated qL packet. This path is already looking somewhat
broken for not using remote_notice_new_inferior to add threads to
GDB's list.
This patch makes all variants work in two passes, like the qXfer
method, and then makes all variants share the code path that adds
threads to GDB's list.
Tested on x86_64 Fedora 20 with native gdbserver.
gdb/
2014-10-02 Pedro Alves <palves@redhat.com>
* remote.c (remote_get_threadlist, remote_threadlist_iterator):
Add describing comment. Return -1 if the qL packet is not
supported.
(struct thread_item, thread_item_t): Move higher up in
the file. Add comments.
(struct threads_parsing_context): Move higher up in
the file, add comments, and remote to ...
(struct threads_listing_context): ... this.
(remote_newthread_step): Don't add the thread to GDB's thread
database here. Instead push it to the thread_listing_context
list.
(remote_find_new_threads): Rename to ...
(remote_get_threads_with_ql): ... this. Add target_ops and
targets_listing_context parameters. Pass down context.
(start_thread): Adjust.
(clear_threads_parsing_context): Rename to ...
(clear_threads_listing_context): ... this.
(remote_get_threads_with_qxfer): New, with parts salvaged from old
remote_threads_info.
(remote_get_threads_with_qthreadinfo): Ditto.
(remote_threads_info): Reimplement.
---
gdb/remote.c | 298 ++++++++++++++++++++++++++++++++---------------------------
1 file changed, 161 insertions(+), 137 deletions(-)
diff --git a/gdb/remote.c b/gdb/remote.c
index 41ea012..e4776cc 100644
--- a/gdb/remote.c
+++ b/gdb/remote.c
@@ -169,8 +169,6 @@ static int stub_unpack_int (char *buff, int fieldlength);
static ptid_t remote_current_thread (ptid_t oldptid);
-static void remote_find_new_threads (void);
-
static int putpkt_binary (const char *buf, int cnt);
static void check_binary_download (CORE_ADDR addr);
@@ -2428,6 +2426,9 @@ parse_threadlist_response (char *pkt, int result_limit,
return resultcount;
}
+/* Fetch the next batch of threads from the remote. Returns -1 if the
+ qL packet is not supported, 0 on error and 1 on success. */
+
static int
remote_get_threadlist (int startflag, threadref *nextthread, int result_limit,
int *done, int *result_count, threadref *threadlist)
@@ -2443,13 +2444,15 @@ remote_get_threadlist (int startflag, threadref *nextthread, int result_limit,
pack_threadlist_request (rs->buf, startflag, result_limit, nextthread);
putpkt (rs->buf);
getpkt (&rs->buf, &rs->buf_size, 0);
-
if (*rs->buf == '\0')
- return 0;
- else
- *result_count =
- parse_threadlist_response (rs->buf + 2, result_limit,
- &rs->echo_nextthread, threadlist, done);
+ {
+ /* Packet not supported. */
+ return -1;
+ }
+
+ *result_count =
+ parse_threadlist_response (rs->buf + 2, result_limit,
+ &rs->echo_nextthread, threadlist, done);
if (!threadmatch (&rs->echo_nextthread, nextthread))
{
@@ -2482,15 +2485,11 @@ remote_get_threadlist (int startflag, threadref *nextthread, int result_limit,
return result;
}
-/* This is the interface between remote and threads, remotes upper
- interface. */
-
-/* remote_find_new_threads retrieves the thread list and for each
- thread in the list, looks up the thread in GDB's internal list,
- adding the thread if it does not already exist. This involves
- getting partial thread lists from the remote target so, polling the
- quit_flag is required. */
-
+/* Fetch the list of remote threads, with the qL packet, and call
+ STEPFUNCTION for each thread found. Stops iterating and returns 1
+ if STEPFUNCTION returns true. Stops iterating and returns 0 if the
+ STEPFUNCTION returns false. If the packet is not supported,
+ returns -1. */
static int
remote_threadlist_iterator (rmt_thread_action stepfunction, void *context,
@@ -2511,13 +2510,12 @@ remote_threadlist_iterator (rmt_thread_action stepfunction, void *context,
warning (_("Remote fetch threadlist -infinite loop-."));
break;
}
- if (!remote_get_threadlist (startflag, &rs->nextthread,
- MAXTHREADLISTRESULTS,
- &done, &result_count, rs->resultthreadlist))
- {
- result = 0;
- break;
- }
+ result = remote_get_threadlist (startflag, &rs->nextthread,
+ MAXTHREADLISTRESULTS,
+ &done, &result_count,
+ rs->resultthreadlist);
+ if (result <= 0)
+ break;
/* Clear for later iterations. */
startflag = 0;
/* Setup to resume next batch of thread references, set nextthread. */
@@ -2526,20 +2524,55 @@ remote_threadlist_iterator (rmt_thread_action stepfunction, void *context,
&rs->resultthreadlist[result_count - 1]);
i = 0;
while (result_count--)
- if (!(result = (*stepfunction) (&rs->resultthreadlist[i++], context)))
- break;
+ {
+ if (!(*stepfunction) (&rs->resultthreadlist[i++], context))
+ {
+ result = 0;
+ break;
+ }
+ }
}
return result;
}
+/* A thread found on the remote target. */
+
+typedef struct thread_item
+{
+ /* The thread's PTID. */
+ ptid_t ptid;
+
+ /* The thread's extra info. May be NULL. */
+ char *extra;
+
+ /* The core the thread was running on. -1 if not known. */
+ int core;
+} thread_item_t;
+DEF_VEC_O(thread_item_t);
+
+/* Context passed around to the various methods listing remote
+ threads. As new threads are found, they're added to the ITEMS
+ vector. */
+
+struct threads_listing_context
+{
+ /* The threads found on the remote target. */
+ VEC (thread_item_t) *items;
+};
+
static int
-remote_newthread_step (threadref *ref, void *context)
+remote_newthread_step (threadref *ref, void *data)
{
+ struct threads_listing_context *context = data;
+ struct thread_item item;
int pid = ptid_get_pid (inferior_ptid);
- ptid_t ptid = ptid_build (pid, threadref_to_int (ref), 0);
- if (!in_thread_list (ptid))
- add_thread (ptid);
+ item.ptid = ptid_build (pid, threadref_to_int (ref), 0);
+ item.core = -1;
+ item.extra = NULL;
+
+ VEC_safe_push (thread_item_t, context->items, &item);
+
return 1; /* continue iterator */
}
@@ -2558,38 +2591,27 @@ remote_current_thread (ptid_t oldpid)
return oldpid;
}
-/* Find new threads for info threads command.
- * Original version, using John Metzler's thread protocol.
- */
+/* List remote threads using the deprecated qL packet. */
-static void
-remote_find_new_threads (void)
+static int
+remote_get_threads_with_ql (struct target_ops *ops,
+ struct threads_listing_context *context)
{
- remote_threadlist_iterator (remote_newthread_step, 0,
- CRAZY_MAX_THREADS);
+ if (remote_threadlist_iterator (remote_newthread_step, context,
+ CRAZY_MAX_THREADS) >= 0)
+ return 1;
+
+ return 0;
}
#if defined(HAVE_LIBEXPAT)
-typedef struct thread_item
-{
- ptid_t ptid;
- char *extra;
- int core;
-} thread_item_t;
-DEF_VEC_O(thread_item_t);
-
-struct threads_parsing_context
-{
- VEC (thread_item_t) *items;
-};
-
static void
start_thread (struct gdb_xml_parser *parser,
const struct gdb_xml_element *element,
void *user_data, VEC(gdb_xml_value_s) *attributes)
{
- struct threads_parsing_context *data = user_data;
+ struct threads_listing_context *data = user_data;
struct thread_item item;
char *id;
@@ -2614,7 +2636,7 @@ end_thread (struct gdb_xml_parser *parser,
const struct gdb_xml_element *element,
void *user_data, const char *body_text)
{
- struct threads_parsing_context *data = user_data;
+ struct threads_listing_context *data = user_data;
if (body_text && *body_text)
VEC_last (thread_item_t, data->items)->extra = xstrdup (body_text);
@@ -2646,9 +2668,9 @@ const struct gdb_xml_element threads_elements[] = {
/* Discard the contents of the constructed thread info context. */
static void
-clear_threads_parsing_context (void *p)
+clear_threads_listing_context (void *p)
{
- struct threads_parsing_context *context = p;
+ struct threads_listing_context *context = p;
int i;
struct thread_item *item;
@@ -2660,124 +2682,126 @@ clear_threads_parsing_context (void *p)
#endif
-/*
- * Find all threads for info threads command.
- * Uses new thread protocol contributed by Cisco.
- * Falls back and attempts to use the older method (above)
- * if the target doesn't respond to the new method.
- */
+/* List remote threads using qXfer:threads:read. */
-static void
-remote_threads_info (struct target_ops *ops)
+static int
+remote_get_threads_with_qxfer (struct target_ops *ops,
+ struct threads_listing_context *context)
{
- struct remote_state *rs = get_remote_state ();
- char *bufp;
- ptid_t new_thread;
-
- if (rs->remote_desc == 0) /* paranoia */
- error (_("Command can only be used when connected to the remote target."));
-
#if defined(HAVE_LIBEXPAT)
if (packet_support (PACKET_qXfer_threads) == PACKET_ENABLE)
{
- char *xml = target_read_stralloc (¤t_target,
- TARGET_OBJECT_THREADS, NULL);
-
+ char *xml = target_read_stralloc (ops, TARGET_OBJECT_THREADS, NULL);
struct cleanup *back_to = make_cleanup (xfree, xml);
- if (xml && *xml)
+ if (xml != NULL && *xml != '\0')
{
- struct threads_parsing_context context;
-
- context.items = NULL;
- make_cleanup (clear_threads_parsing_context, &context);
-
- if (gdb_xml_parse_quick (_("threads"), "threads.dtd",
- threads_elements, xml, &context) == 0)
- {
- int i;
- struct thread_item *item;
-
- for (i = 0;
- VEC_iterate (thread_item_t, context.items, i, item);
- ++i)
- {
- if (!ptid_equal (item->ptid, null_ptid))
- {
- struct private_thread_info *info;
- /* In non-stop mode, we assume new found threads
- are running until proven otherwise with a
- stop reply. In all-stop, we can only get
- here if all threads are stopped. */
- int running = non_stop ? 1 : 0;
-
- remote_notice_new_inferior (item->ptid, running);
-
- info = demand_private_info (item->ptid);
- info->core = item->core;
- info->extra = item->extra;
- item->extra = NULL;
- }
- }
- }
+ gdb_xml_parse_quick (_("threads"), "threads.dtd",
+ threads_elements, xml, context);
}
do_cleanups (back_to);
- return;
+ return 1;
}
#endif
+ return 0;
+}
+
+/* List remote threads using qfThreadInfo/qsThreadInfo. */
+
+static int
+remote_get_threads_with_qthreadinfo (struct target_ops *ops,
+ struct threads_listing_context *context)
+{
+ struct remote_state *rs = get_remote_state ();
+
if (rs->use_threadinfo_query)
{
+ char *bufp;
+
putpkt ("qfThreadInfo");
getpkt (&rs->buf, &rs->buf_size, 0);
bufp = rs->buf;
if (bufp[0] != '\0') /* q packet recognized */
{
- struct cleanup *old_chain;
- char *saved_reply;
-
- /* remote_notice_new_inferior (in the loop below) may make
- new RSP calls, which clobber rs->buf. Work with a
- copy. */
- bufp = saved_reply = xstrdup (rs->buf);
- old_chain = make_cleanup (free_current_contents, &saved_reply);
-
while (*bufp++ == 'm') /* reply contains one or more TID */
{
do
{
- new_thread = read_ptid (bufp, &bufp);
- if (!ptid_equal (new_thread, null_ptid))
- {
- /* In non-stop mode, we assume new found threads
- are running until proven otherwise with a
- stop reply. In all-stop, we can only get
- here if all threads are stopped. */
- int running = non_stop ? 1 : 0;
+ struct thread_item item;
- remote_notice_new_inferior (new_thread, running);
- }
+ item.ptid = read_ptid (bufp, &bufp);
+ item.core = -1;
+ item.extra = NULL;
+
+ VEC_safe_push (thread_item_t, context->items, &item);
}
while (*bufp++ == ','); /* comma-separated list */
- free_current_contents (&saved_reply);
putpkt ("qsThreadInfo");
getpkt (&rs->buf, &rs->buf_size, 0);
- bufp = saved_reply = xstrdup (rs->buf);
+ bufp = rs->buf;
}
- do_cleanups (old_chain);
- return; /* done */
+ return 1;
+ }
+ else
+ {
+ /* Packet not recognized. */
+ rs->use_threadinfo_query = 0;
}
}
- /* Only qfThreadInfo is supported in non-stop mode. */
- if (non_stop)
- return;
+ return 0;
+}
+
+/* Implement the to_find_new_threads function for the remote
+ targets. */
+
+static void
+remote_threads_info (struct target_ops *ops)
+{
+ struct remote_state *rs = get_remote_state ();
+ struct threads_listing_context context;
+ struct cleanup *old_chain;
+
+ context.items = NULL;
+ old_chain = make_cleanup (clear_threads_listing_context, &context);
+
+ /* We have a few different mechanisms to fetch the thread list. Try
+ them all, starting with the most preferred one first, falling
+ back to older methods. */
+ if (remote_get_threads_with_qxfer (ops, &context)
+ || remote_get_threads_with_qthreadinfo (ops, &context)
+ || remote_get_threads_with_ql (ops, &context))
+ {
+ int i;
+ struct thread_item *item;
- /* Else fall back to old method based on jmetzler protocol. */
- rs->use_threadinfo_query = 0;
- remote_find_new_threads ();
- return;
+ /* Add threads we don't know about yet to our list. */
+ for (i = 0;
+ VEC_iterate (thread_item_t, context.items, i, item);
+ ++i)
+ {
+ if (!ptid_equal (item->ptid, null_ptid))
+ {
+ struct private_thread_info *info;
+ /* In non-stop mode, we assume new found threads are
+ running until proven otherwise with a stop reply. In
+ all-stop, we can only get here if all threads are
+ stopped. */
+ int running = non_stop ? 1 : 0;
+
+ remote_notice_new_inferior (item->ptid, running);
+
+ info = demand_private_info (item->ptid);
+ info->core = item->core;
+ info->extra = item->extra;
+ item->extra = NULL;
+ }
+ }
+ }
+
+ do_cleanups (old_chain);
}
/*
--
1.9.3
^ permalink raw reply [flat|nested] 12+ messages in thread* Re: [PATCH 1/4] Merge remote thread listing methods
2014-10-02 16:21 ` [PATCH 1/4] Merge remote thread listing methods Pedro Alves
@ 2014-10-17 8:57 ` Jiong Wang
2014-10-17 10:17 ` [PATCH] Fix build without libexpat (Re: [PATCH 1/4] Merge remote thread listing methods) Pedro Alves
0 siblings, 1 reply; 12+ messages in thread
From: Jiong Wang @ 2014-10-17 8:57 UTC (permalink / raw)
To: Pedro Alves, gdb-patches
On 02/10/14 17:21, Pedro Alves wrote:
> +
> +static void
> +remote_threads_info (struct target_ops *ops)
> +{
> + struct remote_state *rs = get_remote_state ();
> + struct threads_listing_context context;
> + struct cleanup *old_chain;
> +
> + context.items = NULL;
> + old_chain = make_cleanup (clear_threads_listing_context, &context);
>
Hi Pedro,
looks like this change break arm native build on chrome book.
clear_threads_listing_context only exist when HAVE_LIBEXPACT defined.
Reagrds,
Jiong
^ permalink raw reply [flat|nested] 12+ messages in thread* [PATCH] Fix build without libexpat (Re: [PATCH 1/4] Merge remote thread listing methods)
2014-10-17 8:57 ` Jiong Wang
@ 2014-10-17 10:17 ` Pedro Alves
2014-10-17 10:21 ` Jiong Wang
0 siblings, 1 reply; 12+ messages in thread
From: Pedro Alves @ 2014-10-17 10:17 UTC (permalink / raw)
To: Jiong Wang, gdb-patches
Hi Jiong,
> looks like this change break arm native build on chrome book.
>
> clear_threads_listing_context only exist when HAVE_LIBEXPACT defined.
Thanks, fixed with the patch below. Though you should really link
with libexpat. gdb processes built-in xml files even when
native debugging.
----
From 80134cf5b3ca1f75a96af1856fdaad29ad1f57aa Mon Sep 17 00:00:00 2001
From: Pedro Alves <palves@redhat.com>
Date: Fri, 17 Oct 2014 11:05:06 +0100
Subject: [PATCH] Fix build without libexpat
clear_threads_listing_context is used for thread listing methods other
than the xml based, but it's only defined when HAVE_LIBEXPAT is defined.
gdb/
2014-10-17 Pedro Alves <palves@redhat.com>
* remote.c (clear_threads_listing_context): Move higher up, out of
the HAVE_LIBEXPAT guard.
---
gdb/ChangeLog | 5 +++++
gdb/remote.c | 30 +++++++++++++++---------------
2 files changed, 20 insertions(+), 15 deletions(-)
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 62d1d06..1ea76a5 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,8 @@
+2014-10-17 Pedro Alves <palves@redhat.com>
+
+ * remote.c (clear_threads_listing_context): Move higher up, out of
+ the HAVE_LIBEXPAT guard.
+
2014-10-16 Tristan Gingold <gingold@adacore.com>
* i386-darwin-nat.c (i386_darwin_fetch_inferior_registers)
diff --git a/gdb/remote.c b/gdb/remote.c
index 98d3f2a..20f2988 100644
--- a/gdb/remote.c
+++ b/gdb/remote.c
@@ -2559,6 +2559,21 @@ struct threads_listing_context
VEC (thread_item_t) *items;
};
+/* Discard the contents of the constructed thread listing context. */
+
+static void
+clear_threads_listing_context (void *p)
+{
+ struct threads_listing_context *context = p;
+ int i;
+ struct thread_item *item;
+
+ for (i = 0; VEC_iterate (thread_item_t, context->items, i, item); ++i)
+ xfree (item->extra);
+
+ VEC_free (thread_item_t, context->items);
+}
+
static int
remote_newthread_step (threadref *ref, void *data)
{
@@ -2664,21 +2679,6 @@ const struct gdb_xml_element threads_elements[] = {
{ NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL }
};
-/* Discard the contents of the constructed thread info context. */
-
-static void
-clear_threads_listing_context (void *p)
-{
- struct threads_listing_context *context = p;
- int i;
- struct thread_item *item;
-
- for (i = 0; VEC_iterate (thread_item_t, context->items, i, item); ++i)
- xfree (item->extra);
-
- VEC_free (thread_item_t, context->items);
-}
-
#endif
/* List remote threads using qXfer:threads:read. */
--
1.9.3
^ permalink raw reply [flat|nested] 12+ messages in thread* Re: [PATCH] Fix build without libexpat (Re: [PATCH 1/4] Merge remote thread listing methods)
2014-10-17 10:17 ` [PATCH] Fix build without libexpat (Re: [PATCH 1/4] Merge remote thread listing methods) Pedro Alves
@ 2014-10-17 10:21 ` Jiong Wang
0 siblings, 0 replies; 12+ messages in thread
From: Jiong Wang @ 2014-10-17 10:21 UTC (permalink / raw)
To: Pedro Alves, gdb-patches
On 17/10/14 11:17, Pedro Alves wrote:
> Hi Jiong,
>
>> looks like this change break arm native build on chrome book.
>>
>> clear_threads_listing_context only exist when HAVE_LIBEXPACT defined.
> Thanks, fixed with the patch below. Though you should really link
> with libexpat. gdb processes built-in xml files even when
> native debugging.
I see, great, thanks!
Regards,
Jiong
>
> ----
> >From 80134cf5b3ca1f75a96af1856fdaad29ad1f57aa Mon Sep 17 00:00:00 2001
> From: Pedro Alves <palves@redhat.com>
> Date: Fri, 17 Oct 2014 11:05:06 +0100
> Subject: [PATCH] Fix build without libexpat
>
> clear_threads_listing_context is used for thread listing methods other
> than the xml based, but it's only defined when HAVE_LIBEXPAT is defined.
>
> gdb/
> 2014-10-17 Pedro Alves <palves@redhat.com>
>
> * remote.c (clear_threads_listing_context): Move higher up, out of
> the HAVE_LIBEXPAT guard.
> ---
> gdb/ChangeLog | 5 +++++
> gdb/remote.c | 30 +++++++++++++++---------------
> 2 files changed, 20 insertions(+), 15 deletions(-)
>
> diff --git a/gdb/ChangeLog b/gdb/ChangeLog
> index 62d1d06..1ea76a5 100644
> --- a/gdb/ChangeLog
> +++ b/gdb/ChangeLog
> @@ -1,3 +1,8 @@
> +2014-10-17 Pedro Alves <palves@redhat.com>
> +
> + * remote.c (clear_threads_listing_context): Move higher up, out of
> + the HAVE_LIBEXPAT guard.
> +
> 2014-10-16 Tristan Gingold <gingold@adacore.com>
>
> * i386-darwin-nat.c (i386_darwin_fetch_inferior_registers)
> diff --git a/gdb/remote.c b/gdb/remote.c
> index 98d3f2a..20f2988 100644
> --- a/gdb/remote.c
> +++ b/gdb/remote.c
> @@ -2559,6 +2559,21 @@ struct threads_listing_context
> VEC (thread_item_t) *items;
> };
>
> +/* Discard the contents of the constructed thread listing context. */
> +
> +static void
> +clear_threads_listing_context (void *p)
> +{
> + struct threads_listing_context *context = p;
> + int i;
> + struct thread_item *item;
> +
> + for (i = 0; VEC_iterate (thread_item_t, context->items, i, item); ++i)
> + xfree (item->extra);
> +
> + VEC_free (thread_item_t, context->items);
> +}
> +
> static int
> remote_newthread_step (threadref *ref, void *data)
> {
> @@ -2664,21 +2679,6 @@ const struct gdb_xml_element threads_elements[] = {
> { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL }
> };
>
> -/* Discard the contents of the constructed thread info context. */
> -
> -static void
> -clear_threads_listing_context (void *p)
> -{
> - struct threads_listing_context *context = p;
> - int i;
> - struct thread_item *item;
> -
> - for (i = 0; VEC_iterate (thread_item_t, context->items, i, item); ++i)
> - xfree (item->extra);
> -
> - VEC_free (thread_item_t, context->items);
> -}
> -
> #endif
>
> /* List remote threads using qXfer:threads:read. */
^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH 3/4] remote: get rid of all the T packets when synching the thread list
2014-10-02 16:21 [PATCH 0/4] remote thread listing: get rid of unnecessary "thread alive?" traffic Pedro Alves
2014-10-02 16:21 ` [PATCH 1/4] Merge remote thread listing methods Pedro Alves
@ 2014-10-02 16:21 ` Pedro Alves
2014-10-02 16:21 ` [PATCH 2/4] Push pruning old threads down to the target Pedro Alves
` (2 subsequent siblings)
4 siblings, 0 replies; 12+ messages in thread
From: Pedro Alves @ 2014-10-02 16:21 UTC (permalink / raw)
To: gdb-patches
This commit avoids the prune_threads call in the remote target's
target_update_thread_list's implemention, 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-02 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.
---
gdb/gdbthread.h | 8 ++++++++
gdb/remote.c | 38 ++++++++++++++++++++++++++++++++++----
2 files changed, 42 insertions(+), 4 deletions(-)
diff --git a/gdb/gdbthread.h b/gdb/gdbthread.h
index 31675a1..b85e9d7 100644
--- a/gdb/gdbthread.h
+++ b/gdb/gdbthread.h
@@ -329,6 +329,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 74f57f8..8913cd2 100644
--- a/gdb/remote.c
+++ b/gdb/remote.c
@@ -2763,9 +2763,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);
@@ -2779,8 +2777,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)
@@ -2804,6 +2825,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);
}
--
1.9.3
^ permalink raw reply [flat|nested] 12+ messages in thread* [PATCH 2/4] Push pruning old threads down to the target
2014-10-02 16:21 [PATCH 0/4] remote thread listing: get rid of unnecessary "thread alive?" traffic Pedro Alves
2014-10-02 16:21 ` [PATCH 1/4] Merge remote thread listing methods Pedro Alves
2014-10-02 16:21 ` [PATCH 3/4] remote: get rid of all the T packets when synching the thread list Pedro Alves
@ 2014-10-02 16:21 ` Pedro Alves
2016-12-09 6:38 ` Thomas Schwinge
2014-10-02 16:21 ` [PATCH 4/4] DEC threads: Simplify updating the thread list Pedro Alves
2014-10-15 22:01 ` [pushed] Re: [PATCH 0/4] remote thread listing: get rid of unnecessary "thread alive?" traffic Pedro Alves
4 siblings, 1 reply; 12+ messages in thread
From: Pedro Alves @ 2014-10-02 16:21 UTC (permalink / raw)
To: gdb-patches
When GDB wants to sync the thread list with the target's (e.g., due to
"info threads"), it calls update_thread_list:
update_thread_list (void)
{
prune_threads ();
target_find_new_threads ();
update_threads_executing ();
}
And then prune_threads does:
prune_threads (void)
{
struct thread_info *tp, *next;
for (tp = thread_list; tp; tp = next)
{
next = tp->next;
if (!thread_alive (tp))
delete_thread (tp->ptid);
}
}
Calling thread_live on each thread one by one is expensive.
E.g., on Linux, it ends up doing kill(SIG0) once for each thread. Not
a big deal, but still a bunch of syscalls...
With the remote target, it's cumbersome. That thread_alive call ends
up generating one T packet per thread:
Sending packet: $Tp2141.2150#82...Packet received: OK
Sending packet: $Tp2141.214f#b7...Packet received: OK
Sending packet: $Tp2141.2141#82...Packet received: OK
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
That seems a bit silly when target_find_new_threads method
implementations will always fetch the whole current set of target
threads, and then add those that are not in GDB's thread list, to
GDB's thread list.
This patch thus pushes down the responsability of pruning dead threads
to the target_find_new_threads method instead, so a target may
implement pruning dead threads however it wants.
Once we do that, target_find_new_threads becomes a misnomer, so the
patch renames it to target_update_thread_list.
The patch doesn't attempt to do any optimization to any target yet.
It simply exports prune_threads, and makes all implementations of
target_update_thread_list call that. It's meant to be a no-op.
gdb/
2014-10-02 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.
(bsd_uthread_target): Adjust.
* corelow.c (core_open): Adjust.
* dec-thread.c (dec_thread_find_new_threads): Update comment.
(dec_thread_update_thread_list): New function.
(init_dec_thread_ops): Adjust.
* gdbthread.h (prune_threads): New declaration.
* linux-thread-db.c (thread_db_find_new_threads): Rename to ...
(thread_db_update_thread_list): ... this. Call prune_threads.
(init_thread_db_ops): Adjust.
* nto-procfs.c (procfs_find_new_threads): Rename to ...
(procfs_update_thread_list): ... this. Call prune_threads.
(procfs_attach, procfs_create_inferior, init_procfs_targets):
Adjust.
* obsd-nat.c (obsd_find_new_threads): Rename to ...
(obsd_update_thread_list): ... this. Call prune_threads.
(obsd_add_target): Adjust.
* procfs.c (procfs_target): Adjust.
(procfs_notice_thread): Update comment.
(procfs_find_new_threads): Rename to ...
(procfs_update_thread_list): ... this. Call prune_threads.
* ravenscar-thread.c (ravenscar_update_inferior_ptid): Update
comment.
(ravenscar_wait): Adjust.
(ravenscar_find_new_threads): Rename to ...
(ravenscar_update_thread_list): ... this. Call prune_threads.
(init_ravenscar_thread_ops): Adjust.
* record-btrace.c (record_btrace_find_new_threads): Rename to ...
(record_btrace_update_thread_list): ... this. Adjust comment.
(init_record_btrace_ops): Adjust.
* remote.c (remote_threads_info): Rename to ...
(remote_update_thread_list): ... this. Call prune_threads.
(remote_start_remote, extended_remote_attach_1, init_remote_ops):
Adjust.
* sol-thread.c (check_for_thread_db): Adjust.
(sol_find_new_threads_callback): Rename to ...
(sol_update_thread_list_callback): ... this.
(sol_find_new_threads): Rename to ...
(sol_update_thread_list): ... this. Call prune_threads. Adjust.
(sol_get_ada_task_ptid, init_sol_thread_ops): Adjust.
* target-delegates.c: Regenerate.
* target.c (target_find_new_threads): Rename to ...
(target_update_thread_list): ... this.
* target.h (struct target_ops): Rename to_find_new_threads field
to to_update_thread_list.
(target_find_new_threads): Rename to ...
(target_update_thread_list): ... this.
* thread.c (prune_threads): Make extern.
(update_thread_list): Adjust.
---
gdb/ada-tasks.c | 4 ++--
gdb/bsd-uthread.c | 6 ++++--
gdb/corelow.c | 2 +-
gdb/dec-thread.c | 19 +++++++++++++++++--
gdb/gdbthread.h | 4 ++++
gdb/linux-thread-db.c | 6 ++++--
gdb/nto-procfs.c | 10 ++++++----
gdb/obsd-nat.c | 6 ++++--
gdb/procfs.c | 10 ++++++----
gdb/ravenscar-thread.c | 10 +++++-----
gdb/record-btrace.c | 10 +++++-----
gdb/remote.c | 17 ++++++++++-------
gdb/sol-thread.c | 21 ++++++++++++---------
gdb/target-delegates.c | 22 +++++++++++-----------
gdb/target.c | 4 ++--
gdb/target.h | 6 +++---
gdb/thread.c | 8 ++++----
17 files changed, 100 insertions(+), 65 deletions(-)
diff --git a/gdb/ada-tasks.c b/gdb/ada-tasks.c
index 585c1f6..2d5a19d 100644
--- a/gdb/ada-tasks.c
+++ b/gdb/ada-tasks.c
@@ -1025,7 +1025,7 @@ print_ada_task_info (struct ui_out *uiout,
take a --thread argument. However, in order to be able to
provide that thread ID, the thread list must be up to date
first. */
- target_find_new_threads ();
+ target_update_thread_list ();
data = get_ada_tasks_inferior_data (inf);
@@ -1291,7 +1291,7 @@ task_command_1 (char *taskno_str, int from_tty, struct inferior *inf)
to the thread associated to our task if GDB does not know about
that thread, we need to make sure that any new threads gets added
to the thread list. */
- target_find_new_threads ();
+ target_update_thread_list ();
/* Verify that the ptid of the task we want to switch to is valid
(in other words, a ptid that GDB knows about). Otherwise, we will
diff --git a/gdb/bsd-uthread.c b/gdb/bsd-uthread.c
index 817a14b..ebe27be 100644
--- a/gdb/bsd-uthread.c
+++ b/gdb/bsd-uthread.c
@@ -412,12 +412,14 @@ bsd_uthread_thread_alive (struct target_ops *ops, ptid_t ptid)
}
static void
-bsd_uthread_find_new_threads (struct target_ops *ops)
+bsd_uthread_update_thread_list (struct target_ops *ops)
{
pid_t pid = ptid_get_pid (inferior_ptid);
int offset = bsd_uthread_thread_next_offset;
CORE_ADDR addr;
+ prune_threads ();
+
addr = bsd_uthread_read_memory_address (bsd_uthread_thread_list_addr);
while (addr != 0)
{
@@ -516,7 +518,7 @@ bsd_uthread_target (void)
t->to_wait = bsd_uthread_wait;
t->to_resume = bsd_uthread_resume;
t->to_thread_alive = bsd_uthread_thread_alive;
- t->to_find_new_threads = bsd_uthread_find_new_threads;
+ t->to_update_thread_list = bsd_uthread_update_thread_list;
t->to_extra_thread_info = bsd_uthread_extra_thread_info;
t->to_pid_to_str = bsd_uthread_pid_to_str;
t->to_stratum = thread_stratum;
diff --git a/gdb/corelow.c b/gdb/corelow.c
index 30d3367..e3ca6e9 100644
--- a/gdb/corelow.c
+++ b/gdb/corelow.c
@@ -414,7 +414,7 @@ core_open (const char *arg, int from_tty)
sections. */
TRY_CATCH (except, RETURN_MASK_ERROR)
{
- target_find_new_threads ();
+ target_update_thread_list ();
}
if (except.reason < 0)
diff --git a/gdb/dec-thread.c b/gdb/dec-thread.c
index 080640d..fc43153 100644
--- a/gdb/dec-thread.c
+++ b/gdb/dec-thread.c
@@ -394,7 +394,7 @@ dec_thread_add_gdb_thread (struct thread_info *info, void *context)
return 0;
}
-/* Implement the find_new_thread target_ops method. */
+/* Find new threads. */
static void
dec_thread_find_new_threads (struct target_ops *ops)
@@ -412,6 +412,21 @@ dec_thread_find_new_threads (struct target_ops *ops)
}
}
+/* Implement the update_thread_list target_ops method. */
+
+static void
+dec_thread_update_thread_list (struct target_ops *ops)
+{
+ int i;
+ struct dec_thread_info *info;
+
+ /* Delete dead threads. */
+ prune_threads ();
+
+ /* Now find new threads. */
+ dec_thread_find_new_threads (ops);
+}
+
/* Resynchronize the list of threads known by GDB with the actual
list of threads reported by libpthread_debug. */
@@ -717,7 +732,7 @@ init_dec_thread_ops (void)
dec_thread_ops.to_store_registers = dec_thread_store_registers;
dec_thread_ops.to_mourn_inferior = dec_thread_mourn_inferior;
dec_thread_ops.to_thread_alive = dec_thread_thread_alive;
- dec_thread_ops.to_find_new_threads = dec_thread_find_new_threads;
+ dec_thread_ops.to_update_thread_list = dec_thread_update_thread_list;
dec_thread_ops.to_pid_to_str = dec_thread_pid_to_str;
dec_thread_ops.to_stratum = thread_stratum;
dec_thread_ops.to_get_ada_task_ptid = dec_thread_get_ada_task_ptid;
diff --git a/gdb/gdbthread.h b/gdb/gdbthread.h
index 26ca925..31675a1 100644
--- a/gdb/gdbthread.h
+++ b/gdb/gdbthread.h
@@ -419,6 +419,10 @@ extern struct thread_info* inferior_thread (void);
extern void update_thread_list (void);
+/* Delete any thread the target says is no longer alive. */
+
+extern void prune_threads (void);
+
/* Return true if PC is in the stepping range of THREAD. */
int pc_in_thread_step_range (CORE_ADDR pc, struct thread_info *thread);
diff --git a/gdb/linux-thread-db.c b/gdb/linux-thread-db.c
index 8adcb40..63d5265 100644
--- a/gdb/linux-thread-db.c
+++ b/gdb/linux-thread-db.c
@@ -1718,11 +1718,13 @@ update_thread_core (struct lwp_info *info, void *closure)
}
static void
-thread_db_find_new_threads (struct target_ops *ops)
+thread_db_update_thread_list (struct target_ops *ops)
{
struct thread_db_info *info;
struct inferior *inf;
+ prune_threads ();
+
ALL_INFERIORS (inf)
{
struct thread_info *thread;
@@ -2075,7 +2077,7 @@ init_thread_db_ops (void)
thread_db_ops.to_wait = thread_db_wait;
thread_db_ops.to_resume = thread_db_resume;
thread_db_ops.to_mourn_inferior = thread_db_mourn_inferior;
- thread_db_ops.to_find_new_threads = thread_db_find_new_threads;
+ thread_db_ops.to_update_thread_list = thread_db_update_thread_list;
thread_db_ops.to_pid_to_str = thread_db_pid_to_str;
thread_db_ops.to_stratum = thread_stratum;
thread_db_ops.to_has_thread_control = tc_schedlock;
diff --git a/gdb/nto-procfs.c b/gdb/nto-procfs.c
index 7903210..cf53b6b 100644
--- a/gdb/nto-procfs.c
+++ b/gdb/nto-procfs.c
@@ -309,7 +309,7 @@ update_thread_private_data (struct thread_info *new_thread,
}
static void
-procfs_find_new_threads (struct target_ops *ops)
+procfs_update_thread_list (struct target_ops *ops)
{
procfs_status status;
pid_t pid;
@@ -320,6 +320,8 @@ procfs_find_new_threads (struct target_ops *ops)
if (ctl_fd == -1)
return;
+ prune_threads ();
+
pid = ptid_get_pid (inferior_ptid);
status.tid = 1;
@@ -633,7 +635,7 @@ procfs_attach (struct target_ops *ops, const char *args, int from_tty)
if (!target_is_pushed (ops))
push_target (ops);
- procfs_find_new_threads (ops);
+ procfs_update_thread_list (ops);
}
static void
@@ -1195,7 +1197,7 @@ procfs_create_inferior (struct target_ops *ops, char *exec_file,
close (fds[2]);
inferior_ptid = do_attach (pid_to_ptid (pid));
- procfs_find_new_threads (ops);
+ procfs_update_thread_list (ops);
inf = current_inferior ();
inferior_appeared (inf, pid);
@@ -1440,7 +1442,7 @@ init_procfs_targets (void)
t->to_mourn_inferior = procfs_mourn_inferior;
t->to_pass_signals = procfs_pass_signals;
t->to_thread_alive = procfs_thread_alive;
- t->to_find_new_threads = procfs_find_new_threads;
+ t->to_update_thread_list = procfs_update_thread_list;
t->to_pid_to_str = procfs_pid_to_str;
t->to_stop = procfs_stop;
t->to_have_continuable_watchpoint = 1;
diff --git a/gdb/obsd-nat.c b/gdb/obsd-nat.c
index e4a98ae..94bf56a 100644
--- a/gdb/obsd-nat.c
+++ b/gdb/obsd-nat.c
@@ -50,11 +50,13 @@ obsd_pid_to_str (struct target_ops *ops, ptid_t ptid)
}
static void
-obsd_find_new_threads (struct target_ops *ops)
+obsd_update_thread_list (struct target_ops *ops)
{
pid_t pid = ptid_get_pid (inferior_ptid);
struct ptrace_thread_state pts;
+ prune_threads ();
+
if (ptrace (PT_GET_THREAD_FIRST, pid, (caddr_t)&pts, sizeof pts) == -1)
perror_with_name (("ptrace"));
@@ -168,7 +170,7 @@ obsd_add_target (struct target_ops *t)
{
/* Override some methods to support threads. */
t->to_pid_to_str = obsd_pid_to_str;
- t->to_find_new_threads = obsd_find_new_threads;
+ t->to_update_thread_list = obsd_update_thread_list;
t->to_wait = obsd_wait;
add_target (t);
}
diff --git a/gdb/procfs.c b/gdb/procfs.c
index 15a0409..bd91a46 100644
--- a/gdb/procfs.c
+++ b/gdb/procfs.c
@@ -133,7 +133,7 @@ static target_xfer_partial_ftype procfs_xfer_partial;
static int procfs_thread_alive (struct target_ops *ops, ptid_t);
-static void procfs_find_new_threads (struct target_ops *ops);
+static void procfs_update_thread_list (struct target_ops *ops);
static char *procfs_pid_to_str (struct target_ops *, ptid_t);
static int proc_find_memory_regions (struct target_ops *self,
@@ -196,7 +196,7 @@ procfs_target (void)
t->to_files_info = procfs_files_info;
t->to_stop = procfs_stop;
- t->to_find_new_threads = procfs_find_new_threads;
+ t->to_update_thread_list = procfs_update_thread_list;
t->to_thread_alive = procfs_thread_alive;
t->to_pid_to_str = procfs_pid_to_str;
@@ -4646,7 +4646,7 @@ procfs_inferior_created (struct target_ops *ops, int from_tty)
#endif
}
-/* Callback for find_new_threads. Calls "add_thread". */
+/* Callback for update_thread_list. Calls "add_thread". */
static int
procfs_notice_thread (procinfo *pi, procinfo *thread, void *ptr)
@@ -4663,10 +4663,12 @@ procfs_notice_thread (procinfo *pi, procinfo *thread, void *ptr)
back to GDB to add to its list. */
static void
-procfs_find_new_threads (struct target_ops *ops)
+procfs_update_thread_list (struct target_ops *ops)
{
procinfo *pi;
+ prune_threads ();
+
/* Find procinfo for main process. */
pi = find_procinfo_or_die (ptid_get_pid (inferior_ptid), 0);
proc_update_threads (pi);
diff --git a/gdb/ravenscar-thread.c b/gdb/ravenscar-thread.c
index acee55e..f1db1a8 100644
--- a/gdb/ravenscar-thread.c
+++ b/gdb/ravenscar-thread.c
@@ -52,7 +52,7 @@ static const char first_task_name[] = "system__tasking__debug__first_task";
static const char ravenscar_runtime_initializer[] =
"system__bb__threads__initialize";
-static void ravenscar_find_new_threads (struct target_ops *ops);
+static void ravenscar_update_thread_list (struct target_ops *ops);
static ptid_t ravenscar_running_thread (void);
static char *ravenscar_extra_thread_info (struct target_ops *self,
struct thread_info *tp);
@@ -91,7 +91,7 @@ ravenscar_update_inferior_ptid (void)
gdb_assert (!ptid_equal (inferior_ptid, null_ptid));
/* The running thread may not have been added to
- system.tasking.debug's list yet; so ravenscar_find_new_threads
+ system.tasking.debug's list yet; so ravenscar_update_thread_list
may not always add it to the thread list. Add it here. */
if (!find_thread_ptid (inferior_ptid))
add_thread (inferior_ptid);
@@ -201,7 +201,7 @@ ravenscar_wait (struct target_ops *ops, ptid_t ptid,
if (status->kind != TARGET_WAITKIND_EXITED
&& status->kind != TARGET_WAITKIND_SIGNALLED)
{
- ravenscar_find_new_threads (ops);
+ ravenscar_update_thread_list (ops);
ravenscar_update_inferior_ptid ();
}
return inferior_ptid;
@@ -218,7 +218,7 @@ ravenscar_add_thread (struct ada_task_info *task)
}
static void
-ravenscar_find_new_threads (struct target_ops *ops)
+ravenscar_update_thread_list (struct target_ops *ops)
{
ada_build_task_list ();
@@ -368,7 +368,7 @@ init_ravenscar_thread_ops (void)
ravenscar_ops.to_store_registers = ravenscar_store_registers;
ravenscar_ops.to_prepare_to_store = ravenscar_prepare_to_store;
ravenscar_ops.to_thread_alive = ravenscar_thread_alive;
- ravenscar_ops.to_find_new_threads = ravenscar_find_new_threads;
+ ravenscar_ops.to_update_thread_list = ravenscar_update_thread_list;
ravenscar_ops.to_pid_to_str = ravenscar_pid_to_str;
ravenscar_ops.to_extra_thread_info = ravenscar_extra_thread_info;
ravenscar_ops.to_get_ada_task_ptid = ravenscar_get_ada_task_ptid;
diff --git a/gdb/record-btrace.c b/gdb/record-btrace.c
index 430c795..fa01fee 100644
--- a/gdb/record-btrace.c
+++ b/gdb/record-btrace.c
@@ -1791,18 +1791,18 @@ record_btrace_decr_pc_after_break (struct target_ops *ops,
return ops->beneath->to_decr_pc_after_break (ops->beneath, gdbarch);
}
-/* The to_find_new_threads method of target record-btrace. */
+/* The to_update_thread_list method of target record-btrace. */
static void
-record_btrace_find_new_threads (struct target_ops *ops)
+record_btrace_update_thread_list (struct target_ops *ops)
{
- /* Don't expect new threads if we're replaying. */
+ /* We don't add or remove threads during replay. */
if (record_btrace_is_replaying (ops))
return;
/* Forward the request. */
ops = ops->beneath;
- ops->to_find_new_threads (ops);
+ ops->to_update_thread_list (ops);
}
/* The to_thread_alive method of target record-btrace. */
@@ -1964,7 +1964,7 @@ init_record_btrace_ops (void)
ops->to_get_tailcall_unwinder = &record_btrace_to_get_tailcall_unwinder;
ops->to_resume = record_btrace_resume;
ops->to_wait = record_btrace_wait;
- ops->to_find_new_threads = record_btrace_find_new_threads;
+ ops->to_update_thread_list = record_btrace_update_thread_list;
ops->to_thread_alive = record_btrace_thread_alive;
ops->to_goto_record_begin = record_btrace_goto_begin;
ops->to_goto_record_end = record_btrace_goto_end;
diff --git a/gdb/remote.c b/gdb/remote.c
index e4776cc..74f57f8 100644
--- a/gdb/remote.c
+++ b/gdb/remote.c
@@ -2754,16 +2754,19 @@ remote_get_threads_with_qthreadinfo (struct target_ops *ops,
return 0;
}
-/* Implement the to_find_new_threads function for the remote
+/* Implement the to_update_thread_list function for the remote
targets. */
static void
-remote_threads_info (struct target_ops *ops)
+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 ();
+
context.items = NULL;
old_chain = make_cleanup (clear_threads_listing_context, &context);
@@ -2777,7 +2780,7 @@ remote_threads_info (struct target_ops *ops)
int i;
struct thread_item *item;
- /* Add threads we don't know about yet to our list. */
+ /* 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)
@@ -3425,7 +3428,7 @@ remote_start_remote (int from_tty, struct target_ops *target, int extended_p)
controlling. We default to adding them in the running state.
The '?' query below will then tell us about which threads are
stopped. */
- remote_threads_info (target);
+ remote_update_thread_list (target);
}
else if (packet_support (PACKET_QNonStop) == PACKET_ENABLE)
{
@@ -3477,7 +3480,7 @@ remote_start_remote (int from_tty, struct target_ops *target, int extended_p)
}
/* Fetch thread list. */
- target_find_new_threads ();
+ target_update_thread_list ();
/* Let the stub know that we want it to return the thread. */
set_continue_thread (minus_one_ptid);
@@ -4447,7 +4450,7 @@ extended_remote_attach_1 (struct target_ops *target, const char *args,
struct thread_info *thread;
/* Get list of threads. */
- remote_threads_info (target);
+ remote_update_thread_list (target);
thread = first_thread_of_process (pid);
if (thread)
@@ -11455,7 +11458,7 @@ Specify the serial device it is connected to\n\
remote_ops.to_pass_signals = remote_pass_signals;
remote_ops.to_program_signals = remote_program_signals;
remote_ops.to_thread_alive = remote_thread_alive;
- remote_ops.to_find_new_threads = remote_threads_info;
+ remote_ops.to_update_thread_list = remote_update_thread_list;
remote_ops.to_pid_to_str = remote_pid_to_str;
remote_ops.to_extra_thread_info = remote_threads_extra_info;
remote_ops.to_get_ada_task_ptid = remote_get_ada_task_ptid;
diff --git a/gdb/sol-thread.c b/gdb/sol-thread.c
index 88293c3..9993dff 100644
--- a/gdb/sol-thread.c
+++ b/gdb/sol-thread.c
@@ -624,7 +624,7 @@ check_for_thread_db (void)
if (ptid_get_pid (ptid) != -1)
inferior_ptid = ptid;
- target_find_new_threads ();
+ target_update_thread_list ();
break;
default:
@@ -1056,11 +1056,11 @@ solaris_pid_to_str (struct target_ops *ops, ptid_t ptid)
}
\f
-/* Worker bee for find_new_threads. Callback function that gets
+/* Worker bee for update_thread_list. Callback function that gets
called once per user-level thread (i.e. not for LWP's). */
static int
-sol_find_new_threads_callback (const td_thrhandle_t *th, void *ignored)
+sol_update_thread_list_callback (const td_thrhandle_t *th, void *ignored)
{
td_err_e retval;
td_thrinfo_t ti;
@@ -1078,15 +1078,18 @@ sol_find_new_threads_callback (const td_thrhandle_t *th, void *ignored)
}
static void
-sol_find_new_threads (struct target_ops *ops)
+sol_update_thread_list (struct target_ops *ops)
{
struct target_ops *beneath = find_target_beneath (ops);
- /* First Find any new LWP's. */
- beneath->to_find_new_threads (beneath);
+ /* Delete dead threads. */
+ prune_threads ();
+
+ /* Find any new LWP's. */
+ beneath->to_update_thread_list (beneath);
/* Then find any new user-level threads. */
- p_td_ta_thr_iter (main_ta, sol_find_new_threads_callback, (void *) 0,
+ p_td_ta_thr_iter (main_ta, sol_update_thread_list_callback, (void *) 0,
TD_THR_ANY_STATE, TD_THR_LOWEST_PRIORITY,
TD_SIGNO_MASK, TD_THR_ANY_USER_FLAGS);
}
@@ -1200,7 +1203,7 @@ sol_get_ada_task_ptid (struct target_ops *self, long lwp, long thread)
{
/* The list of threads is probably not up to date. Find any
thread that is missing from the list, and try again. */
- sol_find_new_threads (¤t_target);
+ sol_update_thread_list (¤t_target);
thread_info = iterate_over_threads (thread_db_find_thread_from_tid,
&thread);
}
@@ -1225,7 +1228,7 @@ init_sol_thread_ops (void)
sol_thread_ops.to_mourn_inferior = sol_thread_mourn_inferior;
sol_thread_ops.to_thread_alive = sol_thread_alive;
sol_thread_ops.to_pid_to_str = solaris_pid_to_str;
- sol_thread_ops.to_find_new_threads = sol_find_new_threads;
+ sol_thread_ops.to_update_thread_list = sol_update_thread_list;
sol_thread_ops.to_stratum = thread_stratum;
sol_thread_ops.to_get_ada_task_ptid = sol_get_ada_task_ptid;
sol_thread_ops.to_magic = OPS_MAGIC;
diff --git a/gdb/target-delegates.c b/gdb/target-delegates.c
index fe989ff..9beb5ff 100644
--- a/gdb/target-delegates.c
+++ b/gdb/target-delegates.c
@@ -1302,23 +1302,23 @@ debug_thread_alive (struct target_ops *self, ptid_t arg1)
}
static void
-delegate_find_new_threads (struct target_ops *self)
+delegate_update_thread_list (struct target_ops *self)
{
self = self->beneath;
- self->to_find_new_threads (self);
+ self->to_update_thread_list (self);
}
static void
-tdefault_find_new_threads (struct target_ops *self)
+tdefault_update_thread_list (struct target_ops *self)
{
}
static void
-debug_find_new_threads (struct target_ops *self)
+debug_update_thread_list (struct target_ops *self)
{
- fprintf_unfiltered (gdb_stdlog, "-> %s->to_find_new_threads (...)\n", debug_target.to_shortname);
- debug_target.to_find_new_threads (&debug_target);
- fprintf_unfiltered (gdb_stdlog, "<- %s->to_find_new_threads (", debug_target.to_shortname);
+ fprintf_unfiltered (gdb_stdlog, "-> %s->to_update_thread_list (...)\n", debug_target.to_shortname);
+ debug_target.to_update_thread_list (&debug_target);
+ fprintf_unfiltered (gdb_stdlog, "<- %s->to_update_thread_list (", debug_target.to_shortname);
target_debug_print_struct_target_ops_p (&debug_target);
fputs_unfiltered (")\n", gdb_stdlog);
}
@@ -3828,8 +3828,8 @@ install_delegators (struct target_ops *ops)
ops->to_program_signals = delegate_program_signals;
if (ops->to_thread_alive == NULL)
ops->to_thread_alive = delegate_thread_alive;
- if (ops->to_find_new_threads == NULL)
- ops->to_find_new_threads = delegate_find_new_threads;
+ if (ops->to_update_thread_list == NULL)
+ ops->to_update_thread_list = delegate_update_thread_list;
if (ops->to_pid_to_str == NULL)
ops->to_pid_to_str = delegate_pid_to_str;
if (ops->to_extra_thread_info == NULL)
@@ -4062,7 +4062,7 @@ install_dummy_methods (struct target_ops *ops)
ops->to_pass_signals = tdefault_pass_signals;
ops->to_program_signals = tdefault_program_signals;
ops->to_thread_alive = tdefault_thread_alive;
- ops->to_find_new_threads = tdefault_find_new_threads;
+ ops->to_update_thread_list = tdefault_update_thread_list;
ops->to_pid_to_str = default_pid_to_str;
ops->to_extra_thread_info = tdefault_extra_thread_info;
ops->to_thread_name = tdefault_thread_name;
@@ -4205,7 +4205,7 @@ init_debug_target (struct target_ops *ops)
ops->to_pass_signals = debug_pass_signals;
ops->to_program_signals = debug_program_signals;
ops->to_thread_alive = debug_thread_alive;
- ops->to_find_new_threads = debug_find_new_threads;
+ ops->to_update_thread_list = debug_update_thread_list;
ops->to_pid_to_str = debug_pid_to_str;
ops->to_extra_thread_info = debug_extra_thread_info;
ops->to_thread_name = debug_thread_name;
diff --git a/gdb/target.c b/gdb/target.c
index 4606d17..c4e697f 100644
--- a/gdb/target.c
+++ b/gdb/target.c
@@ -3049,9 +3049,9 @@ target_thread_alive (ptid_t ptid)
}
void
-target_find_new_threads (void)
+target_update_thread_list (void)
{
- current_target.to_find_new_threads (¤t_target);
+ current_target.to_update_thread_list (¤t_target);
}
void
diff --git a/gdb/target.h b/gdb/target.h
index a679228..f6175a0 100644
--- a/gdb/target.h
+++ b/gdb/target.h
@@ -563,7 +563,7 @@ struct target_ops
int (*to_thread_alive) (struct target_ops *, ptid_t ptid)
TARGET_DEFAULT_RETURN (0);
- void (*to_find_new_threads) (struct target_ops *)
+ void (*to_update_thread_list) (struct target_ops *)
TARGET_DEFAULT_IGNORE ();
char *(*to_pid_to_str) (struct target_ops *, ptid_t)
TARGET_DEFAULT_FUNC (default_pid_to_str);
@@ -1568,9 +1568,9 @@ extern void target_program_signals (int nsig, unsigned char *program_signals);
extern int target_thread_alive (ptid_t ptid);
-/* Query for new threads and add them to the thread list. */
+/* Sync the target's threads with GDB's thread list. */
-extern void target_find_new_threads (void);
+extern void target_update_thread_list (void);
/* Make target stop in a continuable fashion. (For instance, under
Unix, this should act like SIGSTOP). Note that this function is
diff --git a/gdb/thread.c b/gdb/thread.c
index ac1d8a1..f75fb80 100644
--- a/gdb/thread.c
+++ b/gdb/thread.c
@@ -69,7 +69,6 @@ static int thread_alive (struct thread_info *);
static void info_threads_command (char *, int);
static void thread_apply_command (char *, int);
static void restore_current_thread (ptid_t);
-static void prune_threads (void);
/* Data to cleanup thread array. */
@@ -583,7 +582,9 @@ thread_alive (struct thread_info *tp)
return 1;
}
-static void
+/* See gdbthreads.h. */
+
+void
prune_threads (void)
{
struct thread_info *tp, *next;
@@ -1547,8 +1548,7 @@ update_threads_executing (void)
void
update_thread_list (void)
{
- prune_threads ();
- target_find_new_threads ();
+ target_update_thread_list ();
update_threads_executing ();
}
--
1.9.3
^ permalink raw reply [flat|nested] 12+ messages in thread* Re: [PATCH 2/4] Push pruning old threads down to the target
2014-10-02 16:21 ` [PATCH 2/4] Push pruning old threads down to the target Pedro Alves
@ 2016-12-09 6:38 ` Thomas Schwinge
0 siblings, 0 replies; 12+ messages in thread
From: Thomas Schwinge @ 2016-12-09 6:38 UTC (permalink / raw)
To: Pedro Alves, gdb-patches; +Cc: bug-hurd
Hi!
On Thu, 2 Oct 2014 17:21:34 +0100, Pedro Alves <palves@redhat.com> wrote:
> When GDB wants to sync the thread list with the target's [...]
> --- a/gdb/thread.c
> +++ b/gdb/thread.c
> void
> update_thread_list (void)
> {
> - prune_threads ();
> - target_find_new_threads ();
> + target_update_thread_list ();
> update_threads_executing ();
> }
Pushed to master:
commit c752a4cccb99ba73f51eff74b394dcdcd26d4c59
Author: Thomas Schwinge <thomas@codesourcery.com>
Date: Wed May 25 18:54:40 2016 +0200
Hurd: Adjust to changes to "push pruning old threads down to the target"
For "info threads", we currently run into:
$ gdb/gdb -q -nw -nx --batch -ex start -ex info\ threads bfd/doc/chew
Temporary breakpoint 1 at 0x80486e0: file ../../../W._C._Handy/bfd/doc/chew.c, line 1535.
[New Thread 10656.5]
Thread 4 hit Temporary breakpoint 1, main (ac=1, av=0x102cd84) at ../../../W._C._Handy/bfd/doc/chew.c:1535
1535 {
Id Target Id Frame
1 bogus thread id 1 Can't fetch registers from thread bogus thread id 1: No such thread
Before commit e8032dde10b743253125d7defb5f5503b21c1d26,
gdb/thread.c:update_thread_list used to call prune_threads, after that change
it doesn't anymore, and we don't implement the to_update_thread_list target
method where the prune_threads call got moved. For now, apply a fix, related
to commit c82f56d9d760a9b4034eeaac44f2f0fa5779ff69 "Hurd: Adjust to
startup-with-shell changes", which restores the previous behavior:
Id Target Id Frame
* 4 Thread 10688.4 main (ac=1, av=0x102cd84) at ../../../W._C._Handy/bfd/doc/chew.c:1535
5 Thread 10688.5 0x0106096c in ?? () from /lib/i386-gnu/libc.so.0.3
Not perfect, but at least better.
gdb/
* gnu-nat.c (gnu_create_inferior): After startup_inferior, call
prune_threads.
---
gdb/ChangeLog | 3 +++
gdb/gnu-nat.c | 2 ++
2 files changed, 5 insertions(+)
diff --git gdb/ChangeLog gdb/ChangeLog
index 302eb6e..7fd5d32 100644
--- gdb/ChangeLog
+++ gdb/ChangeLog
@@ -1,5 +1,8 @@
2016-12-09 Thomas Schwinge <thomas@codesourcery.com>
+ * gnu-nat.c (gnu_create_inferior): After startup_inferior, call
+ prune_threads.
+
* inferior.c (print_selected_inferior): Avoid PATH_MAX usage.
2016-12-08 Simon Marchi <simon.marchi@ericsson.com>
diff --git gdb/gnu-nat.c gdb/gnu-nat.c
index 124574e..85a53b8 100644
--- gdb/gnu-nat.c
+++ gdb/gnu-nat.c
@@ -2163,6 +2163,8 @@ gnu_create_inferior (struct target_ops *ops,
startup_inferior (START_INFERIOR_TRAPS_EXPECTED);
inf->pending_execs = 0;
+ /* Get rid of the old shell threads. */
+ prune_threads ();
inf_validate_procinfo (inf);
inf_update_signal_thread (inf);
Grüße
Thomas
^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH 4/4] DEC threads: Simplify updating the thread list
2014-10-02 16:21 [PATCH 0/4] remote thread listing: get rid of unnecessary "thread alive?" traffic Pedro Alves
` (2 preceding siblings ...)
2014-10-02 16:21 ` [PATCH 2/4] Push pruning old threads down to the target Pedro Alves
@ 2014-10-02 16:21 ` Pedro Alves
2014-10-02 18:46 ` Mark Kettenis
2014-10-15 22:01 ` [pushed] Re: [PATCH 0/4] remote thread listing: get rid of unnecessary "thread alive?" traffic Pedro Alves
4 siblings, 1 reply; 12+ messages in thread
From: Pedro Alves @ 2014-10-02 16:21 UTC (permalink / raw)
To: gdb-patches
Seems to me that we can simplify DEC thread's
target_update_thread_list implementation, avoiding the need to build
the array of GDB threads.
I have no way to test this.
gdb/
2014-10-02 Pedro Alves <palves@redhat.com>
* dec-thread.c (dec_thread_count_gdb_threads)
(dec_thread_add_gdb_thread): Delete.
(dec_thread_update_thread_list): Delete.
(dec_thread_find_new_threads): Rename to ...
(dec_thread_update_thread_list): ... this. Delete GDB-size
threads that are no longer found in dec_thread_list.
(resync_thread_list): Delete.
(dec_thread_wait): Call dec_thread_update_thread_list instead of
resync_thread_list.
---
gdb/dec-thread.c | 93 +++++++++++++-------------------------------------------
1 file changed, 21 insertions(+), 72 deletions(-)
diff --git a/gdb/dec-thread.c b/gdb/dec-thread.c
index fc43153..d5cfad2 100644
--- a/gdb/dec-thread.c
+++ b/gdb/dec-thread.c
@@ -369,40 +369,33 @@ update_dec_thread_list (void)
pthreadDebugThdSeqDestroy (debug_context);
}
-/* A callback to count the number of threads known to GDB. */
-
-static int
-dec_thread_count_gdb_threads (struct thread_info *ignored, void *context)
-{
- int *count = (int *) context;
-
- *count = *count + 1;
- return 0;
-}
-
-/* A callback that saves the given thread INFO at the end of an
- array. The end of the array is given in the CONTEXT and is
- incremented once the info has been added. */
-
-static int
-dec_thread_add_gdb_thread (struct thread_info *info, void *context)
-{
- struct thread_info ***listp = (struct thread_info ***) context;
-
- **listp = info;
- *listp = *listp + 1;
- return 0;
-}
-
-/* Find new threads. */
+/* Implement the update_thread_list target_ops method. */
static void
-dec_thread_find_new_threads (struct target_ops *ops)
+dec_thread_update_thread_list (struct target_ops *ops)
{
int i;
struct dec_thread_info *info;
+ struct thread_info *tp, *tmp;
update_dec_thread_list ();
+
+ /* Delete GDB-side threads no longer found in dec_thread_list. */
+ ALL_NON_EXITED_THREADS_SAFE (tp, tmp)
+ {
+ for (i = 0; VEC_iterate (dec_thread_info_s, dec_thread_list, i, info); i++)
+ {
+ if (ptid_equal (info->ptid, tp->ptid))
+ break;
+ }
+ if (i == VEC_length (dec_thread_info_s, dec_thread_list))
+ {
+ /* Not found. */
+ delete_thread (tp->ptid);
+ }
+ }
+
+ /* And now add new threads. */
for (i = 0; VEC_iterate (dec_thread_info_s, dec_thread_list, i, info); i++)
{
ptid_t ptid = ptid_build_from_info (*info);
@@ -412,50 +405,6 @@ dec_thread_find_new_threads (struct target_ops *ops)
}
}
-/* Implement the update_thread_list target_ops method. */
-
-static void
-dec_thread_update_thread_list (struct target_ops *ops)
-{
- int i;
- struct dec_thread_info *info;
-
- /* Delete dead threads. */
- prune_threads ();
-
- /* Now find new threads. */
- dec_thread_find_new_threads (ops);
-}
-
-/* Resynchronize the list of threads known by GDB with the actual
- list of threads reported by libpthread_debug. */
-
-static void
-resync_thread_list (struct target_ops *ops)
-{
- int i;
- int num_gdb_threads = 0;
- struct thread_info **gdb_thread_list;
- struct thread_info **next_thread_info;
-
- /* Add new threads. */
- dec_thread_find_new_threads (ops);
-
- /* Remove threads that no longer exist. To help with the search,
- we build an array of GDB threads, and then iterate over this
- array. */
-
- iterate_over_threads (dec_thread_count_gdb_threads,
- (void *) &num_gdb_threads);
- gdb_thread_list = alloca (num_gdb_threads * sizeof (struct thread_info *));
- next_thread_info = gdb_thread_list;
- iterate_over_threads (dec_thread_add_gdb_thread, (void *) &next_thread_info);
-
- for (i = 0; i < num_gdb_threads; i++)
- if (!dec_thread_ptid_is_alive (gdb_thread_list[i]->ptid))
- delete_thread (gdb_thread_list[i]->ptid);
-}
-
/* The "to_detach" method of the dec_thread_ops. */
static void
@@ -502,7 +451,7 @@ dec_thread_wait (struct target_ops *ops,
/* The ptid returned by the target beneath us is the ptid of the process.
We need to find which thread is currently active and return its ptid. */
- resync_thread_list (ops);
+ dec_thread_update_thread_list (ops);
active_ptid = get_active_ptid ();
if (ptid_equal (active_ptid, null_ptid))
return ptid;
--
1.9.3
^ permalink raw reply [flat|nested] 12+ messages in thread* Re: [PATCH 4/4] DEC threads: Simplify updating the thread list
2014-10-02 16:21 ` [PATCH 4/4] DEC threads: Simplify updating the thread list Pedro Alves
@ 2014-10-02 18:46 ` Mark Kettenis
2014-10-03 9:12 ` Pedro Alves
0 siblings, 1 reply; 12+ messages in thread
From: Mark Kettenis @ 2014-10-02 18:46 UTC (permalink / raw)
To: palves; +Cc: gdb-patches
> From: Pedro Alves <palves@redhat.com>
> Date: Thu, 2 Oct 2014 17:21:36 +0100
>
> Seems to me that we can simplify DEC thread's
> target_update_thread_list implementation, avoiding the need to build
> the array of GDB threads.
>
> I have no way to test this.
Given that Alpha True64 support is about to be removed, I don't think
anyone will care.
> gdb/
> 2014-10-02 Pedro Alves <palves@redhat.com>
>
> * dec-thread.c (dec_thread_count_gdb_threads)
> (dec_thread_add_gdb_thread): Delete.
> (dec_thread_update_thread_list): Delete.
> (dec_thread_find_new_threads): Rename to ...
> (dec_thread_update_thread_list): ... this. Delete GDB-size
> threads that are no longer found in dec_thread_list.
> (resync_thread_list): Delete.
> (dec_thread_wait): Call dec_thread_update_thread_list instead of
> resync_thread_list.
> ---
> gdb/dec-thread.c | 93 +++++++++++++-------------------------------------------
> 1 file changed, 21 insertions(+), 72 deletions(-)
>
> diff --git a/gdb/dec-thread.c b/gdb/dec-thread.c
> index fc43153..d5cfad2 100644
> --- a/gdb/dec-thread.c
> +++ b/gdb/dec-thread.c
> @@ -369,40 +369,33 @@ update_dec_thread_list (void)
> pthreadDebugThdSeqDestroy (debug_context);
> }
>
> -/* A callback to count the number of threads known to GDB. */
> -
> -static int
> -dec_thread_count_gdb_threads (struct thread_info *ignored, void *context)
> -{
> - int *count = (int *) context;
> -
> - *count = *count + 1;
> - return 0;
> -}
> -
> -/* A callback that saves the given thread INFO at the end of an
> - array. The end of the array is given in the CONTEXT and is
> - incremented once the info has been added. */
> -
> -static int
> -dec_thread_add_gdb_thread (struct thread_info *info, void *context)
> -{
> - struct thread_info ***listp = (struct thread_info ***) context;
> -
> - **listp = info;
> - *listp = *listp + 1;
> - return 0;
> -}
> -
> -/* Find new threads. */
> +/* Implement the update_thread_list target_ops method. */
>
> static void
> -dec_thread_find_new_threads (struct target_ops *ops)
> +dec_thread_update_thread_list (struct target_ops *ops)
> {
> int i;
> struct dec_thread_info *info;
> + struct thread_info *tp, *tmp;
>
> update_dec_thread_list ();
> +
> + /* Delete GDB-side threads no longer found in dec_thread_list. */
> + ALL_NON_EXITED_THREADS_SAFE (tp, tmp)
> + {
> + for (i = 0; VEC_iterate (dec_thread_info_s, dec_thread_list, i, info); i++)
> + {
> + if (ptid_equal (info->ptid, tp->ptid))
> + break;
> + }
> + if (i == VEC_length (dec_thread_info_s, dec_thread_list))
> + {
> + /* Not found. */
> + delete_thread (tp->ptid);
> + }
> + }
> +
> + /* And now add new threads. */
> for (i = 0; VEC_iterate (dec_thread_info_s, dec_thread_list, i, info); i++)
> {
> ptid_t ptid = ptid_build_from_info (*info);
> @@ -412,50 +405,6 @@ dec_thread_find_new_threads (struct target_ops *ops)
> }
> }
>
> -/* Implement the update_thread_list target_ops method. */
> -
> -static void
> -dec_thread_update_thread_list (struct target_ops *ops)
> -{
> - int i;
> - struct dec_thread_info *info;
> -
> - /* Delete dead threads. */
> - prune_threads ();
> -
> - /* Now find new threads. */
> - dec_thread_find_new_threads (ops);
> -}
> -
> -/* Resynchronize the list of threads known by GDB with the actual
> - list of threads reported by libpthread_debug. */
> -
> -static void
> -resync_thread_list (struct target_ops *ops)
> -{
> - int i;
> - int num_gdb_threads = 0;
> - struct thread_info **gdb_thread_list;
> - struct thread_info **next_thread_info;
> -
> - /* Add new threads. */
> - dec_thread_find_new_threads (ops);
> -
> - /* Remove threads that no longer exist. To help with the search,
> - we build an array of GDB threads, and then iterate over this
> - array. */
> -
> - iterate_over_threads (dec_thread_count_gdb_threads,
> - (void *) &num_gdb_threads);
> - gdb_thread_list = alloca (num_gdb_threads * sizeof (struct thread_info *));
> - next_thread_info = gdb_thread_list;
> - iterate_over_threads (dec_thread_add_gdb_thread, (void *) &next_thread_info);
> -
> - for (i = 0; i < num_gdb_threads; i++)
> - if (!dec_thread_ptid_is_alive (gdb_thread_list[i]->ptid))
> - delete_thread (gdb_thread_list[i]->ptid);
> -}
> -
> /* The "to_detach" method of the dec_thread_ops. */
>
> static void
> @@ -502,7 +451,7 @@ dec_thread_wait (struct target_ops *ops,
>
> /* The ptid returned by the target beneath us is the ptid of the process.
> We need to find which thread is currently active and return its ptid. */
> - resync_thread_list (ops);
> + dec_thread_update_thread_list (ops);
> active_ptid = get_active_ptid ();
> if (ptid_equal (active_ptid, null_ptid))
> return ptid;
> --
> 1.9.3
>
>
^ permalink raw reply [flat|nested] 12+ messages in thread* Re: [PATCH 4/4] DEC threads: Simplify updating the thread list
2014-10-02 18:46 ` Mark Kettenis
@ 2014-10-03 9:12 ` Pedro Alves
0 siblings, 0 replies; 12+ messages in thread
From: Pedro Alves @ 2014-10-03 9:12 UTC (permalink / raw)
To: Mark Kettenis; +Cc: gdb-patches
On 10/02/2014 07:46 PM, Mark Kettenis wrote:
>> From: Pedro Alves <palves@redhat.com>
>> Date: Thu, 2 Oct 2014 17:21:36 +0100
>>
>> Seems to me that we can simplify DEC thread's
>> target_update_thread_list implementation, avoiding the need to build
>> the array of GDB threads.
>>
>> I have no way to test this.
>
> Given that Alpha True64 support is about to be removed, I don't think
> anyone will care.
Eh, I saw that dec-thread.o was pulled in by config/alpha/alpha-osf3.mh,
and then that is used when configuring for "alpha-osf" host, but somehow
failed to make the OSF->True64 connection. :-P
Thanks,
Pedro Alves
^ permalink raw reply [flat|nested] 12+ messages in thread
* [pushed] Re: [PATCH 0/4] remote thread listing: get rid of unnecessary "thread alive?" traffic
2014-10-02 16:21 [PATCH 0/4] remote thread listing: get rid of unnecessary "thread alive?" traffic Pedro Alves
` (3 preceding siblings ...)
2014-10-02 16:21 ` [PATCH 4/4] DEC threads: Simplify updating the thread list Pedro Alves
@ 2014-10-15 22:01 ` Pedro Alves
4 siblings, 0 replies; 12+ messages in thread
From: Pedro Alves @ 2014-10-15 22:01 UTC (permalink / raw)
To: gdb-patches
On 10/02/2014 05:21 PM, Pedro Alves wrote:
> When GDB wants to sync the thread list with the target's (e.g., due to
> "info threads"), it ends up sending a bunch of T (thread alive?)
> packets before fetching the current remote thread list:
>
> Sending packet: $Tp2141.2150#82...Packet received: OK
> Sending packet: $Tp2141.214f#b7...Packet received: OK
> Sending packet: $Tp2141.2141#82...Packet received: OK
> 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
>
> That's wasteful, given that we can tell whether a thread is gone from
> the fact that it won't appear in the list returned by
> qXfer:threads:read (or qfThreadInfo/qsThreadInfo, or qL).
>
> This series eliminates those unnecessary queries.
>
> IOW, after this series, the above becomes simply:
>
> 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
>
> Pedro Alves (4):
> Merge remote thread listing methods
> Push pruning old threads down to the target
> remote: get rid of all the T packets when synching the thread list
> DEC threads: Simplify updating the thread list
I've now pushed this.
Thanks,
Pedro Alves
^ permalink raw reply [flat|nested] 12+ messages in thread