From patchwork Thu Oct 2 16:21:35 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Pedro Alves X-Patchwork-Id: 3077 Received: (qmail 2452 invoked by alias); 2 Oct 2014 16:21:45 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Delivered-To: mailing list gdb-patches@sourceware.org Received: (qmail 2348 invoked by uid 89); 2 Oct 2014 16:21:44 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-2.5 required=5.0 tests=AWL, BAYES_00, RP_MATCHES_RCVD, SPF_HELO_PASS, SPF_PASS autolearn=ham version=3.3.2 X-HELO: mx1.redhat.com Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES256-GCM-SHA384 encrypted) ESMTPS; Thu, 02 Oct 2014 16:21:42 +0000 Received: from int-mx13.intmail.prod.int.phx2.redhat.com (int-mx13.intmail.prod.int.phx2.redhat.com [10.5.11.26]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id s92GLfmu023468 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=FAIL) for ; Thu, 2 Oct 2014 12:21:41 -0400 Received: from brno.lan (ovpn01.gateway.prod.ext.ams2.redhat.com [10.39.146.11]) by int-mx13.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id s92GLaVN026041 for ; Thu, 2 Oct 2014 12:21:40 -0400 From: Pedro Alves To: gdb-patches@sourceware.org Subject: [PATCH 3/4] remote: get rid of all the T packets when synching the thread list Date: Thu, 2 Oct 2014 17:21:35 +0100 Message-Id: <1412266896-28210-4-git-send-email-palves@redhat.com> In-Reply-To: <1412266896-28210-1-git-send-email-palves@redhat.com> References: <1412266896-28210-1-git-send-email-palves@redhat.com> 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\n\n\n\n\n Becomes: Sending packet: $qXfer:threads:read::0,fff#03...Packet received: l\n\n\n\n\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 * 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); }