This is the mail archive of the
gdb-patches@sourceware.org
mailing list for the GDB project.
Re: [PATCH 09/12] Make reinsert_breakpoint thread specific
- From: Yao Qi <qiyaoltc at gmail dot com>
- To: Pedro Alves <palves at redhat dot com>
- Cc: Yao Qi <qiyaoltc at gmail dot com>, gdb-patches at sourceware dot org
- Date: Tue, 14 Jun 2016 13:52:33 +0100
- Subject: Re: [PATCH 09/12] Make reinsert_breakpoint thread specific
- Authentication-results: sourceware.org; auth=none
- References: <1464859846-15619-1-git-send-email-yao dot qi at linaro dot org> <1464859846-15619-10-git-send-email-yao dot qi at linaro dot org> <71a5322e-41e3-9e23-df73-e14b14c1d656 at redhat dot com>
Pedro Alves <palves@redhat.com> writes:
>> - uninsert_reinsert_breakpoints ();
>> + uninsert_reinsert_breakpoints (ptid_of_lwp (event_lwp));
>> current_thread = saved_thread;
>
> Would it work to pass down the thread pointer directly?
>
> That would then allow pushing down the save current thread / restore
> current thread juggling to uninsert_reinsert_breakpoints too.
Yes, see the patch below,
--
Yao (éå)
From dd8c2dde049af0972d1da51506d990a97bf97193 Mon Sep 17 00:00:00 2001
From: Yao Qi <yao.qi@linaro.org>
Date: Thu, 19 May 2016 16:02:55 +0100
Subject: [PATCH] Make reinsert_breakpoint thread specific
V3: pass argument "thread" isntead of "ptid"
V2: rewrite commit log to make it easy to read,
"id" -> "ptid",
This patch makes reinsert_breakpoint thread specific, which means we
insert and remove reinsert_breakpoint breakpoints for a specific
thread. This motivation of this change is that I'll use
reinsert_breakpoint for vCont;s on software single step target, so that
GDBserver may insert one reinsert_breakpoint for one thread doing
step-over, and insert one reinsert_breakpoint for another thread doing
vCont;s. After the operation of one thread is finished, GDBserver must
remove reinsert_breakpoint for that thread only.
On the other hand, reinsert_breakpoint is used for step-over nowadays.
GDBserver inserts reinsert_breakpoint, and wait only from the thread
doing step-over. After the step-over is done, GDBserver removes the
reinsert_breakpoint. If there is still any threads need step-over, do
the same again until all threads are finished step-over. In other words,
reinsert_breakpoint is globally thread specific, but in an implicit way.
It is natural to make it explicitly thread specific.
gdb/gdbserver:
2016-06-14 Yao Qi <yao.qi@linaro.org>
* mem-break.c (struct reinsert_breakpoint) <ptid>: New field.
(set_reinsert_breakpoint): New parameter ptid. Callers updated.
(clone_one_breakpoint): Likewise.
(delete_reinsert_breakpoints): Change parameter to thread.
Callers updated.
(has_reinsert_breakpoints): Likewise.
(uninsert_reinsert_breakpoints): Likewise.
(reinsert_reinsert_breakpoints): Likewise.
* mem-break.h (set_reinsert_breakpoint): Update declaration.
(delete_reinsert_breakpoints): Likewise.
(reinsert_reinsert_breakpoints): Likewise.
(uninsert_reinsert_breakpoints): Likewise.
(has_reinsert_breakpoints): Likewise.
diff --git a/gdb/gdbserver/linux-low.c b/gdb/gdbserver/linux-low.c
index b0af178..60759c8 100644
--- a/gdb/gdbserver/linux-low.c
+++ b/gdb/gdbserver/linux-low.c
@@ -548,15 +548,11 @@ handle_extended_wait (struct lwp_info **orig_event_lwp, int wstat)
&& can_software_single_step ()
&& event == PTRACE_EVENT_VFORK)
{
- struct thread_info *saved_thread = current_thread;
-
- current_thread = event_thr;
/* If we leave reinsert breakpoints there, child will
hit it, so uninsert reinsert breakpoints from parent
(and child). Once vfork child is done, reinsert
them back to parent. */
- uninsert_reinsert_breakpoints ();
- current_thread = saved_thread;
+ uninsert_reinsert_breakpoints (event_thr);
}
clone_all_breakpoints (child_thr, event_thr);
@@ -591,17 +587,13 @@ handle_extended_wait (struct lwp_info **orig_event_lwp, int wstat)
if (event_lwp->bp_reinsert != 0
&& can_software_single_step ())
{
- struct thread_info *saved_thread = current_thread;
-
/* The child process is forked and stopped, so it is safe
to access its memory without stopping all other threads
from other processes. */
- current_thread = child_thr;
- delete_reinsert_breakpoints ();
- current_thread = saved_thread;
+ delete_reinsert_breakpoints (child_thr);
- gdb_assert (has_reinsert_breakpoints (parent_proc));
- gdb_assert (!has_reinsert_breakpoints (child_proc));
+ gdb_assert (has_reinsert_breakpoints (event_thr));
+ gdb_assert (!has_reinsert_breakpoints (child_thr));
}
/* Report the event. */
@@ -655,14 +647,9 @@ handle_extended_wait (struct lwp_info **orig_event_lwp, int wstat)
if (event_lwp->bp_reinsert != 0 && can_software_single_step ())
{
- struct thread_info *saved_thread = current_thread;
- struct process_info *proc = get_thread_process (event_thr);
+ reinsert_reinsert_breakpoints (event_thr);
- current_thread = event_thr;
- reinsert_reinsert_breakpoints ();
- current_thread = saved_thread;
-
- gdb_assert (has_reinsert_breakpoints (proc));
+ gdb_assert (has_reinsert_breakpoints (event_thr));
}
/* Report the event. */
@@ -2559,11 +2546,9 @@ maybe_hw_step (struct thread_info *thread)
return 1;
else
{
- struct process_info *proc = get_thread_process (thread);
-
/* GDBserver must insert reinsert breakpoint for software
single step. */
- gdb_assert (has_reinsert_breakpoints (proc));
+ gdb_assert (has_reinsert_breakpoints (thread));
return 0;
}
}
@@ -4153,7 +4138,7 @@ install_software_single_step_breakpoints (struct lwp_info *lwp)
next_pcs = (*the_low_target.get_next_pcs) (regcache);
for (i = 0; VEC_iterate (CORE_ADDR, next_pcs, i, pc); ++i)
- set_reinsert_breakpoint (pc);
+ set_reinsert_breakpoint (pc, current_ptid);
do_cleanups (old_chain);
}
@@ -4296,7 +4281,7 @@ linux_resume_one_lwp_throw (struct lwp_info *lwp,
{
/* If the thread isn't doing step-over, there shouldn't be any
reinsert breakpoints. */
- gdb_assert (!has_reinsert_breakpoints (proc));
+ gdb_assert (!has_reinsert_breakpoints (thread));
}
if (fast_tp_collecting == 1)
@@ -4789,8 +4774,8 @@ finish_step_over (struct lwp_info *lwp)
threads but LWP stopped while doing that. */
if (!can_hardware_single_step ())
{
- gdb_assert (has_reinsert_breakpoints (current_process ()));
- delete_reinsert_breakpoints ();
+ gdb_assert (has_reinsert_breakpoints (current_thread));
+ delete_reinsert_breakpoints (current_thread);
}
step_over_bkpt = null_ptid;
diff --git a/gdb/gdbserver/mem-break.c b/gdb/gdbserver/mem-break.c
index c14219e..65ca3f9 100644
--- a/gdb/gdbserver/mem-break.c
+++ b/gdb/gdbserver/mem-break.c
@@ -211,6 +211,9 @@ struct other_breakpoint
struct reinsert_breakpoint
{
struct breakpoint base;
+
+ /* Thread the reinsert breakpoint belongs to. */
+ ptid_t ptid;
};
/* Return the breakpoint size from its kind. */
@@ -1476,17 +1479,21 @@ gdb_breakpoint_here (CORE_ADDR where)
}
void
-set_reinsert_breakpoint (CORE_ADDR stop_at)
+set_reinsert_breakpoint (CORE_ADDR stop_at, ptid_t ptid)
{
- struct breakpoint *bp;
+ struct reinsert_breakpoint *bp;
+
+ gdb_assert (ptid_get_pid (current_ptid) == ptid_get_pid (ptid));
- bp = set_breakpoint_type_at (reinsert_breakpoint, stop_at, NULL);
+ bp = (struct reinsert_breakpoint *) set_breakpoint_type_at (reinsert_breakpoint,
+ stop_at, NULL);
+ bp->ptid = ptid;
}
void
-delete_reinsert_breakpoints (void)
+delete_reinsert_breakpoints (struct thread_info *thread)
{
- struct process_info *proc = current_process ();
+ struct process_info *proc = get_thread_process (thread);
struct breakpoint *bp, **bp_link;
bp = proc->breakpoints;
@@ -1494,11 +1501,17 @@ delete_reinsert_breakpoints (void)
while (bp)
{
- if (bp->type == reinsert_breakpoint)
+ if (bp->type == reinsert_breakpoint
+ && ptid_equal (((struct reinsert_breakpoint *) bp)->ptid,
+ ptid_of (thread)))
{
+ struct thread_info *saved_thread = current_thread;
+
+ current_thread = thread;
*bp_link = bp->next;
release_breakpoint (proc, bp);
bp = *bp_link;
+ current_thread = saved_thread;
}
else
{
@@ -1578,21 +1591,29 @@ uninsert_all_breakpoints (void)
}
void
-uninsert_reinsert_breakpoints (void)
+uninsert_reinsert_breakpoints (struct thread_info *thread)
{
- struct process_info *proc = current_process ();
+ struct process_info *proc = get_thread_process (thread);
struct breakpoint *bp;
for (bp = proc->breakpoints; bp != NULL; bp = bp->next)
{
- if (bp->type == reinsert_breakpoint)
+ if (bp->type == reinsert_breakpoint
+ && ptid_equal (((struct reinsert_breakpoint *) bp)->ptid,
+ ptid_of (thread)))
{
gdb_assert (bp->raw->inserted > 0);
/* Only uninsert the raw breakpoint if it only belongs to a
reinsert breakpoint. */
if (bp->raw->refcount == 1)
- uninsert_raw_breakpoint (bp->raw);
+ {
+ struct thread_info *saved_thread = current_thread;
+
+ current_thread = thread;
+ uninsert_raw_breakpoint (bp->raw);
+ current_thread = saved_thread;
+ }
}
}
}
@@ -1642,8 +1663,9 @@ reinsert_breakpoints_at (CORE_ADDR pc)
}
int
-has_reinsert_breakpoints (struct process_info *proc)
+has_reinsert_breakpoints (struct thread_info *thread)
{
+ struct process_info *proc = get_thread_process (thread);
struct breakpoint *bp, **bp_link;
bp = proc->breakpoints;
@@ -1651,7 +1673,9 @@ has_reinsert_breakpoints (struct process_info *proc)
while (bp)
{
- if (bp->type == reinsert_breakpoint)
+ if (bp->type == reinsert_breakpoint
+ && ptid_equal (((struct reinsert_breakpoint *) bp)->ptid,
+ ptid_of (thread)))
return 1;
else
{
@@ -1677,19 +1701,27 @@ reinsert_all_breakpoints (void)
}
void
-reinsert_reinsert_breakpoints (void)
+reinsert_reinsert_breakpoints (struct thread_info *thread)
{
- struct process_info *proc = current_process ();
+ struct process_info *proc = get_thread_process (thread);
struct breakpoint *bp;
for (bp = proc->breakpoints; bp != NULL; bp = bp->next)
{
- if (bp->type == reinsert_breakpoint)
+ if (bp->type == reinsert_breakpoint
+ && ptid_equal (((struct reinsert_breakpoint *) bp)->ptid,
+ ptid_of (thread)))
{
gdb_assert (bp->raw->inserted > 0);
if (bp->raw->refcount == 1)
- reinsert_raw_breakpoint (bp->raw);
+ {
+ struct thread_info *saved_thread = current_thread;
+
+ current_thread = thread;
+ reinsert_raw_breakpoint (bp->raw);
+ current_thread = saved_thread;
+ }
}
}
}
@@ -2113,7 +2145,7 @@ clone_agent_expr (const struct agent_expr *src_ax)
/* Deep-copy the contents of one breakpoint to another. */
static struct breakpoint *
-clone_one_breakpoint (const struct breakpoint *src)
+clone_one_breakpoint (const struct breakpoint *src, ptid_t ptid)
{
struct breakpoint *dest;
struct raw_breakpoint *dest_raw;
@@ -2174,6 +2206,9 @@ clone_one_breakpoint (const struct breakpoint *src)
= XCNEW (struct reinsert_breakpoint);
dest = (struct breakpoint *) reinsert_dest;
+ /* Since reinsert breakpoint is thread specific, don't copy
+ thread id from SRC, use ID instead. */
+ reinsert_dest->ptid = ptid;
}
else
gdb_assert_not_reached ("unhandled breakpoint type");
@@ -2201,7 +2236,7 @@ clone_all_breakpoints (struct thread_info *child_thread,
for (bp = parent_proc->breakpoints; bp != NULL; bp = bp->next)
{
- new_bkpt = clone_one_breakpoint (bp);
+ new_bkpt = clone_one_breakpoint (bp, ptid_of (child_thread));
APPEND_TO_LIST (new_list, new_bkpt, bkpt_tail);
APPEND_TO_LIST (new_raw_list, new_bkpt->raw, raw_bkpt_tail);
}
diff --git a/gdb/gdbserver/mem-break.h b/gdb/gdbserver/mem-break.h
index d633003..3322ec5 100644
--- a/gdb/gdbserver/mem-break.h
+++ b/gdb/gdbserver/mem-break.h
@@ -152,31 +152,32 @@ struct breakpoint *set_breakpoint_at (CORE_ADDR where,
int delete_breakpoint (struct breakpoint *bkpt);
-/* Set a reinsert breakpoint at STOP_AT. */
+/* Set a reinsert breakpoint at STOP_AT for thread represented by
+ PTID. */
-void set_reinsert_breakpoint (CORE_ADDR stop_at);
+void set_reinsert_breakpoint (CORE_ADDR stop_at, ptid_t ptid);
-/* Delete all reinsert breakpoints. */
+/* Delete all reinsert breakpoints of THREAD. */
-void delete_reinsert_breakpoints (void);
+void delete_reinsert_breakpoints (struct thread_info *thread);
-/* Reinsert all reinsert breakpoints of the current process. */
+/* Reinsert all reinsert breakpoints of THREAD. */
-void reinsert_reinsert_breakpoints (void);
+void reinsert_reinsert_breakpoints (struct thread_info *thread);
-/* Uninsert all reinsert breakpoints of the current process. This
- still leaves the reinsert breakpoints in the table. */
+/* Uninsert all reinsert breakpoints of THREAD. This still leaves
+ the reinsert breakpoints in the table. */
-void uninsert_reinsert_breakpoints (void);
+void uninsert_reinsert_breakpoints (struct thread_info *thread);
/* Reinsert breakpoints at WHERE (and change their status to
inserted). */
void reinsert_breakpoints_at (CORE_ADDR where);
-/* Process PROC has reinsert breakpoints or not. */
+/* The THREAD has reinsert breakpoints or not. */
-int has_reinsert_breakpoints (struct process_info *proc);
+int has_reinsert_breakpoints (struct thread_info *thread);
/* Uninsert breakpoints at WHERE (and change their status to
uninserted). This still leaves the breakpoints in the table. */