diff options
author | Pedro Alves <palves@redhat.com> | 2011-10-12 12:11:26 +0000 |
---|---|---|
committer | Pedro Alves <palves@redhat.com> | 2011-10-12 12:11:26 +0000 |
commit | 12d9289a51b52361abaeb31f1fce8ce38c22afd2 (patch) | |
tree | c295e0ab756dd617dbbd1f6caab2316f420d7793 | |
parent | 9ec72168368110c0ca99f41aacb30a7744379ab5 (diff) | |
download | gdb-12d9289a51b52361abaeb31f1fce8ce38c22afd2.zip gdb-12d9289a51b52361abaeb31f1fce8ce38c22afd2.tar.gz gdb-12d9289a51b52361abaeb31f1fce8ce38c22afd2.tar.bz2 |
2011-10-12 Pedro Alves <pedro@codesourcery.com>
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.
-rw-r--r-- | gdb/ChangeLog | 6 | ||||
-rw-r--r-- | gdb/linux-nat.c | 74 |
2 files changed, 67 insertions, 13 deletions
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 <pedro@codesourcery.com> + + * 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 <saugustine@google.com> * 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. */ |