linux-nat.c: better starvation avoidance, handle non-stop mode too
[deliverable/binutils-gdb.git] / gdb / linux-nat.c
index e2601e0dee69e06195d29365d64534bd5166c321..5f2c176b044799f9f734b51b53b40e9c765e63aa 100644 (file)
@@ -279,6 +279,10 @@ static struct lwp_info *find_lwp_pid (ptid_t ptid);
 
 static int lwp_status_pending_p (struct lwp_info *lp);
 
+static int check_stopped_by_breakpoint (struct lwp_info *lp);
+static int sigtrap_is_event (int status);
+static int (*linux_nat_status_is_event) (int status) = sigtrap_is_event;
+
 \f
 /* Trivial list manipulation functions to keep track of a list of
    new stopped processes.  */
@@ -1519,12 +1523,25 @@ linux_resume_one_lwp (struct lwp_info *lp, int step, enum gdb_signal signo)
   ptid_t ptid;
 
   lp->step = step;
+
+  /* stop_pc doubles as the PC the LWP had when it was last resumed.
+     We only presently need that if the LWP is stepped though (to
+     handle the case of stepping a breakpoint instruction).  */
+  if (step)
+    {
+      struct regcache *regcache = get_thread_regcache (lp->ptid);
+
+      lp->stop_pc = regcache_read_pc (regcache);
+    }
+  else
+    lp->stop_pc = 0;
+
   if (linux_nat_prepare_to_resume != NULL)
     linux_nat_prepare_to_resume (lp);
   /* Convert to something the lower layer understands.  */
   ptid = pid_to_ptid (ptid_get_lwp (lp->ptid));
   linux_ops->to_resume (linux_ops, ptid, step, signo);
-  lp->stopped_by_watchpoint = 0;
+  lp->stop_reason = LWP_STOPPED_BY_NO_REASON;
   lp->stopped = 0;
   registers_changed_ptid (lp->ptid);
 }
@@ -2374,24 +2391,21 @@ maybe_clear_ignore_sigint (struct lwp_info *lp)
    soon as we see LP stop with a SIGTRAP.  If GDB changes the debug
    registers meanwhile, we have the cached data we can rely on.  */
 
-static void
-save_sigtrap (struct lwp_info *lp)
+static int
+check_stopped_by_watchpoint (struct lwp_info *lp)
 {
   struct cleanup *old_chain;
 
   if (linux_ops->to_stopped_by_watchpoint == NULL)
-    {
-      lp->stopped_by_watchpoint = 0;
-      return;
-    }
+    return 0;
 
   old_chain = save_inferior_ptid ();
   inferior_ptid = lp->ptid;
 
-  lp->stopped_by_watchpoint = linux_ops->to_stopped_by_watchpoint (linux_ops);
-
-  if (lp->stopped_by_watchpoint)
+  if (linux_ops->to_stopped_by_watchpoint (linux_ops))
     {
+      lp->stop_reason = LWP_STOPPED_BY_WATCHPOINT;
+
       if (linux_ops->to_stopped_data_address != NULL)
        lp->stopped_data_address_p =
          linux_ops->to_stopped_data_address (&current_target,
@@ -2401,9 +2415,27 @@ save_sigtrap (struct lwp_info *lp)
     }
 
   do_cleanups (old_chain);
+
+  return lp->stop_reason == LWP_STOPPED_BY_WATCHPOINT;
 }
 
-/* See save_sigtrap.  */
+/* Called when the LWP stopped for a trap that could be explained by a
+   watchpoint or a breakpoint.  */
+
+static void
+save_sigtrap (struct lwp_info *lp)
+{
+  gdb_assert (lp->stop_reason == LWP_STOPPED_BY_NO_REASON);
+  gdb_assert (lp->status != 0);
+
+  if (check_stopped_by_watchpoint (lp))
+    return;
+
+  if (linux_nat_status_is_event (lp->status))
+    check_stopped_by_breakpoint (lp);
+}
+
+/* Returns true if the LWP had stopped for a watchpoint.  */
 
 static int
 linux_nat_stopped_by_watchpoint (struct target_ops *ops)
@@ -2412,7 +2444,7 @@ linux_nat_stopped_by_watchpoint (struct target_ops *ops)
 
   gdb_assert (lp != NULL);
 
-  return lp->stopped_by_watchpoint;
+  return lp->stop_reason == LWP_STOPPED_BY_WATCHPOINT;
 }
 
 static int
