From: Tom Tromey <tromey@redhat.com>
To: "Ulrich Weigand" <uweigand@de.ibm.com>
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
Date: Fri, 04 Feb 2011 14:50:00 -0000 [thread overview]
Message-ID: <m3bp2rdfci.fsf@fleche.redhat.com> (raw)
In-Reply-To: <201102041349.p14DnCeY025641@d06av02.portsmouth.uk.ibm.com> (Ulrich Weigand's message of "Fri, 4 Feb 2011 14:49:12 +0100 (CET)")
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 <tromey@redhat.com>
* 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) <regcache>: 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);
}
next parent reply other threads:[~2011-02-04 14:50 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
[not found] <201102041349.p14DnCeY025641@d06av02.portsmouth.uk.ibm.com>
2011-02-04 14:50 ` Tom Tromey [this message]
2011-02-04 14:58 ` Ulrich Weigand
2011-02-04 15:01 ` Pedro Alves
[not found] <201102032140.p13Le89f031563@d06av02.portsmouth.uk.ibm.com>
[not found] ` <201102041455.20607.pedro@codesourcery.com>
[not found] ` <m34o8jddod.fsf@fleche.redhat.com>
2011-02-04 15:56 ` Pedro Alves
2011-02-04 15:58 ` Pedro Alves
[not found] ` <201102041555.52179.pedro__21913.9744448059$1296834976$gmane$org@codesourcery.com>
2011-02-04 17:02 ` Tom Tromey
2011-02-05 9:34 ` Markus Alber
2011-02-07 14:05 ` Markus Alber
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=m3bp2rdfci.fsf@fleche.redhat.com \
--to=tromey@redhat.com \
--cc=gdb-patches@sourceware.org \
--cc=markus@hyperion-imrt.org \
--cc=msnyder@vmware.com \
--cc=pedro@codesourcery.com \
--cc=uweigand@de.ibm.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox