[7/8,gdbserver] linux-low.c: better starvation avoidance, handle non-stop mode too

Message ID 1419625871-28848-8-git-send-email-palves@redhat.com
State New, archived
Headers

Commit Message

Pedro Alves Dec. 26, 2014, 8:31 p.m. UTC
  This patch applies the same starvation avoidance improvements of the
previous patch to the Linux gdbserver side.

Without this, the test added by the following commit
(gdb.threads/non-stop-fair-events.exp) always fails with time outs.

gdb/gdbserver/
2014-12-26  Pedro Alves  <palves@redhat.com>

	* linux-low.c (step_over_bkpt): Move higher up in the file.
	(handle_extended_wait): Don't store the stop_pc here.
	(get_stop_pc): Adjust comments and rename to ...
        (check_stopped_by_breakpoint): ... this.  Record whether the LWP
        stopped for a software breakpoint or hardware breakpoint.
	(thread_still_has_status_pending_p): New function.
	(status_pending_p_callback): Use
	thread_still_has_status_pending_p.  If the event is no longer
	interesting, resume the LWP.
	(handle_tracepoints): Add assert.
	(maybe_move_out_of_jump_pad): Remove cancel_breakpoints call.
	(wstatus_maybe_breakpoint): New function.
	(cancel_breakpoint): Delete function.
	(check_stopped_by_watchpoint): New function, factored out from
	linux_low_filter_event.
	(lp_status_maybe_breakpoint): Delete function.
	(linux_low_filter_event): Remove filter_ptid argument.
	Leave thread group exits pending here.  Store the LWP's stop PC.
	Always leave events pending.
	(linux_wait_for_event_filtered): Pull all events out of the
	kernel, and leave them all pending.
	(count_events_callback, select_event_lwp_callback): Consider all
	events.
	(cancel_breakpoints_callback, linux_cancel_breakpoints): Delete.
        (select_event_lwp): Only give preference to the stepping LWP in
        all-stop mode.  Adjust comments.
	(ignore_event): New function.
	(linux_wait_1): Delete 'retry' label.  Use ignore_event.  Remove
	references to cancel_breakpoints.  Adjust to renames.  Also give
	equal priority to all LWPs that have had events in non-stop mode.
	If reporting a software breakpoint event, unadjust the LWP's PC.
	(linux_wait): If linux_wait_1 returned an ignored event, retry.
	(stuck_in_jump_pad_callback, move_out_of_jump_pad_callback):
	Adjust.
	(linux_resume_one_lwp): Store the LWP's PC.  Adjust.
	(resume_status_pending_p): Use thread_still_has_status_pending_p.
	(linux_stopped_by_watchpoint): Adjust.
	(linux_target_ops): Remove reference to linux_cancel_breakpoints.
	* linux-low.h (enum lwp_stop_reason): New.
	(struct lwp_info) <stop_pc>: Adjust comment.
	<stopped_by_watchpoint>: Delete field.
        <stop_reason>: New field.
	* linux-x86-low.c (x86_linux_prepare_to_resume): Adjust.
	* mem-break.c (software_breakpoint_inserted_here)
	(hardware_breakpoint_inserted_here): New function.
	* mem-break.h (software_breakpoint_inserted_here)
	(hardware_breakpoint_inserted_here): Declare.
	* target.h (struct target_ops) <cancel_breakpoints>: Remove field.
	(cancel_breakpoints): Delete.
	* tracepoint.c (clear_installed_tracepoints, stop_tracing)
	(upload_fast_traceframes): Remove references to
	cancel_breakpoints.
---
 gdb/gdbserver/linux-low.c     | 707 +++++++++++++++++++++++-------------------
 gdb/gdbserver/linux-low.h     |  29 +-
 gdb/gdbserver/linux-x86-low.c |   2 +-
 gdb/gdbserver/mem-break.c     |  34 ++
 gdb/gdbserver/mem-break.h     |  10 +
 gdb/gdbserver/target.h        |  10 -
 gdb/gdbserver/tracepoint.c    |   5 -
 7 files changed, 451 insertions(+), 346 deletions(-)
  

Patch

diff --git a/gdb/gdbserver/linux-low.c b/gdb/gdbserver/linux-low.c
index 65f72a2..609f534 100644
--- a/gdb/gdbserver/linux-low.c
+++ b/gdb/gdbserver/linux-low.c
@@ -218,9 +218,12 @@  static int linux_stopped_by_watchpoint (void);
 static void mark_lwp_dead (struct lwp_info *lwp, int wstat);
 static void proceed_all_lwps (void);
 static int finish_step_over (struct lwp_info *lwp);
-static CORE_ADDR get_stop_pc (struct lwp_info *lwp);
 static int kill_lwp (unsigned long lwpid, int signo);
 
+/* When the event-loop is doing a step-over, this points at the thread
+   being stepped.  */
+ptid_t step_over_bkpt;
+
 /* True if the low target can hardware single-step.  Such targets
    don't need a BREAKPOINT_REINSERT_ADDR callback.  */
 
@@ -363,6 +366,8 @@  linux_add_process (int pid, int attached)
   return proc;
 }
 
+static CORE_ADDR get_pc (struct lwp_info *lwp);
+
 /* Handle a GNU/Linux extended wait response.  If we see a clone
    event, we need to add the new LWP to our list (and not report the
    trap to higher layers).  */
@@ -423,9 +428,7 @@  handle_extended_wait (struct lwp_info *event_child, int wstat)
 	 If we do get another signal, be sure not to lose it.  */
       if (WSTOPSIG (status) == SIGSTOP)
 	{
-	  if (stopping_threads != NOT_STOPPING_THREADS)
-	    new_lwp->stop_pc = get_stop_pc (new_lwp);
-	  else
+	  if (stopping_threads == NOT_STOPPING_THREADS)
 	    linux_resume_one_lwp (new_lwp, 0, 0, NULL);
 	}
       else
@@ -434,7 +437,6 @@  handle_extended_wait (struct lwp_info *event_child, int wstat)
 
 	  if (stopping_threads != NOT_STOPPING_THREADS)
 	    {
-	      new_lwp->stop_pc = get_stop_pc (new_lwp);
 	      new_lwp->status_pending_p = 1;
 	      new_lwp->status_pending = status;
 	    }
@@ -481,44 +483,96 @@  get_pc (struct lwp_info *lwp)
    The SIGTRAP could mean several things.
 
    On i386, where decr_pc_after_break is non-zero:
