+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
/* 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;
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;
}
/* Fake the SIGSTOP that core GDB expects. */
lp->status = W_STOPCODE (SIGSTOP);
+ lp->resumed = 1;
}
static int
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)
{
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)
/* 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)
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. */
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)
{
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)
{
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);
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;
&& 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;
}