aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPedro Alves <palves@redhat.com>2015-09-09 18:23:24 +0100
committerPedro Alves <palves@redhat.com>2015-09-09 18:24:00 +0100
commit243a925328f8e3184b2356bee497181049c0174f (patch)
treebc734266b2d89d35bd5ab6a43d27499d46f4483e /gdb/thread-fsm.h
parentMerge async and sync code paths some more (diff)
downloadbinutils-gdb-243a925328f8e3184b2356bee497181049c0174f.tar.gz
binutils-gdb-243a925328f8e3184b2356bee497181049c0174f.tar.bz2
binutils-gdb-243a925328f8e3184b2356bee497181049c0174f.zip
Replace "struct continuation" mechanism by something more extensible
This adds an object oriented replacement for the "struct continuation" mechanism, and converts the stepping commands (step, next, stepi, nexti) and the "finish" commands to use it. It adds a new thread "class" (struct thread_fsm) that contains the necessary info and callbacks to manage the state machine of a thread's execution command. This allows getting rid of some hacks. E.g., in fetch_inferior_event and normal_stop we no longer need to know whether a thread is doing a multi-step (e.g., step N). This effectively makes the intermediate_continuations unused -- they'll be garbage collected in a separate patch. (They were never a proper abstraction, IMO. See how fetch_inferior_event needs to check step_multi before knowing whether to call INF_EXEC_CONTINUE or INF_EXEC_COMPLETE.) The target async vs !async uiout hacks in mi_on_normal_stop go away too. print_stop_event is no longer called from normal_stop. Instead it is now called from within each interpreter's normal_stop observer. This clears the path to make each interpreter print a stop event the way it sees fit. Currently we have some hacks in common code to differenciate CLI vs TUI vs MI around this area. The "finish" command's FSM class stores the return value plus that value's position in the value history, so that those can be printed to both MI and CLI's streams. This fixes the CLI "finish" command when run from MI -- it now also includes the function's return value in the CLI stream: (gdb) ~"callee3 (strarg=0x400730 \"A string argument.\") at src/gdb/testsuite/gdb.mi/basics.c:35\n" ~"35\t}\n" +~"Value returned is $1 = 0\n" *stopped,reason="function-finished",frame=...,gdb-result-var="$1",return-value="0",thread-id="1",stopped-threads="all",core="0" -FAIL: gdb.mi/mi-cli.exp: CLI finish: check CLI output +PASS: gdb.mi/mi-cli.exp: CLI finish: check CLI output gdb/ChangeLog: 2015-09-09 Pedro Alves <palves@redhat.com> * Makefile.in (COMMON_OBS): Add thread-fsm.o. * breakpoint.c (handle_jit_event): Print debug output. (bpstat_what): Split event callback handling to ... (bpstat_run_callbacks): ... this new function. (momentary_bkpt_print_it): No longer handle bp_finish here. * breakpoint.h (bpstat_run_callbacks): Declare. * gdbthread.h (struct thread_info) <step_multi>: Delete field. <thread_fsm>: New field. (thread_cancel_execution_command): Declare. * infcmd.c: Include thread-fsm.h. (struct step_command_fsm): New. (step_command_fsm_ops): New global. (new_step_command_fsm, step_command_fsm_prepare): New functions. (step_1): Adjust to use step_command_fsm_prepare and prepare_one_step. (struct step_1_continuation_args): Delete. (step_1_continuation): Delete. (step_command_fsm_should_stop): New function. (step_once): Delete. (step_command_fsm_clean_up, step_command_fsm_async_reply_reason) (prepare_one_step): New function, based on step_once. (until_next_command): Remove step_multi reference. (struct return_value_info): New. (print_return_value): Rename to ... (print_return_value_1): ... this. New struct return_value_info parameter. Adjust. (print_return_value): Reimplement as wrapper around print_return_value_1. (struct finish_command_fsm): New. (finish_command_continuation): Delete. (finish_command_fsm_ops): New global. (new_finish_command_fsm, finish_command_fsm_should_stop): New functions. (finish_command_fsm_clean_up, finish_command_fsm_return_value): New. (finish_command_continuation_free_arg): Delete. (finish_command_fsm_async_reply_reason): New. (finish_backward, finish_forward): Change symbol parameter to a finish_command_fsm. Adjust. (finish_command): Create a finish_command_fsm. Adjust. * infrun.c: Include "thread-fsm.h". (clear_proceed_status_thread): Delete the thread's FSM. (infrun_thread_stop_requested_callback): Cancel the thread's execution command. (clean_up_just_stopped_threads_fsms): New function. (fetch_inferior_event): Handle the event_thread's should_stop method saying the command isn't done yet. (process_event_stop_test): Run breakpoint callbacks here. (print_stop_event): Rename to ... (print_stop_location): ... this. (restore_current_uiout_cleanup): New function. (print_stop_event): Reimplement. (normal_stop): No longer notify the end_stepping_range observers here handle "step N" nor "finish" here. No longer call print_stop_event here. * infrun.h (struct return_value_info): Forward declare. (print_return_value): Declare. (print_stop_event): Change prototype. * thread-fsm.c: New file. * thread-fsm.h: New file. * thread.c: Include "thread-fsm.h". (thread_cancel_execution_command): New function. (clear_thread_inferior_resources): Call it. * cli/cli-interp.c (cli_on_normal_stop): New function. (cli_interpreter_init): Install cli_on_normal_stop as normal_stop observer. * mi/mi-interp.c: Include "thread-fsm.h". (restore_current_uiout_cleanup): Delete. (mi_on_normal_stop): If the thread has an FSM associated, and it finished, ask it for the async-reply-reason to print. Always call print_stop_event here, regardless of the top-level interpreter. Check bpstat_what to tell whether an asynchronous breakpoint hit triggered. * tui/tui-interp.c (tui_on_normal_stop): New function. (tui_init): Install tui_on_normal_stop as normal_stop observer. gdb/testsuite/ChangeLog: 2015-09-09 Pedro Alves <palves@redhat.com> * gdb.mi/mi-cli.exp: Add CLI finish tests.
Diffstat (limited to 'gdb/thread-fsm.h')
-rw-r--r--gdb/thread-fsm.h98
1 files changed, 98 insertions, 0 deletions
diff --git a/gdb/thread-fsm.h b/gdb/thread-fsm.h
new file mode 100644
index 00000000000..031684b27a1
--- /dev/null
+++ b/gdb/thread-fsm.h
@@ -0,0 +1,98 @@
+/* Thread command's finish-state machine, for GDB, the GNU debugger.
+ Copyright (C) 2015 Free Software Foundation, Inc.
+
+ This file is part of GDB.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#ifndef THREAD_FSM_H
+#define THREAD_FSM_H
+
+#include "mi/mi-common.h" /* For enum async_reply_reason. */
+
+struct return_value_info;
+struct thread_fsm_ops;
+
+/* A thread finite-state machine structure contains the necessary info
+ and callbacks to manage the state machine protocol of a thread's
+ execution command. */
+
+struct thread_fsm
+{
+ /* Pointer of the virtual table of methods. */
+ struct thread_fsm_ops *ops;
+
+ /* Whether the FSM is done successfully. */
+ int finished;
+};
+
+/* The virtual table of a thread_fsm. */
+
+struct thread_fsm_ops
+{
+ /* The destructor. This should simply free heap allocated data
+ structures. Cleaning up target resources (like, e.g.,
+ breakpoints) should be done in the clean_up method. */
+ void (*dtor) (struct thread_fsm *self);
+
+ /* Called to clean up target resources after the FSM. E.g., if the
+ FSM created internal breakpoints, this is where they should be
+ deleted. */
+ void (*clean_up) (struct thread_fsm *self);
+
+ /* Called after handle_inferior_event decides the target is done
+ (that is, after stop_waiting). The FSM is given a chance to
+ decide whether the command is done and thus the target should
+ stop, or whether there's still more to do and thus the thread
+ should be re-resumed. This is a good place to cache target data
+ too. For example, the "finish" command saves the just-finished
+ function's return value here. */
+ int (*should_stop) (struct thread_fsm *self);
+
+ /* If this FSM saved a function's return value, you can use this
+ method to retrieve it. Otherwise, this returns NULL. */
+ struct return_value_info *(*return_value) (struct thread_fsm *self);
+
+ /* The async_reply_reason that is broadcast to MI clients if this
+ FSM finishes successfully. */
+ enum async_reply_reason (*async_reply_reason) (struct thread_fsm *self);
+};
+/* Initialize FSM. */
+extern void thread_fsm_ctor (struct thread_fsm *fsm,
+ struct thread_fsm_ops *ops);
+
+/* Calls the FSM's dtor method, and then frees FSM. */
+extern void thread_fsm_delete (struct thread_fsm *fsm);
+
+/* Calls the FSM's clean_up method. */
+extern void thread_fsm_clean_up (struct thread_fsm *fsm);
+
+/* Calls the FSM's should_stop method. */
+extern int thread_fsm_should_stop (struct thread_fsm *fsm);
+
+/* Calls the FSM's return_value method. */
+extern struct return_value_info *
+ thread_fsm_return_value (struct thread_fsm *fsm);
+
+/* Marks the FSM as completed successfully. */
+extern void thread_fsm_set_finished (struct thread_fsm *fsm);
+
+/* Returns true if the FSM completed successfully. */
+extern int thread_fsm_finished_p (struct thread_fsm *fsm);
+
+/* Calls the FSM's reply_reason method. */
+extern enum async_reply_reason
+ thread_fsm_async_reply_reason (struct thread_fsm *fsm);
+
+#endif /* THREAD_FSM_H */