aboutsummaryrefslogtreecommitdiff
path: root/gdb/lin-lwp.c
diff options
context:
space:
mode:
authorMark Kettenis <kettenis@gnu.org>2001-06-07 19:31:10 +0000
committerMark Kettenis <kettenis@gnu.org>2001-06-07 19:31:10 +0000
commitfce0e6e1ed31ade460b2734913aeca2ad566c39c (patch)
treea2c0f3b24a742cb3addfa4c869db5efcd92cb1aa /gdb/lin-lwp.c
parent54403c593aa5d8ad80548132ae4eb08914d8251e (diff)
downloadgdb-fce0e6e1ed31ade460b2734913aeca2ad566c39c.zip
gdb-fce0e6e1ed31ade460b2734913aeca2ad566c39c.tar.gz
gdb-fce0e6e1ed31ade460b2734913aeca2ad566c39c.tar.bz2
* 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.
Diffstat (limited to 'gdb/lin-lwp.c')
-rw-r--r--gdb/lin-lwp.c72
1 files changed, 60 insertions, 12 deletions
diff --git a/gdb/lin-lwp.c b/gdb/lin-lwp.c
index 0948a54..91f3691 100644
--- a/gdb/lin-lwp.c
+++ b/gdb/lin-lwp.c
@@ -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;
}