-   If we were single-stepping this process using PTRACE_SINGLESTEP,
-   we will get only the one SIGTRAP (even if the instruction we
-   stepped over was a breakpoint).  The value of $eip will be the
-   next instruction.
+
+   If we were single-stepping this process using PTRACE_SINGLESTEP, we
+   will get only the one SIGTRAP.  The value of $eip will be the next
+   instruction.  If the instruction we stepped over was a breakpoint,
+   we need to decrement the PC.
+
    If we continue the process using PTRACE_CONT, we will get a
    SIGTRAP when we hit a breakpoint.  The value of $eip will be
    the instruction after the breakpoint (i.e. needs to be
    decremented).  If we report the SIGTRAP to GDB, we must also
-   report the undecremented PC.  If we cancel the SIGTRAP, we
+   report the undecremented PC.  If the breakpoint is removed, we
    must resume at the decremented PC.
 
-   (Presumably, not yet tested) On a non-decr_pc_after_break machine
-   with hardware or kernel single-step:
-   If we single-step over a breakpoint instruction, our PC will
-   point at the following instruction.  If we continue and hit a
-   breakpoint instruction, our PC will point at the breakpoint
+   On a non-decr_pc_after_break machine with hardware or kernel
+   single-step:
+
+   If we either single-step a breakpoint instruction, or continue and
+   hit a breakpoint instruction, our PC will point at the breakpoint
    instruction.  */
 
-static CORE_ADDR
-get_stop_pc (struct lwp_info *lwp)
+static int
+check_stopped_by_breakpoint (struct lwp_info *lwp)
 {
-  CORE_ADDR stop_pc;
+  CORE_ADDR pc;
+  CORE_ADDR sw_breakpoint_pc;
+  struct thread_info *saved_thread;
 
   if (the_low_target.get_pc == NULL)
     return 0;
 
-  stop_pc = get_pc (lwp);
+  pc = get_pc (lwp);
+  sw_breakpoint_pc = pc - the_low_target.decr_pc_after_break;
 
-  if (WSTOPSIG (lwp->last_status) == SIGTRAP
-      && !lwp->stepping
-      && !lwp->stopped_by_watchpoint
-      && !linux_is_extended_waitstatus (lwp->last_status))
-    stop_pc -= the_low_target.decr_pc_after_break;
+  /* breakpoint_at reads from the current thread.  */
+  saved_thread = current_thread;
+  current_thread = get_lwp_thread (lwp);
 
-  if (debug_threads)
-    debug_printf ("stop pc is 0x%lx\n", (long) stop_pc);
+  /* We may have just stepped a breakpoint instruction.  E.g., in
+     non-stop mode, GDB first tells the thread A to step a range, and
+     then the user inserts a breakpoint inside the range.  In that
+     case, we need to report the breakpoint PC.  But, when we're
+     trying to step past one of our own breakpoints, that happens to
+     have been placed on top of a permanent breakpoint instruction, we
+     shouldn't adjust the PC, otherwise the program would keep
+     trapping the permanent breakpoint forever.  */
+  if ((!lwp->stepping
+       || (!ptid_equal (ptid_of (current_thread), step_over_bkpt)
+	   && lwp->stop_pc == sw_breakpoint_pc))
+      && (*the_low_target.breakpoint_at) (sw_breakpoint_pc))
+    {
+      if (debug_threads)
+	{
+	  struct thread_info *thr = get_lwp_thread (lwp);
+
+	  debug_printf ("CSBB: %s stopped by software breakpoint\n",
+			target_pid_to_str (ptid_of (thr)));
+	}
+
+      /* Back up the PC if necessary.  */
+      if (pc != sw_breakpoint_pc)
+        {
+	  struct regcache *regcache
+	    = get_thread_regcache (current_thread, 1);
+	  (*the_low_target.set_pc) (regcache, sw_breakpoint_pc);
+	}
+
+      lwp->stop_pc = sw_breakpoint_pc;
+      lwp->stop_reason = LWP_STOPPED_BY_SW_BREAKPOINT;
+      current_thread = saved_thread;
+      return 1;
+    }
+
+  if (hardware_breakpoint_inserted_here (pc))
+    {
+      if (debug_threads)
+	{
+	  struct thread_info *thr = get_lwp_thread (lwp);
+
+	  debug_printf ("CSBB: %s stopped by hardware breakpoint\n",
+			target_pid_to_str (ptid_of (thr)));
+	}
 
-  return stop_pc;
+      lwp->stop_pc = pc;
+      lwp->stop_reason = LWP_STOPPED_BY_HW_BREAKPOINT;
+      current_thread = saved_thread;
+      return 1;
+    }
+
+  current_thread = saved_thread;
+  return 0;
 }
 
 static struct lwp_info *
@@ -1235,12 +1289,83 @@  linux_thread_alive (ptid_t ptid)
     return 0;
 }
 
+/* Return 1 if this lwp still has an interesting status pending.  If
+   not (e.g., it had stopped for a breakpoint that is gone), return
+   false.  */
+
+static int
+thread_still_has_status_pending_p (struct thread_info *thread)
+{
+  struct lwp_info *lp = get_thread_lwp (thread);
+
+  if (!lp->status_pending_p)
+    return 0;
+
+  /* If we got a `vCont;t', but we haven't reported a stop yet, do
+     report any status pending the LWP may have.  */
+  if (thread->last_resume_kind == resume_stop
+      && thread->last_status.kind != TARGET_WAITKIND_IGNORE)
+    return 0;
+
+  if (thread->last_resume_kind != resume_stop
+      && (lp->stop_reason == LWP_STOPPED_BY_SW_BREAKPOINT
+	  || lp->stop_reason == LWP_STOPPED_BY_HW_BREAKPOINT))
+    {
+      struct thread_info *saved_thread;
+      CORE_ADDR pc;
+      int discard = 0;
+
+      gdb_assert (lp->last_status != 0);
+
+      pc = get_pc (lp);
+
+      saved_thread = current_thread;
+      current_thread = thread;
+
+      if (pc != lp->stop_pc)
+	{
+	  if (debug_threads)
+	    debug_printf ("PC of %ld changed\n",
+			  lwpid_of (thread));
+	  discard = 1;
+	}
+      else if (lp->stop_reason == LWP_STOPPED_BY_SW_BREAKPOINT
+	       && !(*the_low_target.breakpoint_at) (pc))
+	{
+	  if (debug_threads)
+	    debug_printf ("previous SW breakpoint of %ld gone\n",
+			  lwpid_of (thread));
+	  discard = 1;
+	}
+      else if (lp->stop_reason == LWP_STOPPED_BY_HW_BREAKPOINT
+	       && !hardware_breakpoint_inserted_here (pc))
+	{
+	  if (debug_threads)
+	    debug_printf ("previous HW breakpoint of %ld gone\n",
+			  lwpid_of (thread));
+	  discard = 1;
+	}
+
+      current_thread = saved_thread;
+
+      if (discard)
+	{
+	  if (debug_threads)
+	    debug_printf ("discarding pending breakpoint status\n");
+	  lp->status_pending_p = 0;
+	  return 0;
+	}
+    }
+
+  return 1;
+}
+
 /* Return 1 if this lwp has an interesting status pending.  */
 static int
 status_pending_p_callback (struct inferior_list_entry *entry, void *arg)
 {
   struct thread_info *thread = (struct thread_info *) entry;
-  struct lwp_info *lwp = get_thread_lwp (thread);
+  struct lwp_info *lp = get_thread_lwp (thread);
   ptid_t ptid = * (ptid_t *) arg;
 
   /* Check if we're only interested in events from a specific process
@@ -1249,13 +1374,14 @@  status_pending_p_callback (struct inferior_list_entry *entry, void *arg)
       && ptid_get_pid (ptid) != ptid_get_pid (thread->entry.id))
     return 0;
 
-  /* If we got a `vCont;t', but we haven't reported a stop yet, do
-     report any status pending the LWP may have.  */
-  if (thread->last_resume_kind == resume_stop
-      && thread->last_status.kind != TARGET_WAITKIND_IGNORE)
-    return 0;
+  if (lp->status_pending_p
+      && !thread_still_has_status_pending_p (thread))
+    {
+      linux_resume_one_lwp (lp, lp->stepping, GDB_SIGNAL_0, NULL);
+      return 0;
+    }
 
-  return lwp->status_pending_p;
+  return lp->status_pending_p;
 }
 
 static int