@@ -2435,24 +2467,6 @@ sigtrap_is_event (int status)
   return WIFSTOPPED (status) && WSTOPSIG (status) == SIGTRAP;
 }
 
-/* SIGTRAP-like events recognizer.  */
-
-static int (*linux_nat_status_is_event) (int status) = sigtrap_is_event;
-
-/* Check for SIGTRAP-like events in LP.  */
-
-static int
-linux_nat_lp_status_is_event (struct lwp_info *lp)
-{
-  /* We check for lp->waitstatus in addition to lp->status, because we can
-     have pending process exits recorded in lp->status
-     and W_EXITCODE(0,0) == 0.  We should probably have an additional
-     lp->status_p flag.  */
-
-  return (lp->waitstatus.kind == TARGET_WAITKIND_IGNORE
-         && linux_nat_status_is_event (lp->status));
-}
-
 /* Set alternative SIGTRAP-like events recognizer.  If
    breakpoint_inserted_here_p there then gdbarch_decr_pc_after_break will be
    applied.  */
@@ -2508,8 +2522,6 @@ stop_wait_callback (struct lwp_info *lp, void *data)
        {
          /* The thread was stopped with a signal other than SIGSTOP.  */
 
-         save_sigtrap (lp);
-
          if (debug_linux_nat)
            fprintf_unfiltered (gdb_stdlog,
                                "SWC: Pending event %s in %s\n",
@@ -2519,6 +2531,7 @@ stop_wait_callback (struct lwp_info *lp, void *data)
          /* Save the sigtrap event.  */
          lp->status = status;
          gdb_assert (lp->signalled);
+         save_sigtrap (lp);
        }
       else
        {
@@ -2539,7 +2552,9 @@ stop_wait_callback (struct lwp_info *lp, void *data)
   return 0;
 }
 
-/* Return non-zero if LP has a wait status pending.  */
+/* Return non-zero if LP has a wait status pending.  Discard the
+   pending event and resume the LWP if the event that originally
+   caused the stop became uninteresting.  */
 
 static int
 status_callback (struct lwp_info *lp, void *data)
@@ -2549,6 +2564,53 @@ status_callback (struct lwp_info *lp, void *data)
   if (!lp->resumed)
     return 0;
 
+  if (lp->stop_reason == LWP_STOPPED_BY_SW_BREAKPOINT
+      || lp->stop_reason == LWP_STOPPED_BY_HW_BREAKPOINT)
+    {
+      struct regcache *regcache = get_thread_regcache (lp->ptid);
+      struct gdbarch *gdbarch = get_regcache_arch (regcache);
+      CORE_ADDR pc;
+      int discard = 0;
+
+      gdb_assert (lp->status != 0);
+
+      pc = regcache_read_pc (regcache);
+
+      if (pc != lp->stop_pc)
+       {
+         if (debug_linux_nat)
+           fprintf_unfiltered (gdb_stdlog,
+                               "SC: PC of %s changed.  was=%s, now=%s\n",
+                               target_pid_to_str (lp->ptid),
+                               paddress (target_gdbarch (), lp->stop_pc),
+                               paddress (target_gdbarch (), pc));
+         discard = 1;
+       }
+      else if (!breakpoint_inserted_here_p (get_regcache_aspace (regcache), pc))
+       {
+         if (debug_linux_nat)
+           fprintf_unfiltered (gdb_stdlog,
+                               "SC: previous breakpoint of %s, at %s gone\n",
+                               target_pid_to_str (lp->ptid),
+                               paddress (target_gdbarch (), lp->stop_pc));
+
+         discard = 1;
+       }
+
+      if (discard)
+       {
+         if (debug_linux_nat)
+           fprintf_unfiltered (gdb_stdlog,
+                               "SC: pending event of %s cancelled.\n",
+                               target_pid_to_str (lp->ptid));
+
+         lp->status = 0;
+         linux_resume_one_lwp (lp, lp->step, GDB_SIGNAL_0);
+         return 0;
+       }
+      return 1;
+    }
+
   return lwp_status_pending_p (lp);
 }
 
