From 12d9289a51b52361abaeb31f1fce8ce38c22afd2 Mon Sep 17 00:00:00 2001 From: Pedro Alves Date: Wed, 12 Oct 2011 12:11:26 +0000 Subject: 2011-10-12 Pedro Alves gdb/ * linux-nat.c (stop_and_resume_callback): Don't re-resume LWPs if the core wanted them stopped, or if they now have a pending event to report. --- gdb/ChangeLog | 6 +++++ gdb/linux-nat.c | 74 +++++++++++++++++++++++++++++++++++++++++++++++---------- 2 files changed, 67 insertions(+), 13 deletions(-) (limited to 'gdb') diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 3ce02ce..fb5aded 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,9 @@ +2011-10-12 Pedro Alves + + * linux-nat.c (stop_and_resume_callback): Don't re-resume LWPs if + the core wanted them stopped, or if they now have a pending event + to report. + 2011-10-11 Sterling Augustine * dwarf2read.c: Undo inadvertent changes in previous commit. diff --git a/gdb/linux-nat.c b/gdb/linux-nat.c index 9a0d9e6..f8a15c9 100644 --- a/gdb/linux-nat.c +++ b/gdb/linux-nat.c @@ -3109,14 +3109,17 @@ resumed_callback (struct lwp_info *lp, void *data) return lp->resumed; } -/* Stop an active thread, verify it still exists, then resume it. */ +/* Stop an active thread, verify it still exists, then resume it. If + the thread ends up with a pending status, then it is not resumed, + and *DATA (really a pointer to int), is set. */ static int stop_and_resume_callback (struct lwp_info *lp, void *data) { + int *new_pending_p = data; + if (!lp->stopped) { - enum resume_kind last_resume_kind = lp->last_resume_kind; ptid_t ptid = lp->ptid; stop_callback (lp, NULL); @@ -3124,23 +3127,57 @@ stop_and_resume_callback (struct lwp_info *lp, void *data) /* Resume if the lwp still exists, and the core wanted it running. */ - if (last_resume_kind != resume_stop) + lp = find_lwp_pid (ptid); + if (lp != NULL) { - lp = find_lwp_pid (ptid); - if (lp) - resume_lwp (lp, lp->step); + if (lp->last_resume_kind == resume_stop + && lp->status == 0) + { + /* The core wanted the LWP to stop. Even if it stopped + cleanly (with SIGSTOP), leave the event pending. */ + if (debug_linux_nat) + fprintf_unfiltered (gdb_stdlog, + "SARC: core wanted LWP %ld stopped " + "(leaving SIGSTOP pending)\n", + GET_LWP (lp->ptid)); + lp->status = W_STOPCODE (SIGSTOP); + } + + if (lp->status == 0) + { + if (debug_linux_nat) + fprintf_unfiltered (gdb_stdlog, + "SARC: re-resuming LWP %ld\n", + GET_LWP (lp->ptid)); + resume_lwp (lp, lp->step); + } + else + { + if (debug_linux_nat) + fprintf_unfiltered (gdb_stdlog, + "SARC: not re-resuming LWP %ld " + "(has pending)\n", + GET_LWP (lp->ptid)); + if (new_pending_p) + *new_pending_p = 1; + } } } return 0; } /* Check if we should go on and pass this event to common code. - Return the affected lwp if we are, or NULL otherwise. */ + Return the affected lwp if we are, or NULL otherwise. If we stop + all lwps temporarily, we may end up with new pending events in some + other lwp. In that case set *NEW_PENDING_P to true. */ + static struct lwp_info * -linux_nat_filter_event (int lwpid, int status, int options) +linux_nat_filter_event (int lwpid, int status, int options, int *new_pending_p) { struct lwp_info *lp; + *new_pending_p = 0; + lp = find_lwp_pid (pid_to_ptid (lwpid)); /* Check for stop events reported by a process we didn't already @@ -3240,7 +3277,7 @@ linux_nat_filter_event (int lwpid, int status, int options) { lp->stopped = 1; iterate_over_lwps (pid_to_ptid (GET_PID (lp->ptid)), - stop_and_resume_callback, NULL); + stop_and_resume_callback, new_pending_p); } if (debug_linux_nat) @@ -3358,9 +3395,9 @@ linux_nat_wait_1 (struct target_ops *ops, { static sigset_t prev_mask; enum resume_kind last_resume_kind; - struct lwp_info *lp = NULL; - int options = 0; - int status = 0; + struct lwp_info *lp; + int options; + int status; pid_t pid; if (debug_linux_nat) @@ -3397,6 +3434,7 @@ linux_nat_wait_1 (struct target_ops *ops, retry: lp = NULL; status = 0; + options = 0; /* Make sure that of those LWPs we want to get an event from, there is at least one LWP that has been resumed. If there's none, just @@ -3527,6 +3565,10 @@ retry: if (lwpid > 0) { + /* If this is true, then we paused LWPs momentarily, and may + now have pending events to handle. */ + int new_pending; + gdb_assert (pid == -1 || lwpid == pid); if (debug_linux_nat) @@ -3536,7 +3578,7 @@ retry: (long) lwpid, status_to_str (status)); } - lp = linux_nat_filter_event (lwpid, status, options); + lp = linux_nat_filter_event (lwpid, status, options, &new_pending); /* STATUS is now no longer valid, use LP->STATUS instead. */ status = 0; @@ -3616,6 +3658,9 @@ retry: store_waitstatus (&lp->waitstatus, lp->status); } + if (new_pending) + goto retry; + /* Keep looking. */ lp = NULL; continue; @@ -3625,6 +3670,9 @@ retry: break; else { + if (new_pending) + goto retry; + if (pid == -1) { /* waitpid did return something. Restart over. */ -- cgit v1.1