@@ -1401,6 +1527,8 @@  handle_tracepoints (struct lwp_info *lwp)
   struct thread_info *tinfo = get_lwp_thread (lwp);
   int tpoint_related_event = 0;
 
+  gdb_assert (lwp->suspended == 0);
+
   /* If this tracepoint hit causes a tracing stop, we'll immediately
      uninsert tracepoints.  To do this, we temporarily pause all
      threads, unpatch away, and then unpause threads.  We need to make
@@ -1566,7 +1694,6 @@  maybe_move_out_of_jump_pad (struct lwp_info *lwp, int *wstat)
 			      "stopping all threads momentarily.\n");
 
 	      stop_all_lwps (1, lwp);
-	      cancel_breakpoints ();
 
 	      delete_breakpoint (lwp->exit_jump_pad_bkpt);
 	      lwp->exit_jump_pad_bkpt = NULL;
@@ -1692,65 +1819,59 @@  dequeue_one_deferred_signal (struct lwp_info *lwp, int *wstat)
   return 0;
 }
 
-/* Arrange for a breakpoint to be hit again later.  We don't keep the
-   SIGTRAP status and don't forward the SIGTRAP signal to the LWP.  We
-   will handle the current event, eventually we will resume this LWP,
-   and this breakpoint will trap again.  */
+/* Return true if the event in LP may be caused by breakpoint.  */
 
 static int
-cancel_breakpoint (struct lwp_info *lwp)
+wstatus_maybe_breakpoint (int wstatus)
 {
-  struct thread_info *saved_thread;
+  return (WIFSTOPPED (wstatus)
+	  && (WSTOPSIG (wstatus) == SIGTRAP
+	      /* SIGILL and SIGSEGV are also treated as traps in case a
+		 breakpoint is inserted at the current PC.  */
+	      || WSTOPSIG (wstatus) == SIGILL
+	      || WSTOPSIG (wstatus) == SIGSEGV));
+}
 
-  /* There's nothing to do if we don't support breakpoints.  */
-  if (!supports_breakpoints ())
-    return 0;
+/* Fetch the possibly triggered data watchpoint info and store it in
+   CHILD.
 
-  /* breakpoint_at reads from current inferior.  */
-  saved_thread = current_thread;
-  current_thread = get_lwp_thread (lwp);
+   On some archs, like x86, that use debug registers to set
+   watchpoints, it's possible that the way to know which watched
+   address trapped, is to check the register that is used to select
+   which address to watch.  Problem is, between setting the watchpoint
+   and reading back which data address trapped, the user may change
+   the set of watchpoints, and, as a consequence, GDB changes the
+   debug registers in the inferior.  To avoid reading back a stale
+   stopped-data-address when that happens, we cache in LP the fact
+   that a watchpoint trapped, and the corresponding data address, as
+   soon as we see CHILD stop with a SIGTRAP.  If GDB changes the debug
+   registers meanwhile, we have the cached data we can rely on.  */
 
-  if ((*the_low_target.breakpoint_at) (lwp->stop_pc))
+static int
+check_stopped_by_watchpoint (struct lwp_info *child)
+{
+  if (the_low_target.stopped_by_watchpoint != NULL)
     {
-      if (debug_threads)
-	debug_printf ("CB: Push back breakpoint for %s\n",
-		      target_pid_to_str (ptid_of (current_thread)));
+      struct thread_info *saved_thread;
 
-      /* Back up the PC if necessary.  */
-      if (the_low_target.decr_pc_after_break)
+      saved_thread = current_thread;
+      current_thread = get_lwp_thread (child);
+
+      if (the_low_target.stopped_by_watchpoint ())
 	{
-	  struct regcache *regcache
-	    = get_thread_regcache (current_thread, 1);
-	  (*the_low_target.set_pc) (regcache, lwp->stop_pc);
+	  child->stop_reason = LWP_STOPPED_BY_WATCHPOINT;
+
+	  if (the_low_target.stopped_data_address != NULL)
+	    child->stopped_data_address
+	      = the_low_target.stopped_data_address ();
+	  else
+	    child->stopped_data_address = 0;
 	}
 
       current_thread = saved_thread;
-      return 1;
-    }
-  else
-    {
-      if (debug_threads)
-	debug_printf ("CB: No breakpoint found at %s for [%s]\n",
-		      paddress (lwp->stop_pc),
-		      target_pid_to_str (ptid_of (current_thread)));
     }
 
-  current_thread = saved_thread;
-  return 0;
-}
-
-/* Return true if the event in LP may be caused by breakpoint.  */
-
-static int
-lp_status_maybe_breakpoint (struct lwp_info *lp)
-{
-  return (lp->status_pending_p
-	  && WIFSTOPPED (lp->status_pending)
-	  && (WSTOPSIG (lp->status_pending) == SIGTRAP
-	      /* SIGILL and SIGSEGV are also treated as traps in case a
-		 breakpoint is inserted at the current PC.  */
-	      || WSTOPSIG (lp->status_pending) == SIGILL
-	      || WSTOPSIG (lp->status_pending) == SIGSEGV));
+  return child->stop_reason == LWP_STOPPED_BY_WATCHPOINT;
 }
 
 /* Do low-level handling of the event, and check if we should go on
@@ -1758,10 +1879,11 @@  lp_status_maybe_breakpoint (struct lwp_info *lp)
    NULL otherwise.  */
 
 static struct lwp_info *