@@ -2570,8 +2632,8 @@ count_events_callback (struct lwp_info *lp, void *data)
 
   gdb_assert (count != NULL);
 
-  /* Count only resumed LWPs that have a SIGTRAP event pending.  */
-  if (lp->resumed && linux_nat_lp_status_is_event (lp))
+  /* Select only resumed LWPs that have an event pending.  */
+  if (lp->resumed && lwp_status_pending_p (lp))
     (*count)++;
 
   return 0;
@@ -2609,16 +2671,19 @@ select_event_lwp_callback (struct lwp_info *lp, void *data)
 
   gdb_assert (selector != NULL);
 
-  /* Select only resumed LWPs that have a SIGTRAP event pending.  */
-  if (lp->resumed && linux_nat_lp_status_is_event (lp))
+  /* Select only resumed LWPs that have an event pending.  */
+  if (lp->resumed && lwp_status_pending_p (lp))
     if ((*selector)-- == 0)
       return 1;
 
   return 0;
 }
 
+/* Called when the LWP got a signal/trap that could be explained by a
+   software or hardware breakpoint.  */
+
 static int
-cancel_breakpoint (struct lwp_info *lp)
+check_stopped_by_breakpoint (struct lwp_info *lp)
 {
   /* 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
@@ -2632,48 +2697,42 @@ cancel_breakpoint (struct lwp_info *lp)
   struct regcache *regcache = get_thread_regcache (lp->ptid);
   struct gdbarch *gdbarch = get_regcache_arch (regcache);
   CORE_ADDR pc;
+  CORE_ADDR sw_bp_pc;
+
+  pc = regcache_read_pc (regcache);
+  sw_bp_pc = pc - target_decr_pc_after_break (gdbarch);
 
-  pc = regcache_read_pc (regcache) - target_decr_pc_after_break (gdbarch);
-  if (breakpoint_inserted_here_p (get_regcache_aspace (regcache), pc))
+  if ((!lp->step || lp->stop_pc == sw_bp_pc)
+      && software_breakpoint_inserted_here_p (get_regcache_aspace (regcache),
+                                             sw_bp_pc))
     {
+      /* The LWP was either continued, or stepped a software
+        breakpoint instruction.  */
       if (debug_linux_nat)
        fprintf_unfiltered (gdb_stdlog,
-                           "CB: Push back breakpoint for %s\n",
+                           "CB: Push back software breakpoint for %s\n",
                            target_pid_to_str (lp->ptid));
 
       /* Back up the PC if necessary.  */
-      if (target_decr_pc_after_break (gdbarch))
-       regcache_write_pc (regcache, pc);
+      if (pc != sw_bp_pc)
+       regcache_write_pc (regcache, sw_bp_pc);
 
+      lp->stop_pc = sw_bp_pc;
+      lp->stop_reason = LWP_STOPPED_BY_SW_BREAKPOINT;
       return 1;
     }
-  return 0;
-}
 
