From: Pedro Alves <pedro@codesourcery.com>
To: Jan Kratochvil <jan.kratochvil@redhat.com>
Cc: Tristan Gingold <gingold@adacore.com>, gdb-patches@sourceware.org
Subject: Re: [PATCH] PR threads/10729: x86 hw watchpoints and non-stop mode
Date: Mon, 12 Dec 2011 17:23:00 -0000 [thread overview]
Message-ID: <201112121656.44478.pedro@codesourcery.com> (raw)
In-Reply-To: <20111211233811.GA27629@host2.jankratochvil.net>
On Sunday 11 December 2011 23:38:11, Jan Kratochvil wrote:
> Hi Pedro,
>
> on simple non-hit (inferior does not touch "j" at all) watchpoint case:
> strace -o 2 -q ./gdb -nx ./36 -ex start -ex 'watch j' -ex stepi -ex 'set confirm no' -ex q
> grep 'PTRACE_....USER' 1 >1b; grep 'PTRACE_....USER' 2 >2b
>
> It has performance regression of 15 ptrace syscalls -> 27 ptrace syscalls.
Hmm. Before, a single step (si) (instead of all syscalls fro the
begining) does:
$ tail -f 1 | grep PTRACE_P...USER
ptrace(PTRACE_POKEUSER, 15618, offsetof(struct user, u_debugreg), 0x601028) = 0
ptrace(PTRACE_PEEKUSER, 15618, offsetof(struct user, u_debugreg) + 48, [0x4000]) = 0
ptrace(PTRACE_POKEUSER, 15618, offsetof(struct user, u_debugreg) + 48, 0x4000) = 0
ptrace(PTRACE_POKEUSER, 15618, offsetof(struct user, u_debugreg) + 56, 0xd0101) = 0
ptrace(PTRACE_PEEKUSER, 15618, offsetof(struct user, u_debugreg) + 48, [0x4000]) = 0
ptrace(PTRACE_POKEUSER, 15618, offsetof(struct user, u_debugreg), 0) = 0
ptrace(PTRACE_POKEUSER, 15618, offsetof(struct user, u_debugreg) + 56, 0xd0100) = 0
So, 7 related ptrace calls.
After the patch, just one single-step does:
$ tail -f 2 | grep PTRACE_P...USER
ptrace(PTRACE_POKEUSER, 16139, offsetof(struct user, u_debugreg), 0x601028) = 0
ptrace(PTRACE_POKEUSER, 16139, offsetof(struct user, u_debugreg) + 8, 0) = 0
ptrace(PTRACE_POKEUSER, 16139, offsetof(struct user, u_debugreg) + 16, 0) = 0
ptrace(PTRACE_POKEUSER, 16139, offsetof(struct user, u_debugreg) + 24, 0) = 0
ptrace(PTRACE_POKEUSER, 16139, offsetof(struct user, u_debugreg) + 56, 0xd0101) = 0
ptrace(PTRACE_PEEKUSER, 16139, offsetof(struct user, u_debugreg) + 48, [0x4000]) = 0
ptrace(PTRACE_PEEKUSER, 16139, offsetof(struct user, u_debugreg) + 56, [0xd0101]) = 0
Still 7 related ptrace syscalls.
The 15 -> 27 jump in all PTRACE_P...USER syscalls is because for all stops,
we're now reading both DR_STATUS and DR_CONTROL, while before
we were only reading DR_STATUS. And there are stops in starting up an inferior
until it reaches main. That looks easily fixed.
In addition, before, we'd only poke to DR[N] if the register was used,
now (i386|amd64)_linux_prepare_to_resume always writes all of DR0-3,
even when only one DR is used. That's looks easily fixed too.
I'm trying out this patch:
gdb/amd64-linux-nat.c | 3 ++-
gdb/i386-nat.c | 26 ++++++++++++++++++--------
2 files changed, 20 insertions(+), 9 deletions(-)
diff --git a/gdb/amd64-linux-nat.c b/gdb/amd64-linux-nat.c
index 9699f84..dc6a735 100644
--- a/gdb/amd64-linux-nat.c
+++ b/gdb/amd64-linux-nat.c
@@ -390,7 +390,8 @@ amd64_linux_prepare_to_resume (struct lwp_info *lwp)
struct i386_debug_reg_state *state = i386_debug_reg_state ();
for (i = DR_FIRSTADDR; i <= DR_LASTADDR; i++)
- amd64_linux_dr_set (lwp->ptid, i, state->dr_mirror[i]);
+ if (state->dr_ref_count[i] > 0)
+ amd64_linux_dr_set (lwp->ptid, i, state->dr_mirror[i]);
amd64_linux_dr_set (lwp->ptid, DR_CONTROL, state->dr_control_mirror);
diff --git a/gdb/i386-nat.c b/gdb/i386-nat.c
index 94306a1..6d59b14 100644
--- a/gdb/i386-nat.c
+++ b/gdb/i386-nat.c
@@ -607,22 +607,32 @@ i386_stopped_data_address (struct target_ops *ops, CORE_ADDR *addr_p)
int rc = 0;
unsigned status;
unsigned control;
+ unsigned control_p = 0;
/* Get the current values the inferior has. If the thread was
running when we last changed watchpoints, the mirror no longer
represents what was set in this thread's debug registers. */
status = i386_dr_low.get_status ();
- control = i386_dr_low.get_control ();
ALL_DEBUG_REGISTERS(i)
{
- if (I386_DR_WATCH_HIT (status, i)
- /* This second condition makes sure DRi is set up for a data
- watchpoint, not a hardware breakpoint. The reason is
- that GDB doesn't call the target_stopped_data_address
- method except for data watchpoints. In other words, I'm
- being paranoiac. */
- && I386_DR_GET_RW_LEN (control, i) != 0)
+ if (!I386_DR_WATCH_HIT (status, i))
+ continue;
+
+ /* Fetching DR_CONTROL may require another syscall. Avoid when
+ possible. */
+ if (!control_p)
+ {
+ control = i386_dr_low.get_control ();
+ control_p = 1;
+ }
+
+ /* This second condition makes sure DRi is set up for a data
+ watchpoint, not a hardware breakpoint. The reason is
+ that GDB doesn't call the target_stopped_data_address
+ method except for data watchpoints. In other words, I'm
+ being paranoiac. */
+ if (I386_DR_GET_RW_LEN (control, i) != 0)
{
addr = i386_dr_low.get_addr (i);
rc = 1;
With those changes, we're actually even better than before. Your
example when from 15 -> 12. A single stepi that doesn't trigger a
watchpoint only does:
ptrace(PTRACE_POKEUSER, 23332, offsetof(struct user, u_debugreg), 0x601028) = 0
ptrace(PTRACE_POKEUSER, 23332, offsetof(struct user, u_debugreg) + 56, 0xd0101) = 0
ptrace(PTRACE_PEEKUSER, 23332, offsetof(struct user, u_debugreg) + 48, [0x4000]) = 0
That is, write DR0 and DR_CONTROL on resume, and, read DR_STATUS on stop.
> On Fri, 09 Dec 2011 17:30:20 +0100, Pedro Alves wrote:
> > @@ -513,22 +499,7 @@ i386_update_inferior_debug_regs (struct i386_debug_reg_state *new_state)
> > ALL_DEBUG_REGISTERS (i)
> > {
> > if (I386_DR_VACANT (new_state, i) != I386_DR_VACANT (&dr_mirror, i))
> > - {
> > - if (!I386_DR_VACANT (new_state, i))
> > - {
> > - i386_dr_low.set_addr (i, new_state->dr_mirror[i]);
> > -
>
>
> > - /* Only a sanity check for leftover bits (set possibly only
> > - by inferior). */
> > - if (i386_dr_low.unset_status)
> > - i386_dr_low.unset_status (I386_DR_WATCH_MASK (i));
>
> Deleting this part is a regression. Testcase for that part is attached.
Thanks a lot, I'll take a look. I had assumed this bit:
if (lwp->stopped_by_watchpoint)
amd64_linux_dr_set (lwp->ptid, DR_STATUS, 0);
in amd64_linux_prepare_to_resume would fix the issue.
>
> > + && I386_DR_GET_RW_LEN (control, i) != 0)
> > {
> > - addr = state->dr_mirror[i];
> > + addr = i386_dr_low.get_addr (i);
>
> Why to do this change? Why we can no longer trust DR_MIRROR? This is
> a performance regression.
This is non-stop, so threads can be running while we change the
global state->dr_mirror (and friends). Say, we set a watchpoint,
and let the threads rusume. Now, say you delete the watchpoint, or
add/remove watchpoints such that state->dr_mirror[*] changes. Inserting/deleting
watchpoines updates state->dr_mirror[*]. Now threads haven't been updated
with the mirror yet, and say a thread has meanwhile hit an old watchpoint,
but we haven't handled the SIGTRAP yet. If we trusted state->dr_mirror[*],
we'd mistake the real trapped address to whatever was
currently state->dr_mirror[i]. So state->dr_mirror now represents
intention. To get at the address that trapped, we need to read the
state the thread had when it trapped. I'll add some comments to the code.
--
Pedro Alves
next prev parent reply other threads:[~2011-12-12 16:57 UTC|newest]
Thread overview: 37+ messages / expand[flat|nested] mbox.gz Atom feed top
2011-12-05 16:46 Pedro Alves
2011-12-05 17:06 ` Eli Zaretskii
2011-12-09 16:30 ` New tests to watch regions larger than a machine word (Re: [PATCH] PR threads/10729: x86 hw watchpoints and non-stop mode) Pedro Alves
2011-12-09 19:11 ` Eli Zaretskii
2011-12-13 16:12 ` Pedro Alves
2011-12-05 21:24 ` [PATCH] PR threads/10729: x86 hw watchpoints and non-stop mode Jan Kratochvil
2011-12-09 16:45 ` Pedro Alves
2011-12-09 16:47 ` Tristan Gingold
2011-12-09 19:23 ` Eli Zaretskii
2011-12-13 16:26 ` Pedro Alves
2011-12-11 23:39 ` Jan Kratochvil
2011-12-12 11:53 ` Pedro Alves
2011-12-12 14:49 ` Jan Kratochvil
2011-12-12 0:14 ` Jan Kratochvil
2011-12-12 17:23 ` Pedro Alves [this message]
2011-12-12 18:38 ` Jan Kratochvil
2011-12-12 20:14 ` Jan Kratochvil
2011-12-12 20:30 ` Pedro Alves
2011-12-13 17:24 ` Jan Kratochvil
2011-12-13 18:49 ` Pedro Alves
2011-12-13 19:25 ` Jan Kratochvil
2011-12-16 16:16 ` Pedro Alves
2012-01-20 19:51 ` testsuite: native/non-extended/extended modes [Re: [PATCH] PR threads/10729: x86 hw watchpoints and non-stop mode] Jan Kratochvil
2012-01-20 19:53 ` Pedro Alves
2012-01-20 19:57 ` Jan Kratochvil
2011-12-12 20:34 ` [PATCH] PR threads/10729: x86 hw watchpoints and non-stop mode Pedro Alves
2011-12-12 21:39 ` Jan Kratochvil
2011-12-13 16:21 ` Fix PR remote/13492 (Re: [PATCH] PR threads/10729: x86 hw watchpoints and non-stop mode) Pedro Alves
2011-12-13 17:23 ` Fix PR remote/13492 Jan Kratochvil
2011-12-13 16:33 ` [PATCH] PR threads/10729: x86 hw watchpoints and non-stop mode Pedro Alves
2011-12-13 18:57 ` Jan Kratochvil
2011-12-14 17:35 ` Pedro Alves
2011-12-14 17:42 ` Pedro Alves
2011-12-15 8:48 ` Regression for T (Stopped) processes [Re: [PATCH] PR threads/10729: x86 hw watchpoints and non-stop mode] Jan Kratochvil
2011-12-15 12:44 ` Pedro Alves
2011-12-15 15:33 ` Jan Kratochvil
2011-12-13 22:27 ` [PATCH] PR threads/10729: x86 hw watchpoints and non-stop mode Jan Kratochvil
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=201112121656.44478.pedro@codesourcery.com \
--to=pedro@codesourcery.com \
--cc=gdb-patches@sourceware.org \
--cc=gingold@adacore.com \
--cc=jan.kratochvil@redhat.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;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).