-linux_low_filter_event (ptid_t filter_ptid, int lwpid, int wstat)
+linux_low_filter_event (int lwpid, int wstat)
 {
   struct lwp_info *child;
   struct thread_info *thread;
+  int have_stop_pc = 0;
 
   child = find_lwp_pid (pid_to_ptid (lwpid));
 
@@ -1783,6 +1905,35 @@  linux_low_filter_event (ptid_t filter_ptid, int lwpid, int wstat)
 
   child->last_status = wstat;
 
+  /* Check if the thread has exited.  */
+  if ((WIFEXITED (wstat) || WIFSIGNALED (wstat)))
+    {
+      if (debug_threads)
+	debug_printf ("LLFE: %d exited.\n", lwpid);
+      if (num_lwps (pid_of (thread)) > 1)
+	{
+
+	  /* If there is at least one more LWP, then the exit signal was
+	     not the end of the debugged application and should be
+	     ignored.  */
+	  delete_lwp (child);
+	  return NULL;
+	}
+      else
+	{
+	  /* This was the last lwp in the process.  Since events are
+	     serialized to GDB core, and we can't report this one
+	     right now, but GDB core and the other target layers will
+	     want to be notified about the exit code/signal, leave the
+	     status pending for the next time we're able to report
+	     it.  */
+	  mark_lwp_dead (child, wstat);
+	  return child;
+	}
+    }
+
+  gdb_assert (WIFSTOPPED (wstat));
+
   if (WIFSTOPPED (wstat))
     {
       struct process_info *proc;
@@ -1807,75 +1958,6 @@  linux_low_filter_event (ptid_t filter_ptid, int lwpid, int wstat)
 	}
     }
 
-  /* Store the STOP_PC, with adjustment applied.  This depends on the
-     architecture being defined already (so that CHILD has a valid
-     regcache), and on LAST_STATUS being set (to check for SIGTRAP or
-     not).  */
-  if (WIFSTOPPED (wstat))
-    {
-      if (debug_threads
-	  && the_low_target.get_pc != NULL)
-	{
-	  struct thread_info *saved_thread;
-	  struct regcache *regcache;
-	  CORE_ADDR pc;
-
-	  saved_thread = current_thread;
-	  current_thread = thread;
-	  regcache = get_thread_regcache (current_thread, 1);
-	  pc = (*the_low_target.get_pc) (regcache);
-	  debug_printf ("linux_low_filter_event: pc is 0x%lx\n", (long) pc);
-	  current_thread = saved_thread;
-	}
-
-      child->stop_pc = get_stop_pc (child);
-    }
-
-  /* Fetch the possibly triggered data watchpoint info and store it in
-     CHILD.
-
-     On some archs, like x86, that use debug registers to set
-     watchpoints, it's possible that the way to know which watched
-     address trapped, is to check the register that is used to select
-     which address to watch.  Problem is, between setting the
-     watchpoint and reading back which data address trapped, the user
-     may change the set of watchpoints, and, as a consequence, GDB
-     changes the debug registers in the inferior.  To avoid reading
-     back a stale stopped-data-address when that happens, we cache in
-     LP the fact that a watchpoint trapped, and the corresponding data
-     address, as soon as we see CHILD stop with a SIGTRAP.  If GDB
-     changes the debug registers meanwhile, we have the cached data we
-     can rely on.  */
-
-  if (WIFSTOPPED (wstat) && WSTOPSIG (wstat) == SIGTRAP)
-    {
-      if (the_low_target.stopped_by_watchpoint == NULL)
-	{
-	  child->stopped_by_watchpoint = 0;
-	}
-      else
-	{
-	  struct thread_info *saved_thread;
-
-	  saved_thread = current_thread;
-	  current_thread = thread;
-
-	  child->stopped_by_watchpoint
-	    = the_low_target.stopped_by_watchpoint ();
-
-	  if (child->stopped_by_watchpoint)
-	    {
-	      if (the_low_target.stopped_data_address != NULL)
-		child->stopped_data_address
-		  = the_low_target.stopped_data_address ();
-	      else
-		child->stopped_data_address = 0;
-	    }
-
-	  current_thread = saved_thread;
-	}
-    }
-
   if (WIFSTOPPED (wstat) && child->must_set_ptrace_flags)
     {
       struct process_info *proc = find_process_pid (pid_of (thread));
@@ -1884,13 +1966,28 @@  linux_low_filter_event (ptid_t filter_ptid, int lwpid, int wstat)
       child->must_set_ptrace_flags = 0;
     }
 
+  /* Be careful to not overwrite stop_pc until
+     check_stopped_by_breakpoint is called.  */
   if (WIFSTOPPED (wstat) && WSTOPSIG (wstat) == SIGTRAP
       && linux_is_extended_waitstatus (wstat))
     {
+      child->stop_pc = get_pc (child);
       handle_extended_wait (child, wstat);
       return NULL;
     }
 
+  if (WIFSTOPPED (wstat) && WSTOPSIG (wstat) == SIGTRAP
+      && check_stopped_by_watchpoint (child))
+    ;
+  else if (WIFSTOPPED (wstat) && wstatus_maybe_breakpoint (wstat))
+    {
+      if (check_stopped_by_breakpoint (child))
+	have_stop_pc = 1;
+    }
+
+  if (!have_stop_pc)
+    child->stop_pc = get_pc (child);
+
   if (WIFSTOPPED (wstat) && WSTOPSIG (wstat) == SIGSTOP
       && child->stop_expected)
     {
@@ -1906,7 +2003,7 @@  linux_low_filter_event (ptid_t filter_ptid, int lwpid, int wstat)
       else if (stopping_threads != NOT_STOPPING_THREADS)
 	{
 	  /* Stopping threads.  We don't want this SIGSTOP to end up
-	     pending in the FILTER_PTID handling below.  */
+	     pending.  */
 	  return NULL;
 	}
       else
@@ -1917,79 +2014,11 @@  linux_low_filter_event (ptid_t filter_ptid, int lwpid, int wstat)
 	}
     }
 
