* lin-lwp.c (struct lwp_info): Add member `resumed'.
authorMark Kettenis <kettenis@gnu.org>
Thu, 7 Jun 2001 19:31:10 +0000 (19:31 +0000)
committerMark Kettenis <kettenis@gnu.org>
Thu, 7 Jun 2001 19:31:10 +0000 (19:31 +0000)
(iterate_over_lwps): Make sure we can handle CALLBACK deleting the
LWP it's called for.
(lin_lwp_attach): Mark LWP as resumed to make sure the fake
SIGSTOP is reported.
(resume_clear_callback): New function.
(resume_set_callback): New function.
(lin_lwp_resume): Mark all LWP's that we're going to resume as
resumed, and unmark all others.
(status_callback): Only report a pending wait status if we pretend
that LP has been resumed.
(resumed_callback): New function.
(lin_lwp_wait): Add assertions to check that LWP's are properly
marked as resumed.  Partially revert 2001-05-25 patch by Michael
Snyder: do not resume all threads.  Add comment explaining the
problems associated with this bit of code.

gdb/ChangeLog
gdb/lin-lwp.c

index 41cc38bd3a8005be9b3e9bf95eb1b676a7a8d501..92cab61e25015e0469dfd17a31a8f5e1ede867e3 100644 (file)
@@ -1,3 +1,22 @@
+2001-06-06  Mark Kettenis  <kettenis@gnu.org>
+
+       * lin-lwp.c (struct lwp_info): Add member `resumed'.
+       (iterate_over_lwps): Make sure we can handle CALLBACK deleting the
+       LWP it's called for.
+       (lin_lwp_attach): Mark LWP as resumed to make sure the fake
+       SIGSTOP is reported.
+       (resume_clear_callback): New function.
+       (resume_set_callback): New function.
+       (lin_lwp_resume): Mark all LWP's that we're going to resume as
+       resumed, and unmark all others.
+       (status_callback): Only report a pending wait status if we pretend
+       that LP has been resumed.
+       (resumed_callback): New function.
+       (lin_lwp_wait): Add assertions to check that LWP's are properly
+       marked as resumed.  Partially revert 2001-05-25 patch by Michael
+       Snyder: do not resume all threads.  Add comment explaining the
+       problems associated with this bit of code.
+
 2001-06-07  Keith Seitz  <keiths@redhat.com>
 
        * MAINTAINTERS: Syd Polk is stepping down from
index 0948a543161e8b3f5aa2d9a2c76ebb64612a79a8..91f3691903bc0017e34485d25519e000b5a22edc 100644 (file)
@@ -82,6 +82,14 @@ struct lwp_info
   /* Non-zero if this LWP is stopped.  */
   int stopped;
 
+  /* Non-zero if this LWP will be/has been resumed.  Note that an LWP
+     can be marked both as stopped and resumed at the same time.  This
+     happens if we try to resume an LWP that has a wait status
+     pending.  We shouldn't let the LWP run until that wait status has
+     been processed, but we should not report that wait status if GDB
+     didn't try to let the LWP run.  */
+  int resumed;
+
   /* If non-zero, a pending wait status.  */
   int status;
 
@@ -249,11 +257,14 @@ find_lwp_pid (ptid_t ptid)
 struct lwp_info *
 iterate_over_lwps (int (*callback) (struct lwp_info *, void *), void *data)
 {
-  struct lwp_info *lp;
+  struct lwp_info *lp, *lpnext;
 
-  for (lp = lwp_list; lp; lp = lp->next)
-    if ((*callback) (lp, data))
-      return lp;
+  for (lp = lwp_list; lp; lp = lpnext)
+    {
+      lpnext = lp->next;
+      if ((*callback) (lp, data))
+       return lp;
+    }
 
   return NULL;
 }
@@ -357,6 +368,7 @@ lin_lwp_attach (char *args, int from_tty)
 
   /* Fake the SIGSTOP that core GDB expects.  */
   lp->status = W_STOPCODE (SIGSTOP);
+  lp->resumed = 1;
 }
 
 static int
@@ -475,6 +487,20 @@ resume_callback (struct lwp_info *lp, void *data)
   return 0;
 }
 
