* lin-lwp.c (count_events_callback): Fix formatting. Turn check
authorMark Kettenis <kettenis@gnu.org>
Fri, 6 Jul 2001 22:31:47 +0000 (22:31 +0000)
committerMark Kettenis <kettenis@gnu.org>
Fri, 6 Jul 2001 22:31:47 +0000 (22:31 +0000)
commented with "paranoia" into gdb_assert.
(select_event_lwp_callback): Likewise.
(cancel_breakpoints_callback): Bail out early if LP is the event
LWP.  Add comment about backup up breakpoints.  Fix formatting and
debug message.
(select_event_lwp): Make solely repsonsible for switching event
LWP.  Fix formatting and remove bogus "ERROR" debug message.
Don't backup breakpoints from here.
(lin_lwp_wait): Don't touch LP->status, let select_event_lwp
handle that.  Only call select_event_lwp if we're not waiting for
a specific LWP, i.e. when PID == -1.  Backup breakpoints from here.

gdb/ChangeLog
gdb/lin-lwp.c

index 3f969be9581e1e50eac9a3d03b53ad2d5f6ff075..1fb4efc3477e98f0183e2e7ee49008030371a87d 100644 (file)
@@ -1,3 +1,18 @@
+2001-07-07  Mark Kettenis  <kettenis@gnu.org>
+
+       * lin-lwp.c (count_events_callback): Fix formatting.  Turn check
+       commented with "paranoia" into gdb_assert.
+       (select_event_lwp_callback): Likewise.
+       (cancel_breakpoints_callback): Bail out early if LP is the event
+       LWP.  Add comment about backup up breakpoints.  Fix formatting and
+       debug message.
+       (select_event_lwp): Make solely repsonsible for switching event
+       LWP.  Fix formatting and remove bogus "ERROR" debug message.
+       Don't backup breakpoints from here.
+       (lin_lwp_wait): Don't touch LP->status, let select_event_lwp
+       handle that.  Only call select_event_lwp if we're not waiting for
+       a specific LWP, i.e. when PID == -1.  Backup breakpoints from here.
+
 2001-07-06  Michael Snyder  <msnyder@redhat.com>
 
        * procfs.c (procfs_resume): Silence noisy warning.
index c36f523182e0352d818497730cc8adf57d695b57..89752ddc15cbbdc57e2b1f94cce1b70613c314e4 100644 (file)
@@ -722,24 +722,24 @@ running_callback (struct lwp_info *lp, void *data)
   return (lp->stopped == 0);
 }
 
-/* Count the LWP's that have had events. */
+/* Count the LWP's that have had events.  */
 
 static int
 count_events_callback (struct lwp_info *lp, void *data)
 {
   int *count = data;
 
-  /* Count only threads that have a SIGTRAP pending. */
-  if (lp->status != 0 &&
-      WIFSTOPPED (lp->status) && 
-      WSTOPSIG (lp->status) == SIGTRAP &&
-      count != NULL)   /* paranoia */
+  gdb_assert (count != NULL);
+
+  /* Count only LWPs that have a SIGTRAP event pending.  */
+  if (lp->status != 0
+      && WIFSTOPPED (lp->status) && WSTOPSIG (lp->status) == SIGTRAP)
     (*count)++;
 
   return 0;
 }
 
-/* Select the LWP (if any) that is currently being single-stepped. */
+/* Select the LWP (if any) that is currently being single-stepped.  */
 
 static int
 select_singlestep_lwp_callback (struct lwp_info *lp, void *data)
@@ -750,18 +750,18 @@ select_singlestep_lwp_callback (struct lwp_info *lp, void *data)
     return 0;
 }
 
-/* Select the Nth LWP that has had a SIGTRAP event. */
+/* Select the Nth LWP that has had a SIGTRAP event.  */
 
 static int
 select_event_lwp_callback (struct lwp_info *lp, void *data)
 {
   int *selector = data;
 
-  /* Select only threads that have a SIGTRAP event pending. */
-  if (lp->status != 0 &&
-      WIFSTOPPED (lp->status) &&
-      WSTOPSIG (lp->status) == SIGTRAP &&
-      selector != NULL)        /* paranoia */
+  gdb_assert (selector != NULL);
+
+  /* Select only LWPs that have a SIGTRAP event pending. */
+  if (lp->status != 0
+      && WIFSTOPPED (lp->status) && WSTOPSIG (lp->status) == SIGTRAP)
     if ((*selector)-- == 0)
       return 1;
 
@@ -773,32 +773,43 @@ cancel_breakpoints_callback (struct lwp_info *lp, void *data)
 {
   struct lwp_info *event_lp = data;
 
-  if (lp != event_lp &&
-      lp->status != 0 &&
-      WIFSTOPPED (lp->status) &&
-      WSTOPSIG (lp->status) == SIGTRAP &&
-      breakpoint_inserted_here_p (read_pc_pid (lp->ptid) - 
-                                 DECR_PC_AFTER_BREAK))
+  /* 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 (lp->status != 0
+      && WIFSTOPPED (lp->status) &&  WSTOPSIG (lp->status) == SIGTRAP
+      && breakpoint_inserted_here_p (read_pc_pid (lp->ptid) - 
+                                    DECR_PC_AFTER_BREAK))
     {
       if (debug_lin_lwp)
-       {
-         fprintf_unfiltered (gdb_stdlog, 
-                             "Push back BP for %ld\n",
-                             GET_LWP (lp->ptid));
-       }
-      /* For each lp except the event lp, if there was a trap,
-        set the PC to before the trap. */
+       fprintf_unfiltered (gdb_stdlog,
+                           "Push back breakpoint for LWP %ld\n",
+                           GET_LWP (lp->ptid));
+
+      /* Back up the PC if necessary.  */
       if (DECR_PC_AFTER_BREAK)
-       {
-         write_pc_pid (read_pc_pid (lp->ptid) - DECR_PC_AFTER_BREAK, 
-                       lp->ptid);
-       }
+       write_pc_pid (read_pc_pid (lp->ptid) - DECR_PC_AFTER_BREAK, lp->ptid);
+
+      /* Throw away the SIGTRAP.  */
       lp->status = 0;
     }
+
   return 0;
 }
 