-    /* Check if the thread has exited.  */
-  if ((WIFEXITED (wstat) || WIFSIGNALED (wstat))
-      && num_lwps (pid_of (thread)) > 1)
-    {
-      if (debug_threads)
-	debug_printf ("LLW: %d exited.\n", lwpid);
-
-	 /* If there is at least one more LWP, then the exit signal
-	    was not the end of the debugged application and should be
-	    ignored.  */
-      delete_lwp (child);
-      return NULL;
-    }
-
-  if (!ptid_match (ptid_of (thread), filter_ptid))
-    {
-      if (debug_threads)
-	debug_printf ("LWP %d got an event %06x, leaving pending.\n",
-		      lwpid, wstat);
-
-      if (WIFSTOPPED (wstat))
-	{
-	  child->status_pending_p = 1;
-	  child->status_pending = wstat;
-
-	  if (WSTOPSIG (wstat) != SIGSTOP)
-	    {
-	      /* Cancel breakpoint hits.  The breakpoint may be
-		 removed before we fetch events from this process to
-		 report to the core.  It is best not to assume the
-		 moribund breakpoints heuristic always handles these
-		 cases --- it could be too many events go through to
-		 the core before this one is handled.  All-stop always
-		 cancels breakpoint hits in all threads.  */
-	      if (non_stop
-		  && lp_status_maybe_breakpoint (child)
-		  && cancel_breakpoint (child))
-		{
-		  /* Throw away the SIGTRAP.  */
-		  child->status_pending_p = 0;
-
-		  if (debug_threads)
-		    debug_printf ("LLW: LWP %d hit a breakpoint while"
-				  " waiting for another process;"
-				  " cancelled it\n", lwpid);
-		}
-	    }
-	}
-      else if (WIFEXITED (wstat) || WIFSIGNALED (wstat))
-	{
-	  if (debug_threads)
-	    debug_printf ("LLWE: process %d exited while fetching "
-			  "event from another LWP\n", lwpid);
-
-	  /* This was the last lwp in the process.  Since events are
-	     serialized to GDB core, and we can't report this one
-	     right now, but GDB core and the other target layers will
-	     want to be notified about the exit code/signal, leave the
-	     status pending for the next time we're able to report
-	     it.  */
-	  mark_lwp_dead (child, wstat);
-	}
-
-      return NULL;
-    }
-
+  child->status_pending_p = 1;
+  child->status_pending = wstat;
   return child;
 }
 
-/* When the event-loop is doing a step-over, this points at the thread
-   being stepped.  */
-ptid_t step_over_bkpt;
-
 /* Wait for an event from child(ren) WAIT_PTID, and return any that
    match FILTER_PTID (leaving others pending).  The PTIDs can be:
    minus_one_ptid, to specify any child; a pid PTID, specifying all
@@ -2079,6 +2108,9 @@  linux_wait_for_event_filtered (ptid_t wait_ptid, ptid_t filter_ptid,
   sigfillset (&block_mask);
   sigprocmask (SIG_BLOCK, &block_mask, &prev_mask);
 
+  /* Always pull all events out of the kernel.  We'll randomly select
+     an event LWP out of all that have events, to prevent
+     starvation.  */
   while (event_child == NULL)
     {
       pid_t ret = 0;
@@ -2111,20 +2143,28 @@  linux_wait_for_event_filtered (ptid_t wait_ptid, ptid_t filter_ptid,
 			    (long) ret, status_to_str (*wstatp));
 	    }
 
-	  event_child = linux_low_filter_event (filter_ptid,
-						ret, *wstatp);
-	  if (event_child != NULL)
-	    {
-	      /* We got an event to report to the core.  */
-	      event_thread = get_lwp_thread (event_child);
-	      break;
-	    }
-
+	  /* Filter all events.  IOW, leave all events pending.  We'll
+	     randomly select an event LWP out of all that have events
+	     below.  */
+	  linux_low_filter_event (ret, *wstatp);
 	  /* Retry until nothing comes out of waitpid.  A single
 	     SIGCHLD can indicate more than one child stopped.  */
 	  continue;
 	}
 
+      /* Now that we've pulled all events out of the kernel, check if
+	 there's any LWP with a status to report to the core.  */
+      event_thread = (struct thread_info *)
+	find_inferior (&all_threads, status_pending_p_callback, &filter_ptid);
+      if (event_thread != NULL)
+	{
+	  event_child = get_thread_lwp (event_thread);
+	  *wstatp = event_child->status_pending;
+	  event_child->status_pending_p = 0;
+	  event_child->status_pending = 0;
+	  break;
+	}
+
       /* Check for zombie thread group leaders.  Those can't be reaped
 	 until all other threads in the thread group are.  */
       check_zombie_leaders ();
@@ -2204,17 +2244,14 @@  static int
 count_events_callback (struct inferior_list_entry *entry, void *data)
 {
   struct thread_info *thread = (struct thread_info *) entry;
-  struct lwp_info *lp = get_thread_lwp (thread);
   int *count = data;
 
   gdb_assert (count != NULL);
 
-  /* Count only resumed LWPs that have a SIGTRAP event pending that
-     should be reported to GDB.  */
+  /* Count only resumed LWPs that have an event pending. */
   if (thread->last_status.kind == TARGET_WAITKIND_IGNORE
       && thread->last_resume_kind != resume_stop
-      && lp_status_maybe_breakpoint (lp)
-      && !breakpoint_inserted_here (lp->stop_pc))
+      && thread->status_pending_p)
     (*count)++;
 
   return 0;
@@ -2243,62 +2280,20 @@  static int
 select_event_lwp_callback (struct inferior_list_entry *entry, void *data)
 {
   struct thread_info *thread = (struct thread_info *) entry;
-  struct lwp_info *lp = get_thread_lwp (thread);
   int *selector = data;
 
   gdb_assert (selector != NULL);
 
-  /* Select only resumed LWPs that have a SIGTRAP event pending. */
+  /* Select only resumed LWPs that have an event pending. */
   if (thread->last_resume_kind != resume_stop
       && thread->last_status.kind == TARGET_WAITKIND_IGNORE
-      && lp_status_maybe_breakpoint (lp)
-      && !breakpoint_inserted_here (lp->stop_pc))
+      && thread->status_pending_p)
     if ((*selector)-- == 0)
       return 1;
 
   return 0;
 }
 
-static int
-cancel_breakpoints_callback (struct inferior_list_entry *entry, void *data)
-{
-  struct thread_info *thread = (struct thread_info *) entry;
-  struct lwp_info *lp = get_thread_lwp (thread);
-  struct lwp_info *event_lp = data;
-
-  /* Leave the LWP that has been elected to receive a SIGTRAP alone.  */
-  if (lp == event_lp)
-    return 0;
-
-  /* If a LWP other than the LWP that we're reporting an event for has
-     hit a GDB breakpoint (as opposed to some random trap signal),
-     then just arrange for it to hit it again later.  We don't keep
-     the SIGTRAP status and don't forward the SIGTRAP signal to the
-     LWP.  We will handle the current event, eventually we will resume
-     all LWPs, and this one will get its breakpoint trap again.
-
-     If we do not do this, then we run the risk that the user will
-     delete or disable the breakpoint, but the LWP will have already
-     tripped on it.  */
-
-  if (thread->last_resume_kind != resume_stop
-      && thread->last_status.kind == TARGET_WAITKIND_IGNORE
-      && lp_status_maybe_breakpoint (lp)
-      && !lp->stepping
-      && !lp->stopped_by_watchpoint
-      && cancel_breakpoint (lp))
-    /* Throw away the SIGTRAP.  */
-    lp->status_pending_p = 0;
-
-  return 0;
-}
-
-static void
-linux_cancel_breakpoints (void)
-{
-  find_inferior (&all_threads, cancel_breakpoints_callback, NULL);
-}
-
 /* Select one LWP out of those that have events pending.  */
 
 static void
