From fce0e6e1ed31ade460b2734913aeca2ad566c39c Mon Sep 17 00:00:00 2001 From: Mark Kettenis Date: Thu, 7 Jun 2001 19:31:10 +0000 Subject: * 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. --- gdb/ChangeLog | 19 ++++++++++++++++ gdb/lin-lwp.c | 72 +++++++++++++++++++++++++++++++++++++++++++++++++---------- 2 files changed, 79 insertions(+), 12 deletions(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 41cc38b..92cab61 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,22 @@ +2001-06-06 Mark Kettenis + + * 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 * MAINTAINTERS: Syd Polk is stepping down from 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; } -- cgit v1.1