-static int
-cancel_breakpoints_callback (struct lwp_info *lp, void *data)
-{
-  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 (hardware_breakpoint_inserted_here_p (get_regcache_aspace (regcache), pc))
+    {
+      if (debug_linux_nat)
+       fprintf_unfiltered (gdb_stdlog,
+                           "CB: Push back hardware breakpoint for %s\n",
+                           target_pid_to_str (lp->ptid));
 
-  if (linux_nat_lp_status_is_event (lp)
-      && cancel_breakpoint (lp))
-    /* Throw away the SIGTRAP.  */
-    lp->status = 0;
+      lp->stop_pc = pc;
+      lp->stop_reason = LWP_STOPPED_BY_HW_BREAKPOINT;
+      return 1;
+    }
 
   return 0;
 }
@@ -2685,36 +2744,48 @@ select_event_lwp (ptid_t filter, struct lwp_info **orig_lp, int *status)
 {
   int num_events = 0;
   int random_selector;
-  struct lwp_info *event_lp;
+  struct lwp_info *event_lp = NULL;
 
   /* Record the wait status for the original LWP.  */
   (*orig_lp)->status = *status;
 
-  /* Give preference to any LWP that is being single-stepped.  */
-  event_lp = iterate_over_lwps (filter,
-                               select_singlestep_lwp_callback, NULL);
-  if (event_lp != NULL)
+  /* In all-stop, give preference to the LWP that is being
+     single-stepped.  There will be at most one, and it will be 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, as
+     otherwise we'd report the pending SIGTRAP then, 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_linux_nat)
-       fprintf_unfiltered (gdb_stdlog,
-                           "SEL: Select single-step %s\n",
-                           target_pid_to_str (event_lp->ptid));
+      event_lp = iterate_over_lwps (filter,
+                                   select_singlestep_lwp_callback, NULL);
+      if (event_lp != NULL)
+       {
+         if (debug_linux_nat)
+           fprintf_unfiltered (gdb_stdlog,
+                               "SEL: Select single-step %s\n",
+                               target_pid_to_str (event_lp->ptid));
+       }
     }
-  else
+
+  if (event_lp == NULL)
     {
-      /* No single-stepping LWP.  Select one at random, out of those
-         which have had SIGTRAP events.  */
+      /* Pick one at random, out of those which have had events.  */
 
-      /* First see how many SIGTRAP events we have.  */
+      /* First see how many events we have.  */
       iterate_over_lwps (filter, count_events_callback, &num_events);
 
-      /* Now randomly pick a LWP out of those that have had a SIGTRAP.  */
+      /* Now randomly pick a LWP out of those that have had
+        events.  */
       random_selector = (int)
        ((num_events * (double) rand ()) / (RAND_MAX + 1.0));
 
       if (debug_linux_nat && num_events > 1)
        fprintf_unfiltered (gdb_stdlog,
-                           "SEL: Found %d SIGTRAP events, selecting #%d\n",
+                           "SEL: Found %d events, selecting #%d\n",
                            num_events, random_selector);
 
       event_lp = iterate_over_lwps (filter,
@@ -2748,8 +2819,6 @@ resumed_callback (struct lwp_info *lp, void *data)
 static int
 stop_and_resume_callback (struct lwp_info *lp, void *data)
 {
-  int *new_pending_p = data;
-
   if (!lp->stopped)
     {
       ptid_t ptid = lp->ptid;
@@ -2790,8 +2859,6 @@ stop_and_resume_callback (struct lwp_info *lp, void *data)
                                    "SARC: not re-resuming LWP %ld "
                                    "(has pending)\n",
                                    ptid_get_lwp (lp->ptid));
-             if (new_pending_p)
-               *new_pending_p = 1;
            }
        }
     }
@@ -2799,18 +2866,14 @@ stop_and_resume_callback (struct lwp_info *lp, void *data)
 }
 
 /* Check if we should go on and pass this event to common code.
-   Return the affected lwp if we are, or NULL otherwise.  If we stop
-   all lwps temporarily, we may end up with new pending events in some
-   other lwp.  In that case set *NEW_PENDING_P to true.  */
+   Return the affected lwp if we are, or NULL otherwise.  */
 
 static struct lwp_info *
