summaryrefslogtreecommitdiff
path: root/gdb
diff options
context:
space:
mode:
authorUlrich Weigand <uweigand@de.ibm.com>2008-11-17 18:50:21 +0000
committerUlrich Weigand <uweigand@de.ibm.com>2008-11-17 18:50:21 +0000
commit8f58442d14dfbbfe0789a94eb903cf4e2fa18b82 (patch)
treea99d7d776dbb087548981d18dc3fc2362e1a308e /gdb
parent6b3e8b0e7a179e728d896a97c43decc6a12ca5c0 (diff)
downloadgdb-8f58442d14dfbbfe0789a94eb903cf4e2fa18b82.tar.gz
PR gdb/2250
* infrun.c (clear_proceed_status_thread): New function. (clear_proceed_status_callback): New function. (clear_proceed_status): In all-stop mode, clear per-thread proceed status of *all* threads, not only the current. (handle_inferior_event): In all-stop mode, if we're stepping one thread, but got some inferior event in another thread that does not cause GDB to break to the user interface, ensure the interrupted stepping operation continues in the original thread. (currently_stepping): Move thread-related tests to ... (currently_stepping_thread): ... this new function. (currently_stepping_callback): New function.
Diffstat (limited to 'gdb')
-rw-r--r--gdb/ChangeLog16
-rw-r--r--gdb/infrun.c124
2 files changed, 118 insertions, 22 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 2327ee17e90..e70bea18ccb 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,19 @@
+2008-11-17 Ulrich Weigand <uweigand@de.ibm.com>
+
+ PR gdb/2250
+ * infrun.c (clear_proceed_status_thread): New function.
+ (clear_proceed_status_callback): New function.
+ (clear_proceed_status): In all-stop mode, clear per-thread
+ proceed status of *all* threads, not only the current.
+ (handle_inferior_event): In all-stop mode, if we're stepping
+ one thread, but got some inferior event in another thread
+ that does not cause GDB to break to the user interface,
+ ensure the interrupted stepping operation continues in the
+ original thread.
+ (currently_stepping): Move thread-related tests to ...
+ (currently_stepping_thread): ... this new function.
+ (currently_stepping_callback): New function.
+
2008-11-17 Vladimir Prus <vladimir@codesourcery.com>
Implement =thread-selected notification.
diff --git a/gdb/infrun.c b/gdb/infrun.c
index 292200f237f..fbe0af06c8f 100644
--- a/gdb/infrun.c
+++ b/gdb/infrun.c
@@ -75,6 +75,8 @@ static void set_schedlock_func (char *args, int from_tty,
static int currently_stepping (struct thread_info *tp);
+static int currently_stepping_callback (struct thread_info *tp, void *data);
+
static void xdb_handle_command (char *args, int from_tty);
static int prepare_to_proceed (int);
@@ -1161,31 +1163,59 @@ a command like `return' or `jump' to continue execution."));
/* Clear out all variables saying what to do when inferior is continued.
First do this, then set the ones you want, then call `proceed'. */
-void
-clear_proceed_status (void)
+static void
+clear_proceed_status_thread (struct thread_info *tp)
{
- if (!ptid_equal (inferior_ptid, null_ptid))
- {
- struct thread_info *tp;
- struct inferior *inferior;
+ if (debug_infrun)
+ fprintf_unfiltered (gdb_stdlog,
+ "infrun: clear_proceed_status_thread (%s)\n",
+ target_pid_to_str (tp->ptid));
- tp = inferior_thread ();
+ tp->trap_expected = 0;
+ tp->step_range_start = 0;
+ tp->step_range_end = 0;
+ tp->step_frame_id = null_frame_id;
+ tp->step_over_calls = STEP_OVER_UNDEBUGGABLE;
+ tp->stop_requested = 0;
- tp->trap_expected = 0;
- tp->step_range_start = 0;
- tp->step_range_end = 0;
- tp->step_frame_id = null_frame_id;
- tp->step_over_calls = STEP_OVER_UNDEBUGGABLE;
- tp->stop_requested = 0;
+ tp->stop_step = 0;
- tp->stop_step = 0;
+ tp->proceed_to_finish = 0;
- tp->proceed_to_finish = 0;
+ /* Discard any remaining commands or status from previous stop. */
+ bpstat_clear (&tp->stop_bpstat);
+}
- /* Discard any remaining commands or status from previous
- stop. */
- bpstat_clear (&tp->stop_bpstat);
+static int
+clear_proceed_status_callback (struct thread_info *tp, void *data)
+{
+ if (is_exited (tp->ptid))
+ return 0;
+ clear_proceed_status_thread (tp);
+ return 0;
+}
+
+void
+clear_proceed_status (void)
+{
+ if (!ptid_equal (inferior_ptid, null_ptid))
+ {
+ struct inferior *inferior;
+
+ if (non_stop)
+ {
+ /* If in non-stop mode, only delete the per-thread status
+ of the current thread. */
+ clear_proceed_status_thread (inferior_thread ());
+ }
+ else
+ {
+ /* In all-stop mode, delete the per-thread status of
+ *all* threads. */
+ iterate_over_threads (clear_proceed_status_callback, NULL);
+ }
+
inferior = current_inferior ();
inferior->stop_soon = NO_STOP_QUIETLY;
}
@@ -3185,6 +3215,43 @@ infrun: BPSTAT_WHAT_SET_LONGJMP_RESUME (!gdbarch_get_longjmp_target)\n");
test for stepping. But, if not stepping,
do not stop. */
+ /* In all-stop mode, if we're currently stepping but have stopped in
+ some other thread, we need to switch back to the stepped thread. */
+ if (!non_stop)
+ {
+ struct thread_info *tp;
+ tp = iterate_over_threads (currently_stepping_callback,
+ ecs->event_thread);
+ if (tp)
+ {
+ /* However, if the current thread is blocked on some internal
+ breakpoint, and we simply need to step over that breakpoint
+ to get it going again, do that first. */
+ if ((ecs->event_thread->trap_expected
+ && ecs->event_thread->stop_signal != TARGET_SIGNAL_TRAP)
+ || ecs->event_thread->stepping_over_breakpoint)
+ {
+ keep_going (ecs);
+ return;
+ }
+
+ /* Otherwise, we no longer expect a trap in the current thread.
+ Clear the trap_expected flag before switching back -- this is
+ what keep_going would do as well, if we called it. */
+ ecs->event_thread->trap_expected = 0;
+
+ if (debug_infrun)
+ fprintf_unfiltered (gdb_stdlog,
+ "infrun: switching back to stepped thread\n");
+
+ ecs->event_thread = tp;
+ ecs->ptid = tp->ptid;
+ context_switch (ecs->ptid);
+ keep_going (ecs);
+ return;
+ }
+ }
+
/* Are we stepping to get the inferior out of the dynamic linker's
hook (and possibly the dld itself) after catching a shlib
event? */
@@ -3604,12 +3671,25 @@ infrun: BPSTAT_WHAT_SET_LONGJMP_RESUME (!gdbarch_get_longjmp_target)\n");
/* Are we in the middle of stepping? */
static int
+currently_stepping_thread (struct thread_info *tp)
+{
+ return (tp->step_range_end && tp->step_resume_breakpoint == NULL)
+ || tp->trap_expected
+ || tp->stepping_through_solib_after_catch;
+}
+
+static int
+currently_stepping_callback (struct thread_info *tp, void *data)
+{
+ /* Return true if any thread *but* the one passed in "data" is
+ in the middle of stepping. */
+ return tp != data && currently_stepping_thread (tp);
+}
+
+static int
currently_stepping (struct thread_info *tp)
{
- return (((tp->step_range_end && tp->step_resume_breakpoint == NULL)
- || tp->trap_expected)
- || tp->stepping_through_solib_after_catch
- || bpstat_should_step ());
+ return currently_stepping_thread (tp) || bpstat_should_step ();
}
/* Inferior has stepped into a subroutine call with source code that