From patchwork Wed Jan 2 23:28:06 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tom Tromey X-Patchwork-Id: 30950 Received: (qmail 78330 invoked by alias); 2 Jan 2019 23:28:22 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Delivered-To: mailing list gdb-patches@sourceware.org Received: (qmail 78307 invoked by uid 89); 2 Jan 2019 23:28:19 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-26.9 required=5.0 tests=BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, RCVD_IN_DNSWL_NONE, SPF_HELO_PASS, TIME_LIMIT_EXCEEDED autolearn=unavailable version=3.3.2 spammy=proceeded, channel, inherit, ASAP X-HELO: gateway20.websitewelcome.com Received: from gateway20.websitewelcome.com (HELO gateway20.websitewelcome.com) (192.185.60.19) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Wed, 02 Jan 2019 23:28:09 +0000 Received: from cm16.websitewelcome.com (cm16.websitewelcome.com [100.42.49.19]) by gateway20.websitewelcome.com (Postfix) with ESMTP id 04A83400C3969 for ; Wed, 2 Jan 2019 17:28:08 -0600 (CST) Received: from box5379.bluehost.com ([162.241.216.53]) by cmsmtp with SMTP id epvjgjG8e4FKpepvjgBtPU; Wed, 02 Jan 2019 17:28:07 -0600 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=tromey.com; s=default; h=Message-Id:Date:Subject:Cc:To:From:Sender:Reply-To:MIME-Version :Content-Type:Content-Transfer-Encoding:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: In-Reply-To:References:List-Id:List-Help:List-Unsubscribe:List-Subscribe: List-Post:List-Owner:List-Archive; bh=yWfVKQrA4coANEnvzNC6lVIw/gdR/NSZhwbic/JzugI=; b=ah1NE6eFVhcjv6PEU4Ioo3rYrn ragfZ8eB19WJuv5vyrR8FFZb79DbUR0E8UPmR0yqiP7MsNwDzEa/OJ8VJH1XHAe5PXWwkrmbga7eA pfPMxDz+eGpPqlZy5P+U7OQv9; Received: from [50.236.237.38] (port=45586 helo=bapiya.TCHFunNetwork.pvt) by box5379.bluehost.com with esmtpsa (TLSv1.2:ECDHE-RSA-AES256-GCM-SHA384:256) (Exim 4.91) (envelope-from ) id 1gepvj-0011bA-NL; Wed, 02 Jan 2019 17:28:07 -0600 From: Tom Tromey To: gdb-patches@sourceware.org Cc: Tom Tromey Subject: [PATCH] C++-ify struct thread_fsm Date: Wed, 2 Jan 2019 16:28:06 -0700 Message-Id: <20190102232806.14123-1-tom@tromey.com> 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-01-02 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 | 106 ++++++------------- 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, 288 insertions(+), 485 deletions(-) delete mode 100644 gdb/thread-fsm.c diff --git a/gdb/Makefile.in b/gdb/Makefile.in index 215ef7933c..4adedf6e94 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 d54d496972..ffbec7001a 100644 --- a/gdb/breakpoint.c +++ b/gdb/breakpoint.c @@ -10967,106 +10967,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. */ 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; } @@ -11081,7 +11041,6 @@ until_break_command (const char *arg, int from_tty, int anywhere) struct cleanup *old_chain; int thread; struct thread_info *tp; - struct until_break_fsm *sm; clear_proceed_status (0); @@ -11159,10 +11118,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)); discard_cleanups (old_chain); diff --git a/gdb/cli/cli-interp.c b/gdb/cli/cli-interp.c index 8a3f65f088..58cf306c71 100644 --- a/gdb/cli/cli-interp.c +++ b/gdb/cli/cli-interp.c @@ -114,7 +114,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 14b0cbc716..0b2ffa0254 100644 --- a/gdb/infcall.c +++ b/gdb/infcall.c @@ -469,106 +469,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. @@ -605,7 +586,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 (); @@ -1147,7 +1128,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, @@ -1160,9 +1141,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; @@ -1178,8 +1159,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 (); @@ -1191,8 +1172,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 182960ab99..d3d97445ad 100644 --- a/gdb/infcmd.c +++ b/gdb/infcmd.c @@ -957,11 +957,8 @@ delete_longjmp_breakpoint_cleanup (void *arg) /* 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; @@ -970,39 +967,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. */ @@ -1050,8 +1025,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); @@ -1068,7 +1043,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); @@ -1082,40 +1057,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; } @@ -1205,7 +1176,7 @@ prepare_one_step (struct step_command_fsm *sm) } /* Done. */ - thread_fsm_set_finished (&sm->thread_fsm); + sm->set_finished (); return 1; } @@ -1427,66 +1398,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); } @@ -1494,8 +1438,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; } @@ -1558,8 +1502,8 @@ until_next_command (int from_tty) set_longjmp_breakpoint (tp, get_frame_id (frame)); old_chain = make_cleanup (delete_longjmp_breakpoint_cleanup, &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; discard_cleanups (old_chain); proceed ((CORE_ADDR) -1, GDB_SIGNAL_DEFAULT); @@ -1725,77 +1669,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")); @@ -1804,7 +1719,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); @@ -1814,45 +1729,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; @@ -1927,7 +1833,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; @@ -1997,9 +1903,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 00eefabf6e..ee854f5422 100644 --- a/gdb/infrun.c +++ b/gdb/infrun.c @@ -2812,7 +2812,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; @@ -3726,8 +3726,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) { @@ -3739,7 +3738,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) @@ -3880,7 +3879,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) @@ -3889,16 +3888,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) { @@ -8009,11 +8005,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 d4baa48521..2b8e59d899 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 1f0eed71a0..0000000000 --- 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 3f63dbd264..57837bfdfb 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 e026d7d766..e6b56fa08c 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; } }