@@ -2306,20 +2301,30 @@  select_event_lwp (struct lwp_info **orig_lp)
 {
   int num_events = 0;
   int random_selector;
-  struct thread_info *event_thread;
-
-  /* Give preference to any LWP that is being single-stepped.  */
-  event_thread
-    = (struct thread_info *) find_inferior (&all_threads,
-					    select_singlestep_lwp_callback,
-					    NULL);
-  if (event_thread != NULL)
+  struct thread_info *event_thread = NULL;
+
+  /* In all-stop, give preference to the LWP that is being
+     single-stepped.  There will be at most one, and it's the LWP that
+     the core is most interested in.  If we didn't do this, then we'd
+     have to handle pending step SIGTRAPs somehow in case the core
+     later continues the previously-stepped thread, otherwise we'd
+     report the pending SIGTRAP, and the core, not having stepped the
+     thread, wouldn't understand what the trap was for, and therefore
+     would report it to the user as a random signal.  */
+  if (!non_stop)
     {
-      if (debug_threads)
-	debug_printf ("SEL: Select single-step %s\n",
-		      target_pid_to_str (ptid_of (event_thread)));
+      event_thread
+	= (struct thread_info *) find_inferior (&all_threads,
+						select_singlestep_lwp_callback,
+						NULL);
+      if (event_thread != NULL)
+	{
+	  if (debug_threads)
+	    debug_printf ("SEL: Select single-step %s\n",
+			  target_pid_to_str (ptid_of (event_thread)));
+	}
     }
-  else
+  if (event_thread == NULL)
     {
       /* No single-stepping LWP.  Select one at random, out of those
          which have had SIGTRAP events.  */
@@ -2486,6 +2491,23 @@  linux_stabilize_threads (void)
     }
 }
 
+static void async_file_mark (void);
+
+/* Convenience function that is called when the kernel reports an
+   event that is not passed out to GDB.  */
+
+static ptid_t
+ignore_event (struct target_waitstatus *ourstatus)
+{
+  /* If we got an event, there may still be others, as a single
+     SIGCHLD can indicate more than one child stopped.  This forces
+     another target_wait call.  */
+  async_file_mark ();
+
+  ourstatus->kind = TARGET_WAITKIND_IGNORE;
+  return null_ptid;
+}
+
 /* Wait for process, returns status.  */
 
 static ptid_t
@@ -2514,7 +2536,6 @@  linux_wait_1 (ptid_t ptid,
   if (target_options & TARGET_WNOHANG)
     options |= WNOHANG;
 
-retry:
   bp_explains_trap = 0;
   trace_event = 0;
   in_step_range = 0;
@@ -2679,7 +2700,8 @@  retry:
 			  WSTOPSIG (w), lwpid_of (current_thread));
 
 	  linux_resume_one_lwp (event_child, 0, 0, NULL);
-	  goto retry;
+
+	  return ignore_event (ourstatus);
 	}
     }
 
@@ -2713,7 +2735,6 @@  retry:
 		 care of while the breakpoint is still
 		 inserted.  */
 	      stop_all_lwps (1, event_child);
-	      cancel_breakpoints ();
 
 	      delete_breakpoint (event_child->exit_jump_pad_bkpt);
 	      event_child->exit_jump_pad_bkpt = NULL;
@@ -2797,7 +2818,7 @@  retry:
 	info_p = NULL;
       linux_resume_one_lwp (event_child, event_child->stepping,
 			    WSTOPSIG (w), info_p);
-      goto retry;
+      return ignore_event (ourstatus);
     }
 
   /* Note that all addresses are always "out of the step range" when
@@ -2816,7 +2837,7 @@  retry:
   report_to_gdb = (!maybe_internal_trap
 		   || (current_thread->last_resume_kind == resume_step
 		       && !in_step_range)
-		   || event_child->stopped_by_watchpoint
+		   || event_child->stop_reason == LWP_STOPPED_BY_WATCHPOINT
 		   || (!step_over_finished && !in_step_range
 		       && !bp_explains_trap && !trace_event)
 		   || (gdb_breakpoint_here (event_child->stop_pc)
@@ -2868,7 +2889,7 @@  retry:
 	unsuspend_all_lwps (event_child);
 
       proceed_all_lwps ();
-      goto retry;
+      return ignore_event (ourstatus);
     }
 
   if (debug_threads)
@@ -2880,9 +2901,9 @@  retry:
 	  else if (!lwp_in_step_range (event_child))
 	    debug_printf ("Out of step range, reporting event.\n");
 	}
-      if (event_child->stopped_by_watchpoint)
+      if (event_child->stop_reason == LWP_STOPPED_BY_WATCHPOINT)
 	debug_printf ("Stopped by watchpoint.\n");
-      if (gdb_breakpoint_here (event_child->stop_pc))
+      else if (gdb_breakpoint_here (event_child->stop_pc))
 	debug_printf ("Stopped by GDB breakpoint.\n");
       if (debug_threads)
 	debug_printf ("Hit a non-gdbserver trap event.\n");
@@ -2890,10 +2911,11 @@  retry:
 
   /* Alright, we're going to report a stop.  */
 
