diff options
author | Mark Kettenis <kettenis@gnu.org> | 2001-06-07 19:31:10 +0000 |
---|---|---|
committer | Mark Kettenis <kettenis@gnu.org> | 2001-06-07 19:31:10 +0000 |
commit | fce0e6e1ed31ade460b2734913aeca2ad566c39c (patch) | |
tree | a2c0f3b24a742cb3addfa4c869db5efcd92cb1aa /gdb/lin-lwp.c | |
parent | 54403c593aa5d8ad80548132ae4eb08914d8251e (diff) | |
download | gdb-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.c | 72 |
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; } |