-linux_nat_filter_event (int lwpid, int status, int *new_pending_p)
+linux_nat_filter_event (int lwpid, int status)
 {
   struct lwp_info *lp;
   int event = linux_ptrace_get_extended_event (status);
 
-  *new_pending_p = 0;
-
   lp = find_lwp_pid (pid_to_ptid (lwpid));
 
   /* Check for stop events reported by a process we didn't already
@@ -2890,42 +2953,62 @@ linux_nat_filter_event (int lwpid, int status, int *new_pending_p)
        return NULL;
     }
 
-  if (linux_nat_status_is_event (status))
-    save_sigtrap (lp);
-
   /* Check if the thread has exited.  */
-  if ((WIFEXITED (status) || WIFSIGNALED (status))
-      && num_lwps (ptid_get_pid (lp->ptid)) > 1)
+  if (WIFEXITED (status) || WIFSIGNALED (status))
     {
-      /* If this is the main thread, we must stop all threads and verify
-        if they are still alive.  This is because in the nptl thread model
-        on Linux 2.4, there is no signal issued for exiting LWPs
-        other than the main thread.  We only get the main thread exit
-        signal once all child threads have already exited.  If we
-        stop all the threads and use the stop_wait_callback to check
-        if they have exited we can determine whether this signal
-        should be ignored or whether it means the end of the debugged
-        application, regardless of which threading model is being
-        used.  */
-      if (ptid_get_pid (lp->ptid) == ptid_get_lwp (lp->ptid))
+      if (num_lwps (ptid_get_pid (lp->ptid)) > 1)
        {
-         iterate_over_lwps (pid_to_ptid (ptid_get_pid (lp->ptid)),
-                            stop_and_resume_callback, new_pending_p);
+         /* If this is the main thread, we must stop all threads and
+            verify if they are still alive.  This is because in the
+            nptl thread model on Linux 2.4, there is no signal issued
+            for exiting LWPs other than the main thread.  We only get
+            the main thread exit signal once all child threads have
+            already exited.  If we stop all the threads and use the
+            stop_wait_callback to check if they have exited we can
+            determine whether this signal should be ignored or
+            whether it means the end of the debugged application,
+            regardless of which threading model is being used.  */
+         if (ptid_get_pid (lp->ptid) == ptid_get_lwp (lp->ptid))
+           {
+             iterate_over_lwps (pid_to_ptid (ptid_get_pid (lp->ptid)),
+                                stop_and_resume_callback, NULL);
+           }
+
+         if (debug_linux_nat)
+           fprintf_unfiltered (gdb_stdlog,
+                               "LLW: %s exited.\n",
+                               target_pid_to_str (lp->ptid));
+
+         if (num_lwps (ptid_get_pid (lp->ptid)) > 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.  */
+             exit_lwp (lp);
+             return NULL;
+           }
        }
 
+      gdb_assert (lp->resumed);
+
       if (debug_linux_nat)
        fprintf_unfiltered (gdb_stdlog,
-                           "LLW: %s exited.\n",
-                           target_pid_to_str (lp->ptid));
+                           "Process %ld exited\n",
+                           ptid_get_lwp (lp->ptid));
 
-      if (num_lwps (ptid_get_pid (lp->ptid)) > 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.  */
-        exit_lwp (lp);
-        return NULL;
-       }
+      /* This was the last lwp in the process.  Since events are
+        serialized to GDB core, we may not be able 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.  */
+
+      /* Dead LWP's aren't expected to reported a pending sigstop.  */
+      lp->signalled = 0;
+
+      /* Store the pending event in the waitstatus, because
+        W_EXITCODE(0,0) == 0.  */
+      store_waitstatus (&lp->waitstatus, status);
+      return lp;
     }
 
   /* Check if the current LWP has previously exited.  In the nptl
@@ -3007,9 +3090,59 @@ linux_nat_filter_event (int lwpid, int status, int *new_pending_p)
       return NULL;
     }
 
+  /* Don't report signals that GDB isn't interested in, such as
+     signals that are neither printed nor stopped upon.  Stopping all
+     threads can be a bit time-consuming so if we want decent
+     performance with heavily multi-threaded programs, especially when
+     they're using a high frequency timer, we'd better avoid it if we
+     can.  */
+  if (WIFSTOPPED (status))
+    {
+      enum gdb_signal signo = gdb_signal_from_host (WSTOPSIG (status));
+
+      if (!non_stop)
+       {
+         /* Only do the below in all-stop, as we currently use SIGSTOP
+            to implement target_stop (see linux_nat_stop) in
+            non-stop.  */
+         if (signo == GDB_SIGNAL_INT && signal_pass_state (signo) == 0)
+           {
+             /* If ^C/BREAK is typed at the tty/console, SIGINT gets
+                forwarded to the entire process group, that is, all LWPs
+                will receive it - unless they're using CLONE_THREAD to
+                share signals.  Since we only want to report it once, we
+                mark it as ignored for all LWPs except this one.  */
+             iterate_over_lwps (pid_to_ptid (ptid_get_pid (lp->ptid)),
+                                             set_ignore_sigint, NULL);
+             lp->ignore_sigint = 0;
+           }
+         else
+           maybe_clear_ignore_sigint (lp);
+       }
+
+      /* When using hardware single-step, we need to report every signal.
+        Otherwise, signals in pass_mask may be short-circuited.  */
+      if (!lp->step
+         && WSTOPSIG (status) && sigismember (&pass_mask, WSTOPSIG (status)))
+       {
+         linux_resume_one_lwp (lp, lp->step, signo);
+         if (debug_linux_nat)
+           fprintf_unfiltered (gdb_stdlog,
+                               "LLW: %s %s, %s (preempt 'handle')\n",
+                               lp->step ?
+                               "PTRACE_SINGLESTEP" : "PTRACE_CONT",
+                               target_pid_to_str (lp->ptid),
+                               (signo != GDB_SIGNAL_0
+                                ? strsignal (gdb_signal_to_host (signo))
+                                : "0"));
+         return NULL;
+       }
+    }
+
   /* An interesting event.  */
   gdb_assert (lp);
   lp->status = status;
