* 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:
parent
54403c593a
commit
fce0e6e1ed
2 changed files with 79 additions and 12 deletions
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue