* 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.
This commit is contained in:
Mark Kettenis 2001-06-07 19:31:10 +00:00
parent 54403c593a
commit fce0e6e1ed
2 changed files with 79 additions and 12 deletions

View 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> 2001-06-07 Keith Seitz <keiths@redhat.com>
* MAINTAINTERS: Syd Polk is stepping down from * MAINTAINTERS: Syd Polk is stepping down from

View file

@ -82,6 +82,14 @@ struct lwp_info
/* Non-zero if this LWP is stopped. */ /* Non-zero if this LWP is stopped. */
int 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. */ /* If non-zero, a pending wait status. */
int status; int status;
@ -249,11 +257,14 @@ find_lwp_pid (ptid_t ptid)
struct lwp_info * struct lwp_info *
iterate_over_lwps (int (*callback) (struct lwp_info *, void *), void *data) 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) for (lp = lwp_list; lp; lp = lpnext)
{
lpnext = lp->next;
if ((*callback) (lp, data)) if ((*callback) (lp, data))
return lp; return lp;
}
return NULL; return NULL;
} }
@ -357,6 +368,7 @@ lin_lwp_attach (char *args, int from_tty)
/* Fake the SIGSTOP that core GDB expects. */ /* Fake the SIGSTOP that core GDB expects. */
lp->status = W_STOPCODE (SIGSTOP); lp->status = W_STOPCODE (SIGSTOP);
lp->resumed = 1;
} }
static int static int
@ -475,6 +487,20 @@ resume_callback (struct lwp_info *lp, void *data)
return 0; 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 static void
lin_lwp_resume (ptid_t ptid, int step, enum target_signal signo) 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'. */ processes, but give the signal only to this one'. */
resume_all = (PIDGET (ptid) == -1) || !step; 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 /* If PID is -1, it's the current inferior that should be
handled specially. */ handled specially. */
if (PIDGET (ptid) == -1) 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. */ /* Remember if we're stepping. */
lp->step = step; lp->step = step;
/* Mark this LWP as resumed. */
lp->resumed = 1;
/* If we have a pending wait status for this thread, there is no /* If we have a pending wait status for this thread, there is no
point in resuming the process. */ point in resuming the process. */
if (lp->status) if (lp->status)
@ -663,7 +697,9 @@ stop_wait_callback (struct lwp_info *lp, void *data)
static int static int
status_callback (struct lwp_info *lp, void *data) 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 non-zero if LP isn't stopped. */
@ -674,6 +710,14 @@ running_callback (struct lwp_info *lp, void *data)
return (lp->stopped == 0); 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 static ptid_t
lin_lwp_wait (ptid_t ptid, struct target_waitstatus *ourstatus) 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: 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. */ /* First check if there is a LWP with a wait status pending. */
if (pid == -1) 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, child_resume (pid_to_ptid (GET_LWP (lp->ptid)), lp->step,
TARGET_SIGNAL_0); TARGET_SIGNAL_0);
lp->stopped = 0; lp->stopped = 0;
gdb_assert (lp->resumed);
/* This should catch the pending SIGSTOP. */ /* This should catch the pending SIGSTOP. */
stop_wait_callback (lp, NULL); 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, child_resume (pid_to_ptid (GET_LWP (lp->ptid)), lp->step,
TARGET_SIGNAL_0); TARGET_SIGNAL_0);
lp->stopped = 0; lp->stopped = 0;
gdb_assert (lp->resumed);
/* Discard the event. */ /* Discard the event. */
status = 0; status = 0;
@ -883,14 +932,13 @@ lin_lwp_wait (ptid_t ptid, struct target_waitstatus *ourstatus)
&& signal_print_state (signo) == 0 && signal_print_state (signo) == 0
&& signal_pass_state (signo) == 1) && signal_pass_state (signo) == 1)
{ {
/* First mark this LWP as "not stopped", so that /* FIMXE: kettenis/2001-06-06: Should we resume all threads
resume_callback will not resume it. */ here? It is not clear we should. GDB may not expect
lp->stopped = 0; other threads to run. On the other hand, not resuming
/* Resume all threads except this one newly attached threads may cause an unwanted delay in
(mainly to get the newly attached ones). */ getting them running. */
iterate_over_lwps (resume_callback, NULL);
/* Now resume this thread, forwarding the signal to it. */
child_resume (pid_to_ptid (GET_LWP (lp->ptid)), lp->step, signo); child_resume (pid_to_ptid (GET_LWP (lp->ptid)), lp->step, signo);
lp->stopped = 0;
status = 0; status = 0;
goto retry; goto retry;
} }