-  if (!non_stop && !stabilizing_threads)
+  if (!stabilizing_threads)
     {
       /* In all-stop, stop all threads.  */
-      stop_all_lwps (0, NULL);
+      if (!non_stop)
+	stop_all_lwps (0, NULL);
 
       /* If we're not waiting for a specific LWP, choose an event LWP
 	 from among those that have had events.  Giving equal priority
@@ -2913,23 +2935,33 @@  retry:
 	  w = event_child->status_pending;
 	}
 
-      /* Now that we've selected our final event LWP, cancel any
-	 breakpoints in other LWPs that have hit a GDB breakpoint.
-	 See the comment in cancel_breakpoints_callback to find out
-	 why.  */
-      find_inferior (&all_threads, cancel_breakpoints_callback, event_child);
-
-      /* If we were going a step-over, all other threads but the stepping one
-	 had been paused in start_step_over, with their suspend counts
-	 incremented.  We don't want to do a full unstop/unpause, because we're
-	 in all-stop mode (so we want threads stopped), but we still need to
-	 unsuspend the other threads, to decrement their `suspended' count
-	 back.  */
       if (step_over_finished)
-	unsuspend_all_lwps (event_child);
+	{
+	  if (!non_stop)
+	    {
+	      /* If we were doing a step-over, all other threads but
+		 the stepping one had been paused in start_step_over,
+		 with their suspend counts incremented.  We don't want
+		 to do a full unstop/unpause, because we're in
+		 all-stop mode (so we want threads stopped), but we
+		 still need to unsuspend the other threads, to
+		 decrement their `suspended' count back.  */
+	      unsuspend_all_lwps (event_child);
+	    }
+	  else
+	    {
+	      /* If we just finished a step-over, then all threads had
+		 been momentarily paused.  In all-stop, that's fine,
+		 we want threads stopped by now anyway.  In non-stop,
+		 we need to re-resume threads that GDB wanted to be
+		 running.  */
+	      unstop_all_lwps (1, event_child);
+	    }
+	}
 
       /* Stabilize threads (move out of jump pads).  */
-      stabilize_threads ();
+      if (!non_stop)
+	stabilize_threads ();
     }
   else
     {
@@ -2943,6 +2975,20 @@  retry:
 
   ourstatus->kind = TARGET_WAITKIND_STOPPED;
 
+  /* Now that we've selected our final event LWP, un-adjust its PC if
+     it was a software breakpoint.  */
+  if (event_child->stop_reason == LWP_STOPPED_BY_SW_BREAKPOINT)
+    {
+      int decr_pc = the_low_target.decr_pc_after_break;
+
+      if (decr_pc != 0)
+	{
+	  struct regcache *regcache
+	    = get_thread_regcache (current_thread, 1);
+	  (*the_low_target.set_pc) (regcache, event_child->stop_pc + decr_pc);
+	}
+    }
+
   if (current_thread->last_resume_kind == resume_stop
       && WSTOPSIG (w) == SIGSTOP)
     {
@@ -3014,7 +3060,13 @@  linux_wait (ptid_t ptid,
   if (target_is_async_p ())
     async_file_flush ();
 
-  event_ptid = linux_wait_1 (ptid, ourstatus, target_options);
+  do
+    {
+      event_ptid = linux_wait_1 (ptid, ourstatus, target_options);
+    }
+  while ((target_options & TARGET_WNOHANG) == 0
+	 && ptid_equal (event_ptid, null_ptid)
+	 && ourstatus->kind == TARGET_WAITKIND_IGNORE);
 
   /* If at least one stop was reported, there may be more.  A single
      SIGCHLD can signal more than one child stop.  */
@@ -3202,7 +3254,7 @@  stuck_in_jump_pad_callback (struct inferior_list_entry *entry, void *data)
   return (supports_fast_tracepoints ()
 	  && agent_loaded_p ()
 	  && (gdb_breakpoint_here (lwp->stop_pc)
-	      || lwp->stopped_by_watchpoint
+	      || lwp->stop_reason == LWP_STOPPED_BY_WATCHPOINT
 	      || thread->last_resume_kind == resume_step)
 	  && linux_fast_tracepoint_collecting (lwp, NULL));
 }
@@ -3221,7 +3273,7 @@  move_out_of_jump_pad_callback (struct inferior_list_entry *entry)
 
   /* Allow debugging the jump pad, gdb_collect, etc.  */
   if (!gdb_breakpoint_here (lwp->stop_pc)
-      && !lwp->stopped_by_watchpoint
+      && lwp->stop_reason != LWP_STOPPED_BY_WATCHPOINT
       && thread->last_resume_kind != resume_step
       && maybe_move_out_of_jump_pad (lwp, wstat))
     {
@@ -3445,11 +3497,17 @@  linux_resume_one_lwp (struct lwp_info *lwp,
       step = 1;
     }
 
-  if (debug_threads && the_low_target.get_pc != NULL)
+  if (the_low_target.get_pc != NULL)
     {
       struct regcache *regcache = get_thread_regcache (current_thread, 1);
-      CORE_ADDR pc = (*the_low_target.get_pc) (regcache);
-      debug_printf ("  resuming from pc 0x%lx\n", (long) pc);
+
+      lwp->stop_pc = (*the_low_target.get_pc) (regcache);
+
+      if (debug_threads)
+	{
+	  debug_printf ("  %s from pc 0x%lx\n", step ? "step" : "continue",
+			(long) lwp->stop_pc);
+	}
     }
 
   /* If we have pending signals, consume one unless we are trying to
@@ -3480,7 +3538,7 @@  linux_resume_one_lwp (struct lwp_info *lwp,
   regcache_invalidate_thread (thread);
   errno = 0;
   lwp->stopped = 0;
-  lwp->stopped_by_watchpoint = 0;
+  lwp->stop_reason = LWP_STOPPED_BY_NO_REASON;
   lwp->stepping = step;
   ptrace (step ? PTRACE_SINGLESTEP : PTRACE_CONT, lwpid_of (thread),
 	  (PTRACE_TYPE_ARG3) 0,
@@ -3601,7 +3659,7 @@  resume_status_pending_p (struct inferior_list_entry *entry, void *flag_p)
   if (lwp->resume == NULL)
     return 0;
 
-  if (lwp->status_pending_p)
+  if (thread_still_has_status_pending_p (thread))
     * (int *) flag_p = 1;
 
   return 0;
@@ -4886,7 +4944,7 @@  linux_stopped_by_watchpoint (void)
 {
   struct lwp_info *lwp = get_thread_lwp (current_thread);
 
-  return lwp->stopped_by_watchpoint;
+  return lwp->stop_reason == LWP_STOPPED_BY_WATCHPOINT;
 }
 
 static CORE_ADDR
@@ -6055,7 +6113,6 @@  static struct target_ops linux_target_ops = {
   NULL,
   linux_pause_all,
   linux_unpause_all,
-  linux_cancel_breakpoints,
   linux_stabilize_threads,
   linux_install_fast_tracepoint_jump_pad,
   linux_emit_ops,
diff --git a/gdb/gdbserver/linux-low.h b/gdb/gdbserver/linux-low.h
index 4820929..b2f0b91c 100644
--- a/gdb/gdbserver/linux-low.h
+++ b/gdb/gdbserver/linux-low.h
@@ -230,6 +230,24 @@  extern struct linux_target_ops the_low_target;
 #define get_thread_lwp(thr) ((struct lwp_info *) (inferior_target_data (thr)))
 #define get_lwp_thread(lwp) ((lwp)->thread)
 
+/* Reasons an LWP last stopped.  */
+
+enum lwp_stop_reason
+{
+  /* Either not stopped, or stopped for a reason that doesn't require
+     special tracking.  */
+  LWP_STOPPED_BY_NO_REASON,
+
+  /* Stopped by a software breakpoint.  */
+  LWP_STOPPED_BY_SW_BREAKPOINT,
+
+  /* Stopped by a hardware breakpoint.  */
+  LWP_STOPPED_BY_HW_BREAKPOINT,
+
+  /* Stopped by a watchpoint.  */
+  LWP_STOPPED_BY_WATCHPOINT
+};
+
 /* This struct is recorded in the target_data field of struct thread_info.
 
    On linux ``all_threads'' is keyed by the LWP ID, which we use as the
@@ -269,8 +287,9 @@  struct lwp_info
   /* When stopped is set, the last wait status recorded for this lwp.  */
   int last_status;
 
-  /* When stopped is set, this is where the lwp stopped, with
-     decr_pc_after_break already accounted for.  */
+  /* When stopped is set, this is where the lwp last stopped, with
+     decr_pc_after_break already accounted for.  If the LWP is
+     running, this is the address at which the lwp was resumed.  */
   CORE_ADDR stop_pc;
 
   /* If this flag is set, STATUS_PENDING is a waitstatus that has not yet
@@ -278,9 +297,9 @@  struct lwp_info
   int status_pending_p;
   int status_pending;
 
-  /* STOPPED_BY_WATCHPOINT is non-zero if this LWP stopped with a data
-     watchpoint trap.  */
-  int stopped_by_watchpoint;
+  /* The reason the LWP last stopped, if we need to track it
+     (breakpoint, watchpoint, etc.)  */
+  enum lwp_stop_reason stop_reason;
 
   /* On architectures where it is possible to know the data address of
      a triggered watchpoint, STOPPED_DATA_ADDRESS is non-zero, and
diff --git a/gdb/gdbserver/linux-x86-low.c b/gdb/gdbserver/linux-x86-low.c
index 838e7c9..885c1d6 100644
--- a/gdb/gdbserver/linux-x86-low.c
+++ b/gdb/gdbserver/linux-x86-low.c
@@ -805,7 +805,7 @@  x86_linux_prepare_to_resume (struct lwp_info *lwp)
       lwp->arch_private->debug_registers_changed = 0;
     }
 
-  if (clear_status || lwp->stopped_by_watchpoint)
+  if (clear_status || lwp->stop_reason == LWP_STOPPED_BY_WATCHPOINT)
     x86_linux_dr_set (ptid, DR_STATUS, 0);
 }
 
diff --git a/gdb/gdbserver/mem-break.c b/gdb/gdbserver/mem-break.c
index d7481c4..5f39bff 100644
--- a/gdb/gdbserver/mem-break.c
+++ b/gdb/gdbserver/mem-break.c
@@ -1610,6 +1610,40 @@  breakpoint_inserted_here (CORE_ADDR addr)
   return 0;
 }
 
+/* See mem-break.h.  */
+
+int
+software_breakpoint_inserted_here (CORE_ADDR addr)
+{
+  struct process_info *proc = current_process ();
+  struct raw_breakpoint *bp;
+
+  for (bp = proc->raw_breakpoints; bp != NULL; bp = bp->next)
+    if (bp->raw_type == raw_bkpt_type_sw
+	&& bp->pc == addr
+	&& bp->inserted)
+      return 1;
+
+  return 0;
+}
+
+/* See mem-break.h.  */
+
+int
+hardware_breakpoint_inserted_here (CORE_ADDR addr)
+{
+  struct process_info *proc = current_process ();
+  struct raw_breakpoint *bp;
+
+  for (bp = proc->raw_breakpoints; bp != NULL; bp = bp->next)
+    if (bp->raw_type == raw_bkpt_type_hw
+	&& bp->pc == addr
+	&& bp->inserted)
+      return 1;
+
+  return 0;
+}
+
 static int
 validate_inserted_breakpoint (struct raw_breakpoint *bp)
 {
diff --git a/gdb/gdbserver/mem-break.h b/gdb/gdbserver/mem-break.h
index c84c688..5f52d93 100644
--- a/gdb/gdbserver/mem-break.h
+++ b/gdb/gdbserver/mem-break.h
@@ -90,6 +90,16 @@  int breakpoint_here (CORE_ADDR addr);
 
 int breakpoint_inserted_here (CORE_ADDR addr);
 
+/* Returns TRUE if there's any inserted software breakpoint at
+   ADDR.  */
+
+int software_breakpoint_inserted_here (CORE_ADDR addr);
+
+/* Returns TRUE if there's any inserted hardware (code) breakpoint at
+   ADDR.  */
+
+int hardware_breakpoint_inserted_here (CORE_ADDR addr);
+
 /* Clear all breakpoint conditions and commands associated with a
    breakpoint.  */
 
diff --git a/gdb/gdbserver/target.h b/gdb/gdbserver/target.h
index 5e29b7f..d8c5c54 100644
--- a/gdb/gdbserver/target.h
+++ b/gdb/gdbserver/target.h
@@ -304,9 +304,6 @@  struct target_ops
      the pause call.  */
   void (*unpause_all) (int unfreeze);
 
-  /* Cancel all pending breakpoints hits in all threads.  */
-  void (*cancel_breakpoints) (void);
-
   /* Stabilize all threads.  That is, force them out of jump pads.  */
   void (*stabilize_threads) (void);
 
@@ -453,13 +450,6 @@  int kill_inferior (int);
 	(*the_target->unpause_all) (unfreeze);	\
     } while (0)
 
-#define cancel_breakpoints()			\
-  do						\
-    {						\
-      if (the_target->cancel_breakpoints)     	\
-	(*the_target->cancel_breakpoints) ();  	\
-    } while (0)
-
 #define stabilize_threads()			\
   do						\
     {						\
diff --git a/gdb/gdbserver/tracepoint.c b/gdb/gdbserver/tracepoint.c
index b6ab53f..1b2eba7 100644
--- a/gdb/gdbserver/tracepoint.c
+++ b/gdb/gdbserver/tracepoint.c
@@ -2443,7 +2443,6 @@  clear_installed_tracepoints (void)
   struct tracepoint *prev_stpoint;
 
   pause_all (1);
-  cancel_breakpoints ();
 
   prev_stpoint = NULL;
 
@@ -3433,9 +3432,6 @@  stop_tracing (void)
      We can't now, since we may be getting here due to the inferior
      agent calling us.  */
   pause_all (1);
-  /* Since we're removing breakpoints, cancel breakpoint hits,
-     possibly related to the breakpoints we're about to delete.  */
-  cancel_breakpoints ();
 
   /* Stop logging. Tracepoints can still be hit, but they will not be
      recorded.  */
@@ -6538,7 +6534,6 @@  upload_fast_traceframes (void)
   trace_debug ("Done uploading traceframes [%d]\n", curr_tbctrl_idx);
 
   pause_all (1);
-  cancel_breakpoints ();
 
   delete_breakpoint (about_to_request_buffer_space_bkpt);
   about_to_request_buffer_space_bkpt = NULL;