+static int
+resume_clear_callback (struct lwp_info *lp, void *data)
+{
+  lp->resumed = 0;
+  return 0;
+}
+
+static int
+resume_set_callback (struct lwp_info *lp, void *data)
+{
+  lp->resumed = 1;
+  return 0;
+}
+
 static void
 lin_lwp_resume (ptid_t ptid, int step, enum target_signal signo)
 {
@@ -487,6 +513,11 @@ lin_lwp_resume (ptid_t ptid, int step, enum target_signal signo)
      processes, but give the signal only to this one'.  */
   resume_all = (PIDGET (ptid) == -1) || !step;
 
+  if (resume_all)
+    iterate_over_lwps (resume_set_callback, NULL);
+  else
+    iterate_over_lwps (resume_clear_callback, NULL);
+
   /* If PID is -1, it's the current inferior that should be
      handled specially.  */
   if (PIDGET (ptid) == -1)
@@ -500,6 +531,9 @@ lin_lwp_resume (ptid_t ptid, int step, enum target_signal signo)
       /* Remember if we're stepping.  */
       lp->step = step;
 
+      /* Mark this LWP as resumed.  */
+      lp->resumed = 1;
+
       /* If we have a pending wait status for this thread, there is no
          point in resuming the process.  */
       if (lp->status)
@@ -663,7 +697,9 @@ stop_wait_callback (struct lwp_info *lp, void *data)
 static int
 status_callback (struct lwp_info *lp, void *data)
 {
-  return (lp->status != 0);
+  /* Only report a pending wait status if we pretend that this has
+     indeed been resumed.  */
+  return (lp->status != 0 && lp->resumed);
 }
 
 /* Return non-zero if LP isn't stopped.  */
@@ -674,6 +710,14 @@ running_callback (struct lwp_info *lp, void *data)
   return (lp->stopped == 0);
 }
 
+/* Return non-zero if LP has been resumed.  */
+
+static int
+resumed_callback (struct lwp_info *lp, void *data)
+{
+  return lp->resumed;
+}
+
 static ptid_t
 lin_lwp_wait (ptid_t ptid, struct target_waitstatus *ourstatus)
 {
@@ -691,6 +735,9 @@ lin_lwp_wait (ptid_t ptid, struct target_waitstatus *ourstatus)
 
  retry:
 
+  /* Make sure there is at least one thread that has been resumed.  */
+  gdb_assert (iterate_over_lwps (resumed_callback, NULL));
+
   /* First check if there is a LWP with a wait status pending.  */
   if (pid == -1)
     {
@@ -754,6 +801,7 @@ lin_lwp_wait (ptid_t ptid, struct target_waitstatus *ourstatus)
       child_resume (pid_to_ptid (GET_LWP (lp->ptid)), lp->step,
                     TARGET_SIGNAL_0);
       lp->stopped = 0;
+      gdb_assert (lp->resumed);
 
       /* This should catch the pending SIGSTOP.  */
       stop_wait_callback (lp, NULL);
@@ -840,6 +888,7 @@ lin_lwp_wait (ptid_t ptid, struct target_waitstatus *ourstatus)
              child_resume (pid_to_ptid (GET_LWP (lp->ptid)), lp->step,
                            TARGET_SIGNAL_0);
              lp->stopped = 0;
+             gdb_assert (lp->resumed);
 
              /* Discard the event.  */
              status = 0;
@@ -883,14 +932,13 @@ lin_lwp_wait (ptid_t ptid, struct target_waitstatus *ourstatus)
          && signal_print_state (signo) == 0
          && signal_pass_state (signo) == 1)
        {
-         /* First mark this LWP as "not stopped", so that
-            resume_callback will not resume it. */
-         lp->stopped = 0;
-         /* Resume all threads except this one
-            (mainly to get the newly attached ones). */
-         iterate_over_lwps (resume_callback, NULL);
-         /* Now resume this thread, forwarding the signal to it. */
+         /* 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.  */
          child_resume (pid_to_ptid (GET_LWP (lp->ptid)), lp->step, signo);
+         lp->stopped = 0;
          status = 0;
          goto retry;
        }
This page took 0.029787 seconds and 4 git commands to generate.