From 46e3ed7ff94dc2d65f3d937d483c459b4cee6a0a Mon Sep 17 00:00:00 2001 From: Tom Tromey Date: Wed, 2 Jan 2019 14:35:57 -0700 Subject: [PATCH] C++-ify struct thread_fsm This C++-ifies struct thread_fsm, replacing the "ops" structure with virtual methods, and changing all the implementations to derive from thread_fsm. gdb/ChangeLog 2019-02-07 Tom Tromey * thread.c (thread_cancel_execution_command): Update. * thread-fsm.h (struct thread_fsm): Add constructor, destructor, methods. (struct thread_fsm_ops): Remove. (thread_fsm_ctor, thread_fsm_delete, thread_fsm_clean_up) (thread_fsm_should_stop, thread_fsm_return_value) (thread_fsm_set_finished, thread_fsm_finished_p) (thread_fsm_async_reply_reason, thread_fsm_should_notify_stop): Don't declare. * mi/mi-interp.c (mi_on_normal_stop_1): Update. * infrun.c (clear_proceed_status_thread) (clean_up_just_stopped_threads_fsms, fetch_inferior_event) (print_stop_event): Update. * infcmd.c (struct step_command_fsm): Inherit from thread_fsm. Add constructor. (step_command_fsm_ops): Remove. (new_step_command_fsm): Remove. (step_1): Update. (step_command_fsm::should_stop): Rename from step_command_fsm_should_stop. (step_command_fsm::clean_up): Rename from step_command_fsm_clean_up. (step_command_fsm::do_async_reply_reason): Rename from step_command_fsm_async_reply_reason. (struct until_next_fsm): Inherit from thread_fsm. Add constructor. (until_next_fsm_ops): Remove. (new_until_next_fsm): Remove. (until_next_fsm::should_stop): Rename from until_next_fsm_should_stop. (until_next_fsm::clean_up): Rename from until_next_fsm_clean_up. (until_next_fsm::do_async_reply_reason): Rename from until_next_fsm_async_reply_reason. (struct finish_command_fsm): Inherit from thread_fsm. Add constructor. Change type of breakpoint. (finish_command_fsm_ops): Remove. (new_finish_command_fsm): Remove. (finish_command_fsm::should_stop): Rename from finish_command_fsm_should_stop. (finish_command_fsm::clean_up): Rename from finish_command_fsm_clean_up. (finish_command_fsm::return_value): Rename from finish_command_fsm_return_value. (finish_command_fsm::do_async_reply_reason): Rename from finish_command_fsm_async_reply_reason. (finish_command): Update. * infcall.c (struct call_thread_fsm): Inherit from thread_fsm. Add constructor. (call_thread_fsm_ops): Remove. (call_thread_fsm::call_thread_fsm): Rename from new_call_thread_fsm. (call_thread_fsm::should_stop): Rename from call_thread_fsm_should_stop. (call_thread_fsm::should_notify_stop): Rename from call_thread_fsm_should_notify_stop. (run_inferior_call, call_function_by_hand_dummy): Update. * cli/cli-interp.c (should_print_stop_to_console): Update. * breakpoint.c (struct until_break_fsm): Inherit from thread_fsm. Add constructor. Change type of location_breakpoint, caller_breakpoint. (until_break_fsm_ops): Remove. (new_until_break_fsm): Remove. (until_break_fsm::should_stop): Rename from until_break_fsm_should_stop. (until_break_fsm::clean_up): Rename from until_break_fsm_clean_up. (until_break_fsm::do_async_reply_reason): Rename from until_break_fsm_async_reply_reason. (until_break_command): Update. * thread-fsm.c: Remove. * Makefile.in (COMMON_SFILES): Remove thread-fsm.c. --- gdb/ChangeLog | 74 ++++++++++++++++ gdb/Makefile.in | 1 - gdb/breakpoint.c | 108 +++++++--------------- gdb/cli/cli-interp.c | 2 +- gdb/infcall.c | 101 +++++++++------------ gdb/infcmd.c | 246 ++++++++++++++++----------------------------------- gdb/infrun.c | 20 ++--- gdb/mi/mi-interp.c | 4 +- gdb/thread-fsm.c | 109 ----------------------- gdb/thread-fsm.h | 106 +++++++++++----------- gdb/thread.c | 4 +- 11 files changed, 289 insertions(+), 486 deletions(-) delete mode 100644 gdb/thread-fsm.c diff --git a/gdb/ChangeLog b/gdb/ChangeLog index c17d05a..a714d50 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,5 +1,79 @@ 2019-02-07 Tom Tromey + * thread.c (thread_cancel_execution_command): Update. + * thread-fsm.h (struct thread_fsm): Add constructor, destructor, + methods. + (struct thread_fsm_ops): Remove. + (thread_fsm_ctor, thread_fsm_delete, thread_fsm_clean_up) + (thread_fsm_should_stop, thread_fsm_return_value) + (thread_fsm_set_finished, thread_fsm_finished_p) + (thread_fsm_async_reply_reason, thread_fsm_should_notify_stop): + Don't declare. + * mi/mi-interp.c (mi_on_normal_stop_1): Update. + * infrun.c (clear_proceed_status_thread) + (clean_up_just_stopped_threads_fsms, fetch_inferior_event) + (print_stop_event): Update. + * infcmd.c (struct step_command_fsm): Inherit from thread_fsm. + Add constructor. + (step_command_fsm_ops): Remove. + (new_step_command_fsm): Remove. + (step_1): Update. + (step_command_fsm::should_stop): Rename from + step_command_fsm_should_stop. + (step_command_fsm::clean_up): Rename from + step_command_fsm_clean_up. + (step_command_fsm::do_async_reply_reason): Rename from + step_command_fsm_async_reply_reason. + (struct until_next_fsm): Inherit from thread_fsm. Add + constructor. + (until_next_fsm_ops): Remove. + (new_until_next_fsm): Remove. + (until_next_fsm::should_stop): Rename from + until_next_fsm_should_stop. + (until_next_fsm::clean_up): Rename from until_next_fsm_clean_up. + (until_next_fsm::do_async_reply_reason): Rename from + until_next_fsm_async_reply_reason. + (struct finish_command_fsm): Inherit from thread_fsm. Add + constructor. Change type of breakpoint. + (finish_command_fsm_ops): Remove. + (new_finish_command_fsm): Remove. + (finish_command_fsm::should_stop): Rename from + finish_command_fsm_should_stop. + (finish_command_fsm::clean_up): Rename from + finish_command_fsm_clean_up. + (finish_command_fsm::return_value): Rename from + finish_command_fsm_return_value. + (finish_command_fsm::do_async_reply_reason): Rename from + finish_command_fsm_async_reply_reason. + (finish_command): Update. + * infcall.c (struct call_thread_fsm): Inherit from thread_fsm. + Add constructor. + (call_thread_fsm_ops): Remove. + (call_thread_fsm::call_thread_fsm): Rename from + new_call_thread_fsm. + (call_thread_fsm::should_stop): Rename from + call_thread_fsm_should_stop. + (call_thread_fsm::should_notify_stop): Rename from + call_thread_fsm_should_notify_stop. + (run_inferior_call, call_function_by_hand_dummy): Update. + * cli/cli-interp.c (should_print_stop_to_console): Update. + * breakpoint.c (struct until_break_fsm): Inherit from thread_fsm. + Add constructor. Change type of location_breakpoint, + caller_breakpoint. + (until_break_fsm_ops): Remove. + (new_until_break_fsm): Remove. + (until_break_fsm::should_stop): Rename from + until_break_fsm_should_stop. + (until_break_fsm::clean_up): Rename from + until_break_fsm_clean_up. + (until_break_fsm::do_async_reply_reason): Rename from + until_break_fsm_async_reply_reason. + (until_break_command): Update. + * thread-fsm.c: Remove. + * Makefile.in (COMMON_SFILES): Remove thread-fsm.c. + +2019-02-07 Tom Tromey + * yy-remap.h: Add include guard. * xtensa-tdep.h: Add include guard. * xcoffread.h: Rename include guard. diff --git a/gdb/Makefile.in b/gdb/Makefile.in index 72ca855..cb5b740 100644 --- a/gdb/Makefile.in +++ b/gdb/Makefile.in @@ -1122,7 +1122,6 @@ COMMON_SFILES = \ test-target.c \ thread.c \ thread-iter.c \ - thread-fsm.c \ tid-parse.c \ top.c \ tracefile.c \ diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c index b2096c5..bd05707 100644 --- a/gdb/breakpoint.c +++ b/gdb/breakpoint.c @@ -10950,106 +10950,66 @@ awatch_command (const char *arg, int from_tty) in infcmd.c. Here because it uses the mechanisms of breakpoints. */ -struct until_break_fsm +struct until_break_fsm : public thread_fsm { - /* The base class. */ - struct thread_fsm thread_fsm; - - /* The thread that as current when the command was executed. */ + /* The thread that was current when the command was executed. */ int thread; /* The breakpoint set at the destination location. */ - struct breakpoint *location_breakpoint; + breakpoint_up location_breakpoint; /* Breakpoint set at the return address in the caller frame. May be NULL. */ - struct breakpoint *caller_breakpoint; -}; - -static void until_break_fsm_clean_up (struct thread_fsm *self, - struct thread_info *thread); -static int until_break_fsm_should_stop (struct thread_fsm *self, - struct thread_info *thread); -static enum async_reply_reason - until_break_fsm_async_reply_reason (struct thread_fsm *self); + breakpoint_up caller_breakpoint; -/* until_break_fsm's vtable. */ + until_break_fsm (struct interp *cmd_interp, int thread, + breakpoint_up &&location_breakpoint, + breakpoint_up &&caller_breakpoint) + : thread_fsm (cmd_interp), + thread (thread), + location_breakpoint (std::move (location_breakpoint)), + caller_breakpoint (std::move (caller_breakpoint)) + { + } -static struct thread_fsm_ops until_break_fsm_ops = -{ - NULL, /* dtor */ - until_break_fsm_clean_up, - until_break_fsm_should_stop, - NULL, /* return_value */ - until_break_fsm_async_reply_reason, + void clean_up (struct thread_info *thread) override; + bool should_stop (struct thread_info *thread) override; + enum async_reply_reason do_async_reply_reason () override; }; -/* Allocate a new until_break_command_fsm. */ - -static struct until_break_fsm * -new_until_break_fsm (struct interp *cmd_interp, int thread, - breakpoint_up &&location_breakpoint, - breakpoint_up &&caller_breakpoint) -{ - struct until_break_fsm *sm; - - sm = XCNEW (struct until_break_fsm); - thread_fsm_ctor (&sm->thread_fsm, &until_break_fsm_ops, cmd_interp); - - sm->thread = thread; - sm->location_breakpoint = location_breakpoint.release (); - sm->caller_breakpoint = caller_breakpoint.release (); - - return sm; -} - /* Implementation of the 'should_stop' FSM method for the until(location)/advance commands. */ -static int -until_break_fsm_should_stop (struct thread_fsm *self, - struct thread_info *tp) +bool +until_break_fsm::should_stop (struct thread_info *tp) { - struct until_break_fsm *sm = (struct until_break_fsm *) self; - if (bpstat_find_breakpoint (tp->control.stop_bpstat, - sm->location_breakpoint) != NULL - || (sm->caller_breakpoint != NULL + location_breakpoint.get ()) != NULL + || (caller_breakpoint != NULL && bpstat_find_breakpoint (tp->control.stop_bpstat, - sm->caller_breakpoint) != NULL)) - thread_fsm_set_finished (self); + caller_breakpoint.get ()) != NULL)) + set_finished (); - return 1; + return true; } /* Implementation of the 'clean_up' FSM method for the until(location)/advance commands. */ -static void -until_break_fsm_clean_up (struct thread_fsm *self, - struct thread_info *thread) +void +until_break_fsm::clean_up (struct thread_info *) { - struct until_break_fsm *sm = (struct until_break_fsm *) self; - /* Clean up our temporary breakpoints. */ - if (sm->location_breakpoint != NULL) - { - delete_breakpoint (sm->location_breakpoint); - sm->location_breakpoint = NULL; - } - if (sm->caller_breakpoint != NULL) - { - delete_breakpoint (sm->caller_breakpoint); - sm->caller_breakpoint = NULL; - } - delete_longjmp_breakpoint (sm->thread); + location_breakpoint.reset (); + caller_breakpoint.reset (); + delete_longjmp_breakpoint (thread); } /* Implementation of the 'async_reply_reason' FSM method for the until(location)/advance commands. */ -static enum async_reply_reason -until_break_fsm_async_reply_reason (struct thread_fsm *self) +enum async_reply_reason +until_break_fsm::do_async_reply_reason () { return EXEC_ASYNC_LOCATION_REACHED; } @@ -11063,7 +11023,6 @@ until_break_command (const char *arg, int from_tty, int anywhere) struct frame_id caller_frame_id; int thread; struct thread_info *tp; - struct until_break_fsm *sm; clear_proceed_status (0); @@ -11142,10 +11101,9 @@ until_break_command (const char *arg, int from_tty, int anywhere) location_breakpoint = set_momentary_breakpoint (frame_gdbarch, sal, stack_frame_id, bp_until); - sm = new_until_break_fsm (command_interp (), tp->global_num, - std::move (location_breakpoint), - std::move (caller_breakpoint)); - tp->thread_fsm = &sm->thread_fsm; + tp->thread_fsm = new until_break_fsm (command_interp (), tp->global_num, + std::move (location_breakpoint), + std::move (caller_breakpoint)); if (lj_deleter) lj_deleter->release (); diff --git a/gdb/cli/cli-interp.c b/gdb/cli/cli-interp.c index 0299f3d..088f4f1 100644 --- a/gdb/cli/cli-interp.c +++ b/gdb/cli/cli-interp.c @@ -113,7 +113,7 @@ should_print_stop_to_console (struct interp *console_interp, == BPSTAT_WHAT_STOP_NOISY) || tp->thread_fsm == NULL || tp->thread_fsm->command_interp == console_interp - || !thread_fsm_finished_p (tp->thread_fsm)) + || !tp->thread_fsm->finished_p ()) return 1; return 0; } diff --git a/gdb/infcall.c b/gdb/infcall.c index 6ca479a..e58ba84 100644 --- a/gdb/infcall.c +++ b/gdb/infcall.c @@ -470,106 +470,87 @@ get_call_return_value (struct call_return_meta_info *ri) /* Data for the FSM that manages an infcall. It's main job is to record the called function's return value. */ -struct call_thread_fsm +struct call_thread_fsm : public thread_fsm { - /* The base class. */ - struct thread_fsm thread_fsm; - /* All the info necessary to be able to extract the return value. */ struct call_return_meta_info return_meta_info; /* The called function's return value. This is extracted from the target before the dummy frame is popped. */ - struct value *return_value; + struct value *return_value = nullptr; /* The top level that started the infcall (and is synchronously waiting for it to end). */ struct ui *waiting_ui; -}; -static int call_thread_fsm_should_stop (struct thread_fsm *self, - struct thread_info *thread); -static int call_thread_fsm_should_notify_stop (struct thread_fsm *self); + call_thread_fsm (struct ui *waiting_ui, struct interp *cmd_interp, + struct gdbarch *gdbarch, struct value *function, + struct type *value_type, + int struct_return_p, CORE_ADDR struct_addr); -/* call_thread_fsm's vtable. */ + bool should_stop (struct thread_info *thread) override; -static struct thread_fsm_ops call_thread_fsm_ops = -{ - NULL, /*dtor */ - NULL, /* clean_up */ - call_thread_fsm_should_stop, - NULL, /* return_value */ - NULL, /* async_reply_reason*/ - call_thread_fsm_should_notify_stop, + bool should_notify_stop () override; }; /* Allocate a new call_thread_fsm object. */ -static struct call_thread_fsm * -new_call_thread_fsm (struct ui *waiting_ui, struct interp *cmd_interp, - struct gdbarch *gdbarch, struct value *function, - struct type *value_type, - int struct_return_p, CORE_ADDR struct_addr) +call_thread_fsm::call_thread_fsm (struct ui *waiting_ui, + struct interp *cmd_interp, + struct gdbarch *gdbarch, + struct value *function, + struct type *value_type, + int struct_return_p, CORE_ADDR struct_addr) + : thread_fsm (cmd_interp), + waiting_ui (waiting_ui) { - struct call_thread_fsm *sm; - - sm = XCNEW (struct call_thread_fsm); - thread_fsm_ctor (&sm->thread_fsm, &call_thread_fsm_ops, cmd_interp); - - sm->return_meta_info.gdbarch = gdbarch; - sm->return_meta_info.function = function; - sm->return_meta_info.value_type = value_type; - sm->return_meta_info.struct_return_p = struct_return_p; - sm->return_meta_info.struct_addr = struct_addr; - - sm->waiting_ui = waiting_ui; - - return sm; + return_meta_info.gdbarch = gdbarch; + return_meta_info.function = function; + return_meta_info.value_type = value_type; + return_meta_info.struct_return_p = struct_return_p; + return_meta_info.struct_addr = struct_addr; } /* Implementation of should_stop method for infcalls. */ -static int -call_thread_fsm_should_stop (struct thread_fsm *self, - struct thread_info *thread) +bool +call_thread_fsm::should_stop (struct thread_info *thread) { - struct call_thread_fsm *f = (struct call_thread_fsm *) self; - if (stop_stack_dummy == STOP_STACK_DUMMY) { /* Done. */ - thread_fsm_set_finished (self); + set_finished (); /* Stash the return value before the dummy frame is popped and registers are restored to what they were before the call.. */ - f->return_value = get_call_return_value (&f->return_meta_info); + return_value = get_call_return_value (&return_meta_info); /* Break out of wait_sync_command_done. */ - scoped_restore save_ui = make_scoped_restore (¤t_ui, f->waiting_ui); + scoped_restore save_ui = make_scoped_restore (¤t_ui, waiting_ui); target_terminal::ours (); - f->waiting_ui->prompt_state = PROMPT_NEEDED; + waiting_ui->prompt_state = PROMPT_NEEDED; } - return 1; + return true; } /* Implementation of should_notify_stop method for infcalls. */ -static int -call_thread_fsm_should_notify_stop (struct thread_fsm *self) +bool +call_thread_fsm::should_notify_stop () { - if (thread_fsm_finished_p (self)) + if (finished_p ()) { /* Infcall succeeded. Be silent and proceed with evaluating the expression. */ - return 0; + return false; } /* Something wrong happened. E.g., an unexpected breakpoint triggered, or a signal was intercepted. Notify the stop. */ - return 1; + return true; } /* Subroutine of call_function_by_hand to simplify it. @@ -606,7 +587,7 @@ run_inferior_call (struct call_thread_fsm *sm, /* Associate the FSM with the thread after clear_proceed_status (otherwise it'd clear this FSM), and before anything throws, so we don't leak it (and any resources it manages). */ - call_thread->thread_fsm = &sm->thread_fsm; + call_thread->thread_fsm = sm; disable_watchpoints_before_interactive_call_start (); @@ -1139,7 +1120,7 @@ call_function_by_hand_dummy (struct value *function, not report the stop to the user, and captures the return value before the dummy frame is popped. run_inferior_call registers it with the thread ASAP. */ - sm = new_call_thread_fsm (current_ui, command_interp (), + sm = new call_thread_fsm (current_ui, command_interp (), gdbarch, function, values_type, return_method != return_method_normal, @@ -1152,9 +1133,9 @@ call_function_by_hand_dummy (struct value *function, if (call_thread->state != THREAD_EXITED) { /* The FSM should still be the same. */ - gdb_assert (call_thread->thread_fsm == &sm->thread_fsm); + gdb_assert (call_thread->thread_fsm == sm); - if (thread_fsm_finished_p (call_thread->thread_fsm)) + if (call_thread->thread_fsm->finished_p ()) { struct value *retval; @@ -1170,8 +1151,8 @@ call_function_by_hand_dummy (struct value *function, /* Clean up / destroy the call FSM, and restore the original one. */ - thread_fsm_clean_up (call_thread->thread_fsm, call_thread.get ()); - thread_fsm_delete (call_thread->thread_fsm); + call_thread->thread_fsm->clean_up (call_thread.get ()); + delete call_thread->thread_fsm; call_thread->thread_fsm = saved_sm; maybe_remove_breakpoints (); @@ -1182,8 +1163,8 @@ call_function_by_hand_dummy (struct value *function, /* Didn't complete. Clean up / destroy the call FSM, and restore the previous state machine, and handle the error. */ - thread_fsm_clean_up (call_thread->thread_fsm, call_thread.get ()); - thread_fsm_delete (call_thread->thread_fsm); + call_thread->thread_fsm->clean_up (call_thread.get ()); + delete call_thread->thread_fsm; call_thread->thread_fsm = saved_sm; } } diff --git a/gdb/infcmd.c b/gdb/infcmd.c index dc533bf..c5977c4 100644 --- a/gdb/infcmd.c +++ b/gdb/infcmd.c @@ -950,11 +950,8 @@ nexti_command (const char *count_string, int from_tty) /* Data for the FSM that manages the step/next/stepi/nexti commands. */ -struct step_command_fsm +struct step_command_fsm : public thread_fsm { - /* The base class. */ - struct thread_fsm thread_fsm; - /* How many steps left in a "step N"-like command. */ int count; @@ -963,39 +960,17 @@ struct step_command_fsm /* If true, this is a stepi/nexti, otherwise a step/step. */ int single_inst; -}; -static void step_command_fsm_clean_up (struct thread_fsm *self, - struct thread_info *thread); -static int step_command_fsm_should_stop (struct thread_fsm *self, - struct thread_info *thread); -static enum async_reply_reason - step_command_fsm_async_reply_reason (struct thread_fsm *self); - -/* step_command_fsm's vtable. */ + explicit step_command_fsm (struct interp *cmd_interp) + : thread_fsm (cmd_interp) + { + } -static struct thread_fsm_ops step_command_fsm_ops = -{ - NULL, - step_command_fsm_clean_up, - step_command_fsm_should_stop, - NULL, /* return_value */ - step_command_fsm_async_reply_reason, + void clean_up (struct thread_info *thread) override; + bool should_stop (struct thread_info *thread) override; + enum async_reply_reason do_async_reply_reason () override; }; -/* Allocate a new step_command_fsm. */ - -static struct step_command_fsm * -new_step_command_fsm (struct interp *cmd_interp) -{ - struct step_command_fsm *sm; - - sm = XCNEW (struct step_command_fsm); - thread_fsm_ctor (&sm->thread_fsm, &step_command_fsm_ops, cmd_interp); - - return sm; -} - /* Prepare for a step/next/etc. command. Any target resource allocated here is undone in the FSM's clean_up method. */ @@ -1043,8 +1018,8 @@ step_1 (int skip_subroutines, int single_inst, const char *count_string) /* Setup the execution command state machine to handle all the COUNT steps. */ thr = inferior_thread (); - step_sm = new_step_command_fsm (command_interp ()); - thr->thread_fsm = &step_sm->thread_fsm; + step_sm = new step_command_fsm (command_interp ()); + thr->thread_fsm = step_sm; step_command_fsm_prepare (step_sm, skip_subroutines, single_inst, count, thr); @@ -1061,7 +1036,7 @@ step_1 (int skip_subroutines, int single_inst, const char *count_string) /* Stepped into an inline frame. Pretend that we've stopped. */ - thread_fsm_clean_up (thr->thread_fsm, thr); + thr->thread_fsm->clean_up (thr); proceeded = normal_stop (); if (!proceeded) inferior_event_handler (INF_EXEC_COMPLETE, NULL); @@ -1075,40 +1050,36 @@ step_1 (int skip_subroutines, int single_inst, const char *count_string) return control to the user. If count is > 1, returns false, as we will need to keep going. */ -static int -step_command_fsm_should_stop (struct thread_fsm *self, struct thread_info *tp) +bool +step_command_fsm::should_stop (struct thread_info *tp) { - struct step_command_fsm *sm = (struct step_command_fsm *) self; - if (tp->control.stop_step) { /* There are more steps to make, and we did stop due to ending a stepping range. Do another step. */ - if (--sm->count > 0) - return prepare_one_step (sm); + if (--count > 0) + return prepare_one_step (this); - thread_fsm_set_finished (self); + set_finished (); } - return 1; + return true; } /* Implementation of the 'clean_up' FSM method for stepping commands. */ -static void -step_command_fsm_clean_up (struct thread_fsm *self, struct thread_info *thread) +void +step_command_fsm::clean_up (struct thread_info *thread) { - struct step_command_fsm *sm = (struct step_command_fsm *) self; - - if (!sm->single_inst || sm->skip_subroutines) + if (!single_inst || skip_subroutines) delete_longjmp_breakpoint (thread->global_num); } /* Implementation of the 'async_reply_reason' FSM method for stepping commands. */ -static enum async_reply_reason -step_command_fsm_async_reply_reason (struct thread_fsm *self) +enum async_reply_reason +step_command_fsm::do_async_reply_reason () { return EXEC_ASYNC_END_STEPPING_RANGE; } @@ -1198,7 +1169,7 @@ prepare_one_step (struct step_command_fsm *sm) } /* Done. */ - thread_fsm_set_finished (&sm->thread_fsm); + sm->set_finished (); return 1; } @@ -1420,66 +1391,39 @@ queue_signal_command (const char *signum_exp, int from_tty) /* Data for the FSM that manages the until (with no argument) command. */ -struct until_next_fsm +struct until_next_fsm : public thread_fsm { - /* The base class. */ - struct thread_fsm thread_fsm; - /* The thread that as current when the command was executed. */ int thread; -}; - -static int until_next_fsm_should_stop (struct thread_fsm *self, - struct thread_info *thread); -static void until_next_fsm_clean_up (struct thread_fsm *self, - struct thread_info *thread); -static enum async_reply_reason - until_next_fsm_async_reply_reason (struct thread_fsm *self); -/* until_next_fsm's vtable. */ + until_next_fsm (struct interp *cmd_interp, int thread) + : thread_fsm (cmd_interp), + thread (thread) + { + } -static struct thread_fsm_ops until_next_fsm_ops = -{ - NULL, /* dtor */ - until_next_fsm_clean_up, - until_next_fsm_should_stop, - NULL, /* return_value */ - until_next_fsm_async_reply_reason, + bool should_stop (struct thread_info *thread) override; + void clean_up (struct thread_info *thread) override; + enum async_reply_reason do_async_reply_reason () override; }; -/* Allocate a new until_next_fsm. */ - -static struct until_next_fsm * -new_until_next_fsm (struct interp *cmd_interp, int thread) -{ - struct until_next_fsm *sm; - - sm = XCNEW (struct until_next_fsm); - thread_fsm_ctor (&sm->thread_fsm, &until_next_fsm_ops, cmd_interp); - - sm->thread = thread; - - return sm; -} - /* Implementation of the 'should_stop' FSM method for the until (with no arg) command. */ -static int -until_next_fsm_should_stop (struct thread_fsm *self, - struct thread_info *tp) +bool +until_next_fsm::should_stop (struct thread_info *tp) { if (tp->control.stop_step) - thread_fsm_set_finished (self); + set_finished (); - return 1; + return true; } /* Implementation of the 'clean_up' FSM method for the until (with no arg) command. */ -static void -until_next_fsm_clean_up (struct thread_fsm *self, struct thread_info *thread) +void +until_next_fsm::clean_up (struct thread_info *thread) { delete_longjmp_breakpoint (thread->global_num); } @@ -1487,8 +1431,8 @@ until_next_fsm_clean_up (struct thread_fsm *self, struct thread_info *thread) /* Implementation of the 'async_reply_reason' FSM method for the until (with no arg) command. */ -static enum async_reply_reason -until_next_fsm_async_reply_reason (struct thread_fsm *self) +enum async_reply_reason +until_next_fsm::do_async_reply_reason () { return EXEC_ASYNC_END_STEPPING_RANGE; } @@ -1550,8 +1494,8 @@ until_next_command (int from_tty) set_longjmp_breakpoint (tp, get_frame_id (frame)); delete_longjmp_breakpoint_cleanup lj_deleter (thread); - sm = new_until_next_fsm (command_interp (), tp->global_num); - tp->thread_fsm = &sm->thread_fsm; + sm = new until_next_fsm (command_interp (), tp->global_num); + tp->thread_fsm = sm; lj_deleter.release (); proceed ((CORE_ADDR) -1, GDB_SIGNAL_DEFAULT); @@ -1718,77 +1662,48 @@ print_return_value (struct ui_out *uiout, struct return_value_info *rv) /* Data for the FSM that manages the finish command. */ -struct finish_command_fsm +struct finish_command_fsm : public thread_fsm { - /* The base class. */ - struct thread_fsm thread_fsm; - /* The momentary breakpoint set at the function's return address in the caller. */ - struct breakpoint *breakpoint; + breakpoint_up breakpoint; /* The function that we're stepping out of. */ - struct symbol *function; + struct symbol *function = nullptr; /* If the FSM finishes successfully, this stores the function's return value. */ - struct return_value_info return_value; -}; + struct return_value_info return_value_info {}; -static int finish_command_fsm_should_stop (struct thread_fsm *self, - struct thread_info *thread); -static void finish_command_fsm_clean_up (struct thread_fsm *self, - struct thread_info *thread); -static struct return_value_info * - finish_command_fsm_return_value (struct thread_fsm *self); -static enum async_reply_reason - finish_command_fsm_async_reply_reason (struct thread_fsm *self); - -/* finish_command_fsm's vtable. */ - -static struct thread_fsm_ops finish_command_fsm_ops = -{ - NULL, /* dtor */ - finish_command_fsm_clean_up, - finish_command_fsm_should_stop, - finish_command_fsm_return_value, - finish_command_fsm_async_reply_reason, - NULL, /* should_notify_stop */ -}; - -/* Allocate a new finish_command_fsm. */ - -static struct finish_command_fsm * -new_finish_command_fsm (struct interp *cmd_interp) -{ - struct finish_command_fsm *sm; - - sm = XCNEW (struct finish_command_fsm); - thread_fsm_ctor (&sm->thread_fsm, &finish_command_fsm_ops, cmd_interp); + explicit finish_command_fsm (struct interp *cmd_interp) + : thread_fsm (cmd_interp) + { + } - return sm; -} + bool should_stop (struct thread_info *thread) override; + void clean_up (struct thread_info *thread) override; + struct return_value_info *return_value () override; + enum async_reply_reason do_async_reply_reason () override; +}; /* Implementation of the 'should_stop' FSM method for the finish commands. Detects whether the thread stepped out of the function successfully, and if so, captures the function's return value and marks the FSM finished. */ -static int -finish_command_fsm_should_stop (struct thread_fsm *self, - struct thread_info *tp) +bool +finish_command_fsm::should_stop (struct thread_info *tp) { - struct finish_command_fsm *f = (struct finish_command_fsm *) self; - struct return_value_info *rv = &f->return_value; + struct return_value_info *rv = &return_value_info; - if (f->function != NULL + if (function != NULL && bpstat_find_breakpoint (tp->control.stop_bpstat, - f->breakpoint) != NULL) + breakpoint.get ()) != NULL) { /* We're done. */ - thread_fsm_set_finished (self); + set_finished (); - rv->type = TYPE_TARGET_TYPE (SYMBOL_TYPE (f->function)); + rv->type = TYPE_TARGET_TYPE (SYMBOL_TYPE (function)); if (rv->type == NULL) internal_error (__FILE__, __LINE__, _("finish_command: function has no target type")); @@ -1797,7 +1712,7 @@ finish_command_fsm_should_stop (struct thread_fsm *self, { struct value *func; - func = read_var_value (f->function, NULL, get_current_frame ()); + func = read_var_value (function, NULL, get_current_frame ()); rv->value = get_return_value (func, rv->type); if (rv->value != NULL) rv->value_history_index = record_latest_value (rv->value); @@ -1807,45 +1722,36 @@ finish_command_fsm_should_stop (struct thread_fsm *self, { /* Finishing from an inline frame, or reverse finishing. In either case, there's no way to retrieve the return value. */ - thread_fsm_set_finished (self); + set_finished (); } - return 1; + return true; } /* Implementation of the 'clean_up' FSM method for the finish commands. */ -static void -finish_command_fsm_clean_up (struct thread_fsm *self, - struct thread_info *thread) +void +finish_command_fsm::clean_up (struct thread_info *thread) { - struct finish_command_fsm *f = (struct finish_command_fsm *) self; - - if (f->breakpoint != NULL) - { - delete_breakpoint (f->breakpoint); - f->breakpoint = NULL; - } + breakpoint.reset (); delete_longjmp_breakpoint (thread->global_num); } /* Implementation of the 'return_value' FSM method for the finish commands. */ -static struct return_value_info * -finish_command_fsm_return_value (struct thread_fsm *self) +struct return_value_info * +finish_command_fsm::return_value () { - struct finish_command_fsm *f = (struct finish_command_fsm *) self; - - return &f->return_value; + return &return_value_info; } /* Implementation of the 'async_reply_reason' FSM method for the finish commands. */ -static enum async_reply_reason -finish_command_fsm_async_reply_reason (struct thread_fsm *self) +enum async_reply_reason +finish_command_fsm::do_async_reply_reason () { if (execution_direction == EXEC_REVERSE) return EXEC_ASYNC_END_STEPPING_RANGE; @@ -1920,7 +1826,7 @@ finish_forward (struct finish_command_fsm *sm, struct frame_info *frame) sm->breakpoint = set_momentary_breakpoint (gdbarch, sal, get_stack_frame_id (frame), - bp_finish).release (); + bp_finish); /* set_momentary_breakpoint invalidates FRAME. */ frame = NULL; @@ -1990,9 +1896,9 @@ finish_command (const char *arg, int from_tty) tp = inferior_thread (); - sm = new_finish_command_fsm (command_interp ()); + sm = new finish_command_fsm (command_interp ()); - tp->thread_fsm = &sm->thread_fsm; + tp->thread_fsm = sm; /* Finishing from an inline frame is completely different. We don't try to show the "return value" - no way to locate it. */ diff --git a/gdb/infrun.c b/gdb/infrun.c index a66c46c..b32635f 100644 --- a/gdb/infrun.c +++ b/gdb/infrun.c @@ -2710,7 +2710,7 @@ 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); + delete tp->thread_fsm; tp->thread_fsm = NULL; tp->control.trap_expected = 0; @@ -3610,8 +3610,7 @@ clean_up_just_stopped_threads_fsms (struct execution_control_state *ecs) { if (ecs->event_thread != NULL && ecs->event_thread->thread_fsm != NULL) - thread_fsm_clean_up (ecs->event_thread->thread_fsm, - ecs->event_thread); + ecs->event_thread->thread_fsm->clean_up (ecs->event_thread); if (!non_stop) { @@ -3623,7 +3622,7 @@ clean_up_just_stopped_threads_fsms (struct execution_control_state *ecs) continue; switch_to_thread (thr); - thread_fsm_clean_up (thr->thread_fsm, thr); + thr->thread_fsm->clean_up (thr); } if (ecs->event_thread != NULL) @@ -3766,7 +3765,7 @@ fetch_inferior_event (void *client_data) struct thread_fsm *thread_fsm = thr->thread_fsm; if (thread_fsm != NULL) - should_stop = thread_fsm_should_stop (thread_fsm, thr); + should_stop = thread_fsm->should_stop (thr); } if (!should_stop) @@ -3775,16 +3774,13 @@ fetch_inferior_event (void *client_data) } else { - int should_notify_stop = 1; + bool should_notify_stop = true; int proceeded = 0; clean_up_just_stopped_threads_fsms (ecs); if (thr != NULL && thr->thread_fsm != NULL) - { - should_notify_stop - = thread_fsm_should_notify_stop (thr->thread_fsm); - } + should_notify_stop = thr->thread_fsm->should_notify_stop (); if (should_notify_stop) { @@ -7886,11 +7882,11 @@ print_stop_event (struct ui_out *uiout) tp = inferior_thread (); if (tp->thread_fsm != NULL - && thread_fsm_finished_p (tp->thread_fsm)) + && tp->thread_fsm->finished_p ()) { struct return_value_info *rv; - rv = thread_fsm_return_value (tp->thread_fsm); + rv = tp->thread_fsm->return_value (); if (rv != NULL) print_return_value (uiout, rv); } diff --git a/gdb/mi/mi-interp.c b/gdb/mi/mi-interp.c index e45ddfe..3e9f368 100644 --- a/gdb/mi/mi-interp.c +++ b/gdb/mi/mi-interp.c @@ -632,11 +632,11 @@ mi_on_normal_stop_1 (struct bpstats *bs, int print_frame) tp = inferior_thread (); if (tp->thread_fsm != NULL - && thread_fsm_finished_p (tp->thread_fsm)) + && tp->thread_fsm->finished_p ()) { enum async_reply_reason reason; - reason = thread_fsm_async_reply_reason (tp->thread_fsm); + reason = tp->thread_fsm->async_reply_reason (); mi_uiout->field_string ("reason", async_reason_lookup (reason)); } print_stop_event (mi_uiout); diff --git a/gdb/thread-fsm.c b/gdb/thread-fsm.c deleted file mode 100644 index 1f0eed7..0000000 --- a/gdb/thread-fsm.c +++ /dev/null @@ -1,109 +0,0 @@ -/* Thread command's finish-state machine, for GDB, the GNU debugger. - Copyright (C) 2015-2019 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 . */ - -#include "defs.h" -#include "thread-fsm.h" - -/* See thread-fsm.h. */ - -void -thread_fsm_ctor (struct thread_fsm *self, struct thread_fsm_ops *ops, - struct interp *cmd_interp) -{ - self->command_interp = cmd_interp; - self->finished = 0; - self->ops = ops; -} - -/* See thread-fsm.h. */ - -void -thread_fsm_delete (struct thread_fsm *self) -{ - if (self != NULL) - { - if (self->ops->dtor != NULL) - self->ops->dtor (self); - xfree (self); - } -} - -/* See thread-fsm.h. */ - -void -thread_fsm_clean_up (struct thread_fsm *self, struct thread_info *thread) -{ - if (self->ops->clean_up != NULL) - self->ops->clean_up (self, thread); -} - -/* See thread-fsm.h. */ - -int -thread_fsm_should_stop (struct thread_fsm *self, struct thread_info *thread) -{ - return self->ops->should_stop (self, thread); -} - -/* See thread-fsm.h. */ - -struct return_value_info * -thread_fsm_return_value (struct thread_fsm *self) -{ - if (self->ops->return_value != NULL) - return self->ops->return_value (self); - return NULL; -} - -/* See thread-fsm.h. */ - -void -thread_fsm_set_finished (struct thread_fsm *self) -{ - self->finished = 1; -} - -/* See thread-fsm.h. */ - -int -thread_fsm_finished_p (struct thread_fsm *self) -{ - return self->finished; -} - -/* See thread-fsm.h. */ - -enum async_reply_reason -thread_fsm_async_reply_reason (struct thread_fsm *self) -{ - /* If we didn't finish, then the stop reason must come from - elsewhere. E.g., a breakpoint hit or a signal intercepted. */ - gdb_assert (thread_fsm_finished_p (self)); - - return self->ops->async_reply_reason (self); -} - -/* See thread-fsm.h. */ - -int -thread_fsm_should_notify_stop (struct thread_fsm *self) -{ - if (self->ops->should_notify_stop != NULL) - return self->ops->should_notify_stop (self); - return 1; -} diff --git a/gdb/thread-fsm.h b/gdb/thread-fsm.h index 3f63dbd..57837bf 100644 --- a/gdb/thread-fsm.h +++ b/gdb/thread-fsm.h @@ -30,34 +30,24 @@ struct thread_fsm_ops; struct thread_fsm { - /* Pointer of the virtual table of methods. */ - struct thread_fsm_ops *ops; + explicit thread_fsm (struct interp *cmd_interp) + : command_interp (cmd_interp) + { + } - /* Whether the FSM is done successfully. */ - int finished; - - /* The interpreter that issued the execution command that caused - this thread to resume. If the top level interpreter is MI/async, - and the execution command was a CLI command (next/step/etc.), - we'll want to print stop event output to the MI console channel - (the stepped-to line, etc.), as if the user entered the execution - command on a real GDB console. */ - struct interp *command_interp; -}; - -/* 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); + virtual ~thread_fsm () = default; + + DISABLE_COPY_AND_ASSIGN (thread_fsm); /* 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, struct thread_info *thread); + virtual void clean_up (struct thread_info *thread) + { + } /* Called after handle_inferior_event decides the target is done (that is, after stop_waiting). The FSM is given a chance to @@ -66,50 +56,58 @@ struct thread_fsm_ops 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, struct thread_info *thread); + virtual bool should_stop (struct thread_info *thread) = 0; /* 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); + virtual struct return_value_info *return_value () + { + return nullptr; + } + + enum async_reply_reason async_reply_reason () + { + /* If we didn't finish, then the stop reason must come from + elsewhere. E.g., a breakpoint hit or a signal intercepted. */ + gdb_assert (finished_p ()); + return do_async_reply_reason (); + } /* Whether the stop should be notified to the user/frontend. */ - int (*should_notify_stop) (struct thread_fsm *self); -}; -/* Initialize FSM. */ -extern void thread_fsm_ctor (struct thread_fsm *self, - struct thread_fsm_ops *ops, - struct interp *cmd_interp); - -/* 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, - struct thread_info *thread); + virtual bool should_notify_stop () + { + return true; + } -/* Calls the FSM's should_stop method. */ -extern int thread_fsm_should_stop (struct thread_fsm *fsm, - struct thread_info *thread); + void set_finished () + { + finished = true; + } -/* Calls the FSM's return_value method. */ -extern struct return_value_info * - thread_fsm_return_value (struct thread_fsm *fsm); + bool finished_p () const + { + return finished; + } -/* Marks the FSM as completed successfully. */ -extern void thread_fsm_set_finished (struct thread_fsm *fsm); + /* The interpreter that issued the execution command that caused + this thread to resume. If the top level interpreter is MI/async, + and the execution command was a CLI command (next/step/etc.), + we'll want to print stop event output to the MI console channel + (the stepped-to line, etc.), as if the user entered the execution + command on a real GDB console. */ + struct interp *command_interp = nullptr; -/* Returns true if the FSM completed successfully. */ -extern int thread_fsm_finished_p (struct thread_fsm *fsm); +protected: -/* Calls the FSM's reply_reason method. */ -extern enum async_reply_reason - thread_fsm_async_reply_reason (struct thread_fsm *fsm); + /* Whether the FSM is done successfully. */ + bool finished = false; -/* Calls the FSM's should_notify_stop method. */ -extern int thread_fsm_should_notify_stop (struct thread_fsm *self); + /* The async_reply_reason that is broadcast to MI clients if this + FSM finishes successfully. */ + virtual enum async_reply_reason do_async_reply_reason () + { + gdb_assert_not_reached (_("should not call async_reply_reason here")); + } +}; #endif /* THREAD_FSM_H */ diff --git a/gdb/thread.c b/gdb/thread.c index 258fb47..6c23252 100644 --- a/gdb/thread.c +++ b/gdb/thread.c @@ -170,8 +170,8 @@ thread_cancel_execution_command (struct thread_info *thr) { if (thr->thread_fsm != NULL) { - thread_fsm_clean_up (thr->thread_fsm, thr); - thread_fsm_delete (thr->thread_fsm); + thr->thread_fsm->clean_up (thr); + delete thr->thread_fsm; thr->thread_fsm = NULL; } } -- 2.7.4