aboutsummaryrefslogtreecommitdiff
path: root/gdb/infrun.c
diff options
context:
space:
mode:
Diffstat (limited to 'gdb/infrun.c')
-rw-r--r--gdb/infrun.c157
1 files changed, 108 insertions, 49 deletions
diff --git a/gdb/infrun.c b/gdb/infrun.c
index 273c2bc..73ac090 100644
--- a/gdb/infrun.c
+++ b/gdb/infrun.c
@@ -62,6 +62,7 @@
#include "terminal.h"
#include "solist.h"
#include "event-loop.h"
+#include "thread-fsm.h"
/* Prototypes for local functions */
@@ -2749,6 +2750,9 @@ clear_proceed_status_thread (struct thread_info *tp)
if (!signal_pass_state (tp->suspend.stop_signal))
tp->suspend.stop_signal = GDB_SIGNAL_0;
+ thread_fsm_delete (tp->thread_fsm);
+ tp->thread_fsm = NULL;
+
tp->control.trap_expected = 0;
tp->control.step_range_start = 0;
tp->control.step_range_end = 0;
@@ -3220,7 +3224,7 @@ infrun_thread_stop_requested_callback (struct thread_info *info, void *arg)
have consistent output as if the stop event had been
reported. */
ecs->ptid = info->ptid;
- ecs->event_thread = find_thread_ptid (info->ptid);
+ ecs->event_thread = info;
ecs->ws.kind = TARGET_WAITKIND_STOPPED;
ecs->ws.value.sig = GDB_SIGNAL_0;
@@ -3230,6 +3234,9 @@ infrun_thread_stop_requested_callback (struct thread_info *info, void *arg)
{
struct thread_info *tp;
+ /* Cancel any running execution command. */
+ thread_cancel_execution_command (info);
+
normal_stop ();
/* Finish off the continuations. */
@@ -3718,6 +3725,35 @@ reinstall_readline_callback_handler_cleanup (void *arg)
gdb_rl_callback_handler_reinstall ();
}
+/* Clean up the FSMs of threads that are now stopped. In non-stop,
+ that's just the event thread. In all-stop, that's all threads. */
+
+static void
+clean_up_just_stopped_threads_fsms (struct execution_control_state *ecs)
+{
+ struct thread_info *thr = ecs->event_thread;
+
+ if (thr != NULL && thr->thread_fsm != NULL)
+ thread_fsm_clean_up (thr->thread_fsm);
+
+ if (!non_stop)
+ {
+ ALL_NON_EXITED_THREADS (thr)
+ {
+ if (thr->thread_fsm == NULL)
+ continue;
+ if (thr == ecs->event_thread)
+ continue;
+
+ switch_to_thread (thr->ptid);
+ thread_fsm_clean_up (thr->thread_fsm);
+ }
+
+ if (ecs->event_thread != NULL)
+ switch_to_thread (ecs->event_thread->ptid);
+ }
+}
+
/* Asynchronous version of wait_for_inferior. It is called by the
event loop whenever a change of state is detected on the file
descriptor corresponding to the target. It can be called more than
@@ -3796,22 +3832,31 @@ fetch_inferior_event (void *client_data)
if (!ecs->wait_some_more)
{
struct inferior *inf = find_inferior_ptid (ecs->ptid);
+ int should_stop = 1;
+ struct thread_info *thr = ecs->event_thread;
delete_just_stopped_threads_infrun_breakpoints ();
- /* We may not find an inferior if this was a process exit. */
- if (inf == NULL || inf->control.stop_soon == NO_STOP_QUIETLY)
- normal_stop ();
-
- if (target_has_execution
- && ecs->ws.kind != TARGET_WAITKIND_NO_RESUMED
- && ecs->ws.kind != TARGET_WAITKIND_EXITED
- && ecs->ws.kind != TARGET_WAITKIND_SIGNALLED
- && ecs->event_thread->step_multi
- && ecs->event_thread->control.stop_step)
- inferior_event_handler (INF_EXEC_CONTINUE, NULL);
+ if (thr != NULL)
+ {
+ struct thread_fsm *thread_fsm = thr->thread_fsm;
+
+ if (thread_fsm != NULL)
+ should_stop = thread_fsm_should_stop (thread_fsm);
+ }
+
+ if (!should_stop)
+ {
+ keep_going (ecs);
+ }
else
{
+ clean_up_just_stopped_threads_fsms (ecs);
+
+ /* We may not find an inferior if this was a process exit. */
+ if (inf == NULL || inf->control.stop_soon == NO_STOP_QUIETLY)
+ normal_stop ();
+
inferior_event_handler (INF_EXEC_COMPLETE, NULL);
cmd_done = 1;
}
@@ -5898,6 +5943,10 @@ process_event_stop_test (struct execution_control_state *ecs)
stop_stack_dummy = what.call_dummy;
}
+ /* A few breakpoint types have callbacks associated (e.g.,
+ bp_jit_event). Run them now. */
+ bpstat_run_callbacks (ecs->event_thread->control.stop_bpstat);
+
/* If we hit an internal event that triggers symbol changes, the
current frame will be invalidated within bpstat_what (e.g., if we
hit an internal solib event). Re-fetch it. */
@@ -7663,8 +7712,8 @@ print_no_history_reason (struct ui_out *uiout)
bpstat_print contains the logic deciding in detail what to print,
based on the event(s) that just occurred. */
-void
-print_stop_event (struct target_waitstatus *ws)
+static void
+print_stop_location (struct target_waitstatus *ws)
{
int bpstat_ret;
enum print_what source_flag;
@@ -7715,9 +7764,50 @@ print_stop_event (struct target_waitstatus *ws)
SRC_AND_LOC: Print location and source line. */
if (do_frame_printing)
print_stack_frame (get_selected_frame (NULL), 0, source_flag, 1);
+}
+
+/* Cleanup that restores a previous current uiout. */
+
+static void
+restore_current_uiout_cleanup (void *arg)
+{
+ struct ui_out *saved_uiout = arg;
+
+ current_uiout = saved_uiout;
+}
+
+/* See infrun.h. */
+
+void
+print_stop_event (struct ui_out *uiout)
+{
+ struct cleanup *old_chain;
+ struct target_waitstatus last;
+ ptid_t last_ptid;
+ struct thread_info *tp;
+
+ get_last_target_status (&last_ptid, &last);
+
+ old_chain = make_cleanup (restore_current_uiout_cleanup, current_uiout);
+ current_uiout = uiout;
+
+ print_stop_location (&last);
/* Display the auto-display expressions. */
do_displays ();
+
+ do_cleanups (old_chain);
+
+ tp = inferior_thread ();
+ if (tp->thread_fsm != NULL
+ && thread_fsm_finished_p (tp->thread_fsm))
+ {
+ struct return_value_info *rv;
+
+ rv = thread_fsm_return_value (tp->thread_fsm);
+ if (rv != NULL)
+ print_return_value (uiout, rv);
+ }
}
/* Here to return control to GDB when the inferior stops for real.
@@ -7830,20 +7920,6 @@ normal_stop (void)
if (stopped_by_random_signal)
disable_current_display ();
- /* Notify observers if we finished a "step"-like command, etc. */
- if (target_has_execution
- && last.kind != TARGET_WAITKIND_SIGNALLED
- && last.kind != TARGET_WAITKIND_EXITED
- && inferior_thread ()->control.stop_step)
- {
- /* But not if in the middle of doing a "step n" operation for
- n > 1 */
- if (inferior_thread ()->step_multi)
- goto done;
-
- observer_notify_end_stepping_range ();
- }
-
target_terminal_ours ();
async_enable_stdin ();
@@ -7885,15 +7961,7 @@ normal_stop (void)
or if the program has exited. */
if (!stop_stack_dummy)
- {
- select_frame (get_current_frame ());
-
- /* If --batch-silent is enabled then there's no need to print the current
- source location, and to try risks causing an error message about
- missing source files. */
- if (stop_print_frame && !batch_silent)
- print_stop_event (&last);
- }
+ select_frame (get_current_frame ());
if (stop_stack_dummy == STOP_STACK_DUMMY)
{
@@ -7917,16 +7985,9 @@ normal_stop (void)
}
done:
- annotate_stopped ();
/* Suppress the stop observer if we're in the middle of:
- - a step n (n > 1), as there still more steps to be done.
-
- - a "finish" command, as the observer will be called in
- finish_command_continuation, so it can include the inferior
- function's return value.
-
- calling an inferior function, as we pretend we inferior didn't
run at all. The return value of the call is handled by the
expression evaluator, through call_function_by_hand. */
@@ -7935,11 +7996,7 @@ done:
|| last.kind == TARGET_WAITKIND_SIGNALLED
|| last.kind == TARGET_WAITKIND_EXITED
|| last.kind == TARGET_WAITKIND_NO_RESUMED
- || (!(inferior_thread ()->step_multi
- && inferior_thread ()->control.stop_step)
- && !(inferior_thread ()->control.stop_bpstat
- && inferior_thread ()->control.proceed_to_finish)
- && !inferior_thread ()->control.in_infcall))
+ || !inferior_thread ()->control.in_infcall)
{
if (!ptid_equal (inferior_ptid, null_ptid))
observer_notify_normal_stop (inferior_thread ()->control.stop_bpstat,
@@ -7948,6 +8005,8 @@ done:
observer_notify_normal_stop (NULL, stop_print_frame);
}
+ annotate_stopped ();
+
if (target_has_execution)
{
if (last.kind != TARGET_WAITKIND_SIGNALLED