Make reinsert_breakpoint thread specific
authorYao Qi <yao.qi@linaro.org>
Thu, 21 Jul 2016 11:12:18 +0000 (12:12 +0100)
committerYao Qi <yao.qi@linaro.org>
Thu, 21 Jul 2016 11:12:18 +0000 (12:12 +0100)
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-07-21  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.

gdb/gdbserver/ChangeLog
gdb/gdbserver/linux-low.c
gdb/gdbserver/mem-break.c
gdb/gdbserver/mem-break.h

index c440d6686f71c375ee4201e5280adf3c7d222522..b5e9c9630aec495adc605cff7c5e63960b459b3e 100644 (file)
@@ -1,3 +1,19 @@
+2016-07-21  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.
+
 2016-07-21  Yao Qi  <yao.qi@linaro.org>
 
        * inferiors.c (get_thread_process): Make parameter const.
index 39718c65502cbf641a59e67743ebe786e8ac262d..c0b2ac09cdbb1d4507a9fc66fc84ebfeadec1d69 100644 (file)
@@ -549,15 +549,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);
@@ -592,17 +588,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.  */
@@ -656,14 +648,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.  */
@@ -2632,11 +2619,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;
     }
 }
@@ -4224,7 +4209,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);
 }
@@ -4367,7 +4352,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)
@@ -4860,8 +4845,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;
index c14219e07952e0e8ee9b6501bcda195106ea95f3..65ca3f9d3e30442d092fa45382af3befaaf53f30 100644 (file)
@@ -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);
     }
index d6330035e7ab3ddc0ef74db9ca6c28336c85a448..3322ec569e452e14c66cbf06260af30c73657b19 100644 (file)
@@ -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.  */