-/* Select one LWP out of those that have events to be the event thread. */
+/* Select one LWP out of those that have events pending.  */
 
 static void
 select_event_lwp (struct lwp_info **orig_lp, int *status)
@@ -807,54 +818,48 @@ select_event_lwp (struct lwp_info **orig_lp, int *status)
   int random_selector;
   struct lwp_info *event_lp;
 
-  /* Give preference to any LWP that is being single-stepped. */
+  /* Record the wait status for the origional LWP.  */
+  (*orig_lp)->status = *status;
+
+  /* Give preference to any LWP that is being single-stepped.  */
   event_lp = iterate_over_lwps (select_singlestep_lwp_callback, NULL);
   if (event_lp != NULL)
     {
       if (debug_lin_lwp)
-       fprintf_unfiltered (gdb_stdlog, 
-                           "Select singlestep lwp %ld\n", 
+       fprintf_unfiltered (gdb_stdlog,
+                           "Select single-step LWP %ld\n",
                            GET_LWP (event_lp->ptid));
     }
   else
     {
       /* No single-stepping LWP.  Select one at random, out of those
-        which have had SIGTRAP events. */
+        which have had SIGTRAP events.  */
 
-      /* First see how many SIGTRAP events we have. */
-      iterate_over_lwps (count_events_callback, (void *) &num_events);
+      /* First see how many SIGTRAP events we have.  */
+      iterate_over_lwps (count_events_callback, &num_events);
 
-      /* OK, now randomly pick the Nth LWP of those that have had SIGTRAP. */
-      random_selector = (int) 
+      /* Now randomly pick a LWP out of those that have had a SIGTRAP.  */
+      random_selector = (int)
        ((num_events * (double) rand ()) / (RAND_MAX + 1.0));
 
-      if (debug_lin_lwp)
-       {
-         if (num_events > 1)
-           fprintf_unfiltered (gdb_stdlog, 
-                               "Found %d SIGTRAP events, selecting #%d\n", 
-                               num_events, random_selector);
-         else if (num_events <= 0)
-           fprintf_unfiltered (gdb_stdlog, 
-                               "ERROR select_event_lwp %d events!\n", 
-                               num_events);
-       }
+      if (debug_lin_lwp && num_events > 1)
+       fprintf_unfiltered (gdb_stdlog, 
+                           "Found %d SIGTRAP events, selecting #%d\n", 
+                           num_events, random_selector);
 
-      event_lp =  iterate_over_lwps (select_event_lwp_callback, 
-                                    (void *) &random_selector);
+      event_lp = iterate_over_lwps (select_event_lwp_callback,
+                                   &random_selector);
     }
 
   if (event_lp != NULL)
     {
-      /* "event_lp" is now the selected event thread.
-        If any other threads have had SIGTRAP events, these events
-        must now be cancelled, so that the respective thread will
-        trip the breakpoint again once it is resumed.  */
-      iterate_over_lwps (cancel_breakpoints_callback, (void *) event_lp);
+      /* Switch the event LWP.  */
       *orig_lp = event_lp;
       *status  = event_lp->status;
-      event_lp->status = 0;
     }
+
+  /* Flush the wait status for the event LWP.  */
+  (*orig_lp)->status = 0;
 }
 
 /* Return non-zero if LP has been resumed.  */
@@ -1097,12 +1102,6 @@ lin_lwp_wait (ptid_t ptid, struct target_waitstatus *ourstatus)
   /* This LWP is stopped now.  */
   lp->stopped = 1;
 
-  if (WIFSTOPPED (status) && WSTOPSIG (status) == SIGTRAP)
-    {
-      /* Save SIGTRAP event for select_event_lwp. */
-      lp->status = status;
-    }
-
   if (debug_lin_lwp)
     fprintf_unfiltered (gdb_stdlog, 
                        "LLW: Candidate event %d in %ld\n",
@@ -1115,11 +1114,16 @@ lin_lwp_wait (ptid_t ptid, struct target_waitstatus *ourstatus)
      longer running.  */
   iterate_over_lwps (stop_wait_callback, NULL);
 
-  /* MVS Now choose an event thread from among those that
-     have had events.  Giving equal priority to all threads
-     that have had events helps prevent starvation. */
+  /* 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 (pid == -1)
+    select_event_lwp (&lp, &status);
 
-  select_event_lwp (&lp, &status);
+  /* 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 (cancel_breakpoints_callback, lp);
 
   /* If we're not running in "threaded" mode, we'll report the bare
      process id.  */