+  save_sigtrap (lp);
   return lp;
 }
 
@@ -3108,9 +3241,6 @@ linux_nat_wait_1 (struct target_ops *ops,
   /* Make sure SIGCHLD is blocked until the sigsuspend below.  */
   block_child_signals (&prev_mask);
 
-retry:
-  status = 0;
-
   /* First check if there is a LWP with a wait status pending.  */
   lp = iterate_over_lwps (ptid, status_callback, NULL);
   if (lp != NULL)
@@ -3128,7 +3258,9 @@ retry:
       set_sigint_trap ();
     }
 
-  /* But if we don't find a pending event, we'll have to wait.  */
+  /* But if we don't find a pending event, we'll have to wait.  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 (lp == NULL)
     {
@@ -3159,10 +3291,6 @@ retry:
 
       if (lwpid > 0)
        {
-         /* If this is true, then we paused LWPs momentarily, and may
-            now have pending events to handle.  */
-         int new_pending;
-
          if (debug_linux_nat)
            {
              fprintf_unfiltered (gdb_stdlog,
@@ -3170,101 +3298,18 @@ retry:
                                  (long) lwpid, status_to_str (status));
            }
 
-         lp = linux_nat_filter_event (lwpid, status, &new_pending);
-
-         /* STATUS is now no longer valid, use LP->STATUS instead.  */
-         status = 0;
-
-         if (lp && !ptid_match (lp->ptid, ptid))
-           {
-             gdb_assert (lp->resumed);
-
-             if (debug_linux_nat)
-               fprintf_unfiltered (gdb_stdlog,
-                                   "LWP %ld got an event %06x, "
-                                   "leaving pending.\n",
-                                   ptid_get_lwp (lp->ptid), lp->status);
-
-             if (WIFSTOPPED (lp->status))
-               {
-                 if (WSTOPSIG (lp->status) != 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
-                         && linux_nat_lp_status_is_event (lp)
-                         && cancel_breakpoint (lp))
-                       {
-                         /* Throw away the SIGTRAP.  */
-                         lp->status = 0;
-
-                         if (debug_linux_nat)
-                           fprintf_unfiltered (gdb_stdlog,
-                                               "LLW: LWP %ld hit a "
-                                               "breakpoint while "
-                                               "waiting for another "
-                                               "process; "
-                                               "cancelled it\n",
-                                               ptid_get_lwp (lp->ptid));
-                       }
-                   }
-                 else
-                   lp->signalled = 0;
-               }
-             else if (WIFEXITED (lp->status) || WIFSIGNALED (lp->status))
-               {
-                 if (debug_linux_nat)
-                   fprintf_unfiltered (gdb_stdlog,
-                                       "Process %ld exited while stopping "
-                                       "LWPs\n",
-                                       ptid_get_lwp (lp->ptid));
-
-                 /* 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.  */
-
-                 /* Dead LWP's aren't expected to reported a pending
-                    sigstop.  */
-                 lp->signalled = 0;
-
-                 /* Store the pending event in the waitstatus as
-                    well, because W_EXITCODE(0,0) == 0.  */
-                 store_waitstatus (&lp->waitstatus, lp->status);
-               }
-
-             /* Keep looking.  */
-             lp = NULL;
-           }
-
-         if (new_pending)
-           {
-             /* Some LWP now has a pending event.  Go all the way
-                back to check it.  */
-             goto retry;
-           }
-
-         if (lp)
-           {
-             /* We got an event to report to the core.  */
-             break;
-           }
-
+         linux_nat_filter_event (lwpid, status);
          /* 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.  */
