From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 5356 invoked by alias); 14 Sep 2005 22:04:55 -0000 Mailing-List: contact rda-help@sources.redhat.com; run by ezmlm Precedence: bulk List-Subscribe: List-Post: List-Help: , Sender: rda-owner@sources.redhat.com Received: (qmail 5321 invoked by uid 22791); 14 Sep 2005 22:04:46 -0000 Received: from mx1.redhat.com (HELO mx1.redhat.com) (66.187.233.31) by sourceware.org (qpsmtpd/0.30-dev) with ESMTP; Wed, 14 Sep 2005 22:04:46 +0000 Received: from int-mx1.corp.redhat.com (int-mx1.corp.redhat.com [172.16.52.254]) by mx1.redhat.com (8.12.11/8.12.11) with ESMTP id j8EM4jvD004020 for ; Wed, 14 Sep 2005 18:04:45 -0400 Received: from pobox.corp.redhat.com (pobox.corp.redhat.com [172.16.52.156]) by int-mx1.corp.redhat.com (8.11.6/8.11.6) with ESMTP id j8EM4jV26808 for ; Wed, 14 Sep 2005 18:04:45 -0400 Received: from localhost.localdomain (vpn50-50.rdu.redhat.com [172.16.50.50]) by pobox.corp.redhat.com (8.12.8/8.12.8) with ESMTP id j8EM4i8M014513 for ; Wed, 14 Sep 2005 18:04:45 -0400 Received: from ironwood.lan (ironwood.lan [192.168.64.8]) by localhost.localdomain (8.12.11/8.12.10) with ESMTP id j8EM4dCL025819 for ; Wed, 14 Sep 2005 15:04:39 -0700 Date: Wed, 14 Sep 2005 22:04:00 -0000 From: Kevin Buettner To: rda@sources.redhat.com Subject: [RFC] Improve performance of multi-threaded debugging Message-ID: <20050914150439.5a86df49@ironwood.lan> Organization: Red Hat X-Mailer: Sylpheed-Claws 0.9.12cvs173.1 (GTK+ 2.4.14; i386-redhat-linux-gnu) Mime-Version: 1.0 Content-Type: text/plain; charset=US-ASCII Content-Transfer-Encoding: 7bit X-SW-Source: 2005-q3/txt/msg00003.txt.bz2 As things stand now, the thread list is fetched each time rda checks the status of the program. This doesn't sound like such a burden until you realize that some decent sized data structures are read via the ptrace() interface. On slower machines, it can take a significant amount of time to single step or continue primarily due to this overhead. The patch below fetches the thread list only when it knows for certain that something has changed. The only fly in the ointment is that the signal based event model only knows about thread creation, but not about thread death. So it won't catch thread death until some new thread is created. I'm not sure what the implications of this are in practice. Comments? * thread-db.c (ALWAYS_UPDATE_THREAD_LIST): Define to be 0. (handle_thread_db_event): Update thread list upon receipt of TD_CREATE or TD_DEATH events. (thread_db_check_child_state): Potentially disable, depending upon value of ALWAYS_UPDATE_THREAD_LIST, the thread list update. (thread_db_check_child_state): Update thread list for signal based event model too. Index: thread-db.c =================================================================== RCS file: /cvs/cvsfiles/devo/rda/unix/thread-db.c,v retrieving revision 1.25.2.1 diff -u -p -r1.25.2.1 thread-db.c --- thread-db.c 3 Aug 2005 05:20:58 -0000 1.25.2.1 +++ thread-db.c 14 Sep 2005 21:31:48 -0000 @@ -48,6 +48,8 @@ int thread_db_noisy = 0; int proc_service_noisy = 0; +#define ALWAYS_UPDATE_THREAD_LIST 0 + /* * A tiny local symbol table. * @@ -1779,6 +1781,7 @@ handle_thread_db_event (struct child_pro struct gdbserv_thread *thread = process->event_thread; lwpid_t lwp; union wait w; + int do_update = 0; /* We need to be actually using the event interface. */ if (! using_thread_db_events) @@ -1812,13 +1815,16 @@ handle_thread_db_event (struct child_pro break; } - /* The only messages we're concerned with are TD_CREATE and - TD_DEATH. + if (msg.event == TD_CREATE || msg.event == TD_DEATH) + do_update = 1; + } - Every time thread_db_check_child_state gets a wait status - from waitpid, we call update_thread_list, so our list is - always up to date; we don't actually need to do anything with - these messages for our own sake. */ + if (do_update) + { +#if !ALWAYS_UPDATE_THREAD_LIST + /* Update the thread list. */ + update_thread_list (process); +#endif } /* Disable the event breakpoints while we step the thread across them. */ @@ -2122,9 +2128,11 @@ thread_db_check_child_state (struct chil process->stop_signal, (unsigned long) debug_get_pc (process->serv, process->pid)); +#if ALWAYS_UPDATE_THREAD_LIST /* Update the thread list, and attach to (and thereby stop) any new threads we find. */ update_thread_list (process); +#endif process->event_thread = thread_list_lookup_by_lid (process->pid); @@ -2170,6 +2178,12 @@ thread_db_check_child_state (struct chil process->stop_signal = restart_signal; else /* not main thread */ process->stop_signal = 0; + +#if !ALWAYS_UPDATE_THREAD_LIST + /* Update the thread list. */ + update_thread_list (process); +#endif + } process->signal_to_send = process->stop_signal; currentvec->continue_program (serv);