mirror of
https://sourceware.org/git/binutils-gdb.git
synced 2025-04-24 14:53:34 +08:00
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 <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.
This commit is contained in:
parent
1a5c25988e
commit
46e3ed7ff9
@ -1,3 +1,77 @@
|
||||
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.
|
||||
|
@ -1122,7 +1122,6 @@ COMMON_SFILES = \
|
||||
test-target.c \
|
||||
thread.c \
|
||||
thread-iter.c \
|
||||
thread-fsm.c \
|
||||
tid-parse.c \
|
||||
top.c \
|
||||
tracefile.c \
|
||||
|
112
gdb/breakpoint.c
112
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;
|
||||
breakpoint_up caller_breakpoint;
|
||||
|
||||
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))
|
||||
{
|
||||
}
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
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);
|
||||
|
||||
/* until_break_fsm's vtable. */
|
||||
|
||||
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,
|
||||
};
|
||||
|
||||
/* 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 ();
|
||||
|
@ -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;
|
||||
}
|
||||
|
101
gdb/infcall.c
101
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;
|
||||
}
|
||||
}
|
||||
|
256
gdb/infcmd.c
256
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;
|
||||
|
||||
explicit step_command_fsm (struct interp *cmd_interp)
|
||||
: thread_fsm (cmd_interp)
|
||||
{
|
||||
}
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
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. */
|
||||
|
||||
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,
|
||||
};
|
||||
|
||||
/* 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;
|
||||
|
||||
until_next_fsm (struct interp *cmd_interp, int thread)
|
||||
: thread_fsm (cmd_interp),
|
||||
thread (thread)
|
||||
{
|
||||
}
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
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. */
|
||||
|
||||
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,
|
||||
};
|
||||
|
||||
/* 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 {};
|
||||
|
||||
explicit finish_command_fsm (struct interp *cmd_interp)
|
||||
: thread_fsm (cmd_interp)
|
||||
{
|
||||
}
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
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);
|
||||
|
||||
return sm;
|
||||
}
|
||||
|
||||
/* 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. */
|
||||
|
20
gdb/infrun.c
20
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);
|
||||
}
|
||||
|
@ -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);
|
||||
|
109
gdb/thread-fsm.c
109
gdb/thread-fsm.c
@ -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 <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;
|
||||
}
|
114
gdb/thread-fsm.h
114
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);
|
||||
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. */
|
||||
virtual bool should_notify_stop ()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
void set_finished ()
|
||||
{
|
||||
finished = true;
|
||||
}
|
||||
|
||||
bool finished_p () const
|
||||
{
|
||||
return 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 = nullptr;
|
||||
|
||||
protected:
|
||||
|
||||
/* Whether the FSM is done successfully. */
|
||||
bool finished = false;
|
||||
|
||||
/* 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);
|
||||
|
||||
/* Whether the stop should be notified to the user/frontend. */
|
||||
int (*should_notify_stop) (struct thread_fsm *self);
|
||||
virtual enum async_reply_reason do_async_reply_reason ()
|
||||
{
|
||||
gdb_assert_not_reached (_("should not call async_reply_reason here"));
|
||||
}
|
||||
};
|
||||
/* 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);
|
||||
|
||||
/* Calls the FSM's should_stop method. */
|
||||
extern int thread_fsm_should_stop (struct thread_fsm *fsm,
|
||||
struct thread_info *thread);
|
||||
|
||||
/* Calls the FSM's return_value method. */
|
||||
extern struct return_value_info *
|
||||
thread_fsm_return_value (struct thread_fsm *fsm);
|
||||
|
||||
/* Marks the FSM as completed successfully. */
|
||||
extern void thread_fsm_set_finished (struct thread_fsm *fsm);
|
||||
|
||||
/* Returns true if the FSM completed successfully. */
|
||||
extern int thread_fsm_finished_p (struct thread_fsm *fsm);
|
||||
|
||||
/* Calls the FSM's reply_reason method. */
|
||||
extern enum async_reply_reason
|
||||
thread_fsm_async_reply_reason (struct thread_fsm *fsm);
|
||||
|
||||
/* Calls the FSM's should_notify_stop method. */
|
||||
extern int thread_fsm_should_notify_stop (struct thread_fsm *self);
|
||||
|
||||
#endif /* THREAD_FSM_H */
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user