From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 11724 invoked by alias); 4 Feb 2011 14:50:21 -0000 Received: (qmail 11707 invoked by uid 22791); 4 Feb 2011 14:50:19 -0000 X-SWARE-Spam-Status: No, hits=-6.8 required=5.0 tests=AWL,BAYES_00,RCVD_IN_DNSWL_HI,SPF_HELO_PASS,TW_EG,T_RP_MATCHES_RCVD X-Spam-Check-By: sourceware.org Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Fri, 04 Feb 2011 14:50:12 +0000 Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id p14Enrq0013447 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 4 Feb 2011 09:49:53 -0500 Received: from ns3.rdu.redhat.com (ns3.rdu.redhat.com [10.11.255.199]) by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id p14Enq5E029640; Fri, 4 Feb 2011 09:49:52 -0500 Received: from opsy.redhat.com (ovpn01.gateway.prod.ext.phx2.redhat.com [10.5.9.1]) by ns3.rdu.redhat.com (8.13.8/8.13.8) with ESMTP id p14EnodX028504; Fri, 4 Feb 2011 09:49:51 -0500 Received: by opsy.redhat.com (Postfix, from userid 500) id 3508D3784E1; Fri, 4 Feb 2011 07:49:49 -0700 (MST) From: Tom Tromey To: "Ulrich Weigand" Cc: markus@hyperion-imrt.org (Markus Alber), msnyder@vmware.com (Michael Snyder), gdb-patches@sourceware.org, pedro@codesourcery.com Subject: Re: performance of multithreading gets gradually worse under gdb References: <201102041349.p14DnCeY025641@d06av02.portsmouth.uk.ibm.com> Date: Fri, 04 Feb 2011 14:50:00 -0000 In-Reply-To: <201102041349.p14DnCeY025641@d06av02.portsmouth.uk.ibm.com> (Ulrich Weigand's message of "Fri, 4 Feb 2011 14:49:12 +0100 (CET)") Message-ID: User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/23.2 (gnu/linux) MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org X-SW-Source: 2011-02/txt/msg00058.txt.bz2 Moving to gdb-patches. Ulrich> Yes, I think so. Note that we still need to (potentially) keep Ulrich> more than one regcache per thread for multi-arch support. We Ulrich> may also need to reset the regcache's address space before Ulrich> reusing it ... In that case it seemed simpler to free the caches. Here is what I am testing. Let me know what you think. Tom 2011-02-04 Tom Tromey * thread.c (free_thread): Call free_thread_regcache. * regcache.h (free_thread_regcache): Declare. * regcache.c (current_regcache): Remove. (get_thread_arch_regcache): Use thread's regcache. (free_thread_regcache): New function. (regcache_thread_ptid_changed): Use thread's regcache. (invalidate_registers_maybe): New function. (registers_changed_ptid): Use iterate_over_threads and invalidate_registers_maybe. * gdbthread.h (struct thread_info) : New field. diff --git a/gdb/gdbthread.h b/gdb/gdbthread.h index ddb7b0f..cfe1bea 100644 --- a/gdb/gdbthread.h +++ b/gdb/gdbthread.h @@ -23,6 +23,7 @@ #define GDBTHREAD_H struct symtab; +struct regcache_list; #include "breakpoint.h" #include "frame.h" @@ -224,6 +225,10 @@ struct thread_info /* Function that is called to free PRIVATE. If this is NULL, then xfree will be called on PRIVATE. */ void (*private_dtor) (struct private_thread_info *); + + /* The register caches associated with this thread. Note that this + type is opaque; it is entirely managed by the regcache code. */ + struct regcache_list *regcache; }; /* Create an empty thread list, or empty the existing one. */ diff --git a/gdb/regcache.c b/gdb/regcache.c index 53e0c59..55f39fe 100644 --- a/gdb/regcache.c +++ b/gdb/regcache.c @@ -29,6 +29,7 @@ #include "gdb_string.h" #include "gdbcmd.h" /* For maintenanceprintlist. */ #include "observer.h" +#include "gdbthread.h" /* * DATA STRUCTURE @@ -433,9 +434,6 @@ regcache_invalidate (struct regcache *regcache, int regnum) regcache->register_status[regnum] = REG_UNKNOWN; } - -/* Global structure containing the current regcache. */ - /* NOTE: this is a write-through cache. There is no "dirty" bit for recording if the register values have been changed (eg. by the user). Therefore all registers must be written back to the @@ -447,17 +445,15 @@ struct regcache_list struct regcache_list *next; }; -static struct regcache_list *current_regcache; - struct regcache * get_thread_arch_regcache (ptid_t ptid, struct gdbarch *gdbarch) { struct regcache_list *list; struct regcache *new_regcache; + struct thread_info *tp = find_thread_ptid (ptid); - for (list = current_regcache; list; list = list->next) - if (ptid_equal (list->regcache->ptid, ptid) - && get_regcache_arch (list->regcache) == gdbarch) + for (list = tp->regcache; list; list = list->next) + if (get_regcache_arch (list->regcache) == gdbarch) return list->regcache; new_regcache = regcache_xmalloc_1 (gdbarch, @@ -467,8 +463,8 @@ get_thread_arch_regcache (ptid_t ptid, struct gdbarch *gdbarch) list = xmalloc (sizeof (struct regcache_list)); list->regcache = new_regcache; - list->next = current_regcache; - current_regcache = list; + list->next = tp->regcache; + tp->regcache = list; return new_regcache; } @@ -494,6 +490,21 @@ get_current_regcache (void) return get_thread_regcache (inferior_ptid); } +void +free_thread_regcache (struct thread_info *tp) +{ + struct regcache_list *iter, *next; + + for (iter = tp->regcache; iter; iter = next) + { + next = iter->next; + regcache_xfree (iter->regcache); + xfree (iter); + } + + tp->regcache = NULL; +} + /* Observer for the target_changed event. */ @@ -508,11 +519,14 @@ regcache_observer_target_changed (struct target_ops *target) static void regcache_thread_ptid_changed (ptid_t old_ptid, ptid_t new_ptid) { + struct thread_info *tp = find_thread_ptid (new_ptid); struct regcache_list *list; - for (list = current_regcache; list; list = list->next) - if (ptid_equal (list->regcache->ptid, old_ptid)) + for (list = tp->regcache; list; list = list->next) + { + gdb_assert (ptid_equal (list->regcache->ptid, old_ptid)); list->regcache->ptid = new_ptid; + } } /* Low level examining and depositing of registers. @@ -522,6 +536,21 @@ regcache_thread_ptid_changed (ptid_t old_ptid, ptid_t new_ptid) garbage. (a change from GDB version 3, in which the caller got the value from the last stop). */ +/* Helper for registers_changed_ptid. This is used as a callback to + iterate_over_threads. */ + +static int +invalidate_registers_maybe (struct thread_info *tp, void *data) +{ + ptid_t *filter = data; + + if (ptid_match (tp->ptid, *filter)) + free_thread_regcache (tp); + + /* Keep going. */ + return 0; +} + /* REGISTERS_CHANGED () Indicate that registers may have changed, so invalidate the cache. */ @@ -529,28 +558,7 @@ regcache_thread_ptid_changed (ptid_t old_ptid, ptid_t new_ptid) void registers_changed_ptid (ptid_t ptid) { - struct regcache_list *list, **list_link; - - list = current_regcache; - list_link = ¤t_regcache; - while (list) - { - if (ptid_match (list->regcache->ptid, ptid)) - { - struct regcache_list *dead = list; - - *list_link = list->next; - regcache_xfree (list->regcache); - list = *list_link; - xfree (dead); - continue; - } - - list_link = &list->next; - list = *list_link; - } - - current_regcache = NULL; + iterate_over_threads (invalidate_registers_maybe, &ptid); current_thread_ptid = null_ptid; current_thread_arch = NULL; diff --git a/gdb/regcache.h b/gdb/regcache.h index 7ae585a..be71f90 100644 --- a/gdb/regcache.h +++ b/gdb/regcache.h @@ -180,4 +180,8 @@ extern void regcache_cpy_no_passthrough (struct regcache *dest, extern void registers_changed (void); extern void registers_changed_ptid (ptid_t); +/* Free the regcaches associated with the thread TP. */ + +extern void free_thread_regcache (struct thread_info *tp); + #endif /* REGCACHE_H */ diff --git a/gdb/thread.c b/gdb/thread.c index 62455c2..6717dd4 100644 --- a/gdb/thread.c +++ b/gdb/thread.c @@ -141,6 +141,8 @@ free_thread (struct thread_info *tp) xfree (tp->private); } + free_thread_regcache (tp); + xfree (tp->name); xfree (tp); }