2019-02-07 Tom Tromey <tom@tromey.com>
+ * 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 <tom@tromey.com>
+
* yy-remap.h: Add include guard.
* xtensa-tdep.h: Add include guard.
* xcoffread.h: Rename include guard.
test-target.c \
thread.c \
thread-iter.c \
- thread-fsm.c \
tid-parse.c \
top.c \
tracefile.c \
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;
}
struct frame_id caller_frame_id;
int thread;
struct thread_info *tp;
- struct until_break_fsm *sm;
clear_proceed_status (0);
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 ();
== 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;
}
/* 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.
/* 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 ();
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,
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;
/* 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 ();
/* 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;
}
}
/* 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;
/* 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. */
/* 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);
/* 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);
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;
}
}
/* Done. */
- thread_fsm_set_finished (&sm->thread_fsm);
+ sm->set_finished ();
return 1;
}
/* 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);
}
/* 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;
}
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);
/* 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"));
{
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);
{
/* 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;
sm->breakpoint = set_momentary_breakpoint (gdbarch, sal,
get_stack_frame_id (frame),
- bp_finish).release ();
+ bp_finish);
/* set_momentary_breakpoint invalidates FRAME. */
frame = NULL;
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. */
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;
{
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)
{
continue;
switch_to_thread (thr);
- thread_fsm_clean_up (thr->thread_fsm, thr);
+ thr->thread_fsm->clean_up (thr);
}
if (ecs->event_thread != NULL)
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)
}
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)
{
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);
}
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);
+++ /dev/null
-/* 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 <http://www.gnu.org/licenses/>. */
-
-#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;
-}
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
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 */
{
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;
}
}