+      lp = iterate_over_lwps (ptid, status_callback, NULL);
+      if (lp != NULL)
+       break;
+
       /* Check for zombie thread group leaders.  Those can't be reaped
         until all other threads in the thread group are.  */
       check_zombie_leaders ();
@@ -3314,68 +3359,6 @@ retry:
   status = lp->status;
   lp->status = 0;
 
-  /* Don't report signals that GDB isn't interested in, such as
-     signals that are neither printed nor stopped upon.  Stopping all
-     threads can be a bit time-consuming so if we want decent
-     performance with heavily multi-threaded programs, especially when
-     they're using a high frequency timer, we'd better avoid it if we
-     can.  */
-
-  if (WIFSTOPPED (status))
-    {
-      enum gdb_signal signo = gdb_signal_from_host (WSTOPSIG (status));
-
-      /* When using hardware single-step, we need to report every signal.
-        Otherwise, signals in pass_mask may be short-circuited.  */
-      if (!lp->step
-         && WSTOPSIG (status) && sigismember (&pass_mask, WSTOPSIG (status)))
-       {
-         /* FIMXE: kettenis/2001-06-06: Should we resume all threads
-            here?  It is not clear we should.  GDB may not expect
-            other threads to run.  On the other hand, not resuming
-            newly attached threads may cause an unwanted delay in
-            getting them running.  */
-         linux_resume_one_lwp (lp, lp->step, signo);
-         if (debug_linux_nat)
-           fprintf_unfiltered (gdb_stdlog,
-                               "LLW: %s %s, %s (preempt 'handle')\n",
-                               lp->step ?
-                               "PTRACE_SINGLESTEP" : "PTRACE_CONT",
-                               target_pid_to_str (lp->ptid),
-                               (signo != GDB_SIGNAL_0
-                                ? strsignal (gdb_signal_to_host (signo))
-                                : "0"));
-         goto retry;
-       }
-
-      if (!non_stop)
-       {
-         /* Only do the below in all-stop, as we currently use SIGINT
-            to implement target_stop (see linux_nat_stop) in
-            non-stop.  */
-         if (signo == GDB_SIGNAL_INT && signal_pass_state (signo) == 0)
-           {
-             /* If ^C/BREAK is typed at the tty/console, SIGINT gets
-                forwarded to the entire process group, that is, all LWPs
-                will receive it - unless they're using CLONE_THREAD to
-                share signals.  Since we only want to report it once, we
-                mark it as ignored for all LWPs except this one.  */
-             iterate_over_lwps (pid_to_ptid (ptid_get_pid (ptid)),
-                                             set_ignore_sigint, NULL);
-             lp->ignore_sigint = 0;
-           }
-         else
-           maybe_clear_ignore_sigint (lp);
-       }
-    }
-
-  /* This LWP is stopped now.  */
-  lp->stopped = 1;
-
-  if (debug_linux_nat)
-    fprintf_unfiltered (gdb_stdlog, "LLW: Candidate event %s in %s.\n",
-                       status_to_str (status), target_pid_to_str (lp->ptid));
-
   if (!non_stop)
     {
       /* Now stop all other LWP's ...  */
@@ -3384,33 +3367,46 @@ retry:
       /* ... and wait until all of them have reported back that
         they're no longer running.  */
       iterate_over_lwps (minus_one_ptid, stop_wait_callback, NULL);
+    }
+
+  /* If we're not waiting for a specific LWP, choose an event LWP from
+     among those that have had events.  Giving equal priority to all
+     LWPs that have had events helps prevent starvation.  */
+  if (ptid_equal (ptid, minus_one_ptid) || ptid_is_pid (ptid))
+    select_event_lwp (ptid, &lp, &status);
+
+  gdb_assert (lp != NULL);
+
+  /* Now that we've selected our final event LWP, un-adjust its PC if
+     it was a software breakpoint.  */
+  if (lp->stop_reason == LWP_STOPPED_BY_SW_BREAKPOINT)
+    {
+      struct regcache *regcache = get_thread_regcache (lp->ptid);
+      struct gdbarch *gdbarch = get_regcache_arch (regcache);
+      int decr_pc = target_decr_pc_after_break (gdbarch);
 
-      /* If we're not waiting for a specific LWP, choose an event LWP
-        from among those that have had events.  Giving equal priority
-        to all LWPs that have had events helps prevent
-        starvation.  */
-      if (ptid_equal (ptid, minus_one_ptid) || ptid_is_pid (ptid))
-       select_event_lwp (ptid, &lp, &status);
+      if (decr_pc != 0)
+       {
+         CORE_ADDR pc;
 
-      /* 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.  */
-      iterate_over_lwps (minus_one_ptid, cancel_breakpoints_callback, lp);
+         pc = regcache_read_pc (regcache);
+         regcache_write_pc (regcache, pc + decr_pc);
+       }
+    }
 
-      /* We'll need this to determine whether to report a SIGSTOP as
-        TARGET_WAITKIND_0.  Need to take a copy because
-        resume_clear_callback clears it.  */
-      last_resume_kind = lp->last_resume_kind;
+  /* We'll need this to determine whether to report a SIGSTOP as
+     GDB_SIGNAL_0.  Need to take a copy because resume_clear_callback
+     clears it.  */
+  last_resume_kind = lp->last_resume_kind;
 
+  if (!non_stop)
+    {
       /* In all-stop, from the core's perspective, all LWPs are now
         stopped until a new resume action is sent over.  */
       iterate_over_lwps (minus_one_ptid, resume_clear_callback, NULL);
     }
   else
     {
-      /* See above.  */
-      last_resume_kind = lp->last_resume_kind;
       resume_clear_callback (lp, NULL);
     }
 
This page took 0.037337 seconds and 4 git commands to generate.