aboutsummaryrefslogtreecommitdiff
path: root/gdb/infcmd.c
diff options
context:
space:
mode:
authorPedro Alves <palves@redhat.com>2015-09-09 18:23:23 +0100
committerPedro Alves <palves@redhat.com>2015-09-09 18:23:23 +0100
commit0b333c5e7d6c3fc65d37ffa11bd21ba52c4adb25 (patch)
tree3adaca984618d51de1b6dd44a48b83417b01f919 /gdb/infcmd.c
parentea4a7f9986ed4614d8ffb85ccd4fa4bb49b6d420 (diff)
downloadgdb-0b333c5e7d6c3fc65d37ffa11bd21ba52c4adb25.zip
gdb-0b333c5e7d6c3fc65d37ffa11bd21ba52c4adb25.tar.gz
gdb-0b333c5e7d6c3fc65d37ffa11bd21ba52c4adb25.tar.bz2
Merge async and sync code paths some more
This patch makes the execution control code use largely the same mechanisms in both sync- and async-capable targets. This means using continuations and use the event loop to react to target events on sync targets as well. The trick is to immediately mark infrun's event loop source after resume instead of calling wait_for_inferior. Then fetch_inferior_event is adjusted to do a blocking wait on sync targets. Tested on x86_64 Fedora 20, native and gdbserver, with and without "maint set target-async off". gdb/ChangeLog: 2015-09-09 Pedro Alves <palves@redhat.com> * breakpoint.c (bpstat_do_actions_1, until_break_command): Don't check whether the target can async. * inf-loop.c (inferior_event_handler): Only call target_async if the target can async. * infcall.c: Include top.h and interps.h. (run_inferior_call): For the interpreter to sync mode while running the infcall. Call wait_sync_command_done instead of wait_for_inferior plus normal_stop. * infcmd.c (prepare_execution_command): Don't check whether the target can async when running in the foreground. (step_1): Delete synchronous case handling. (step_once): Always install a continuation, even in sync mode. (until_next_command, finish_forward): Don't check whether the target can async. (attach_command_post_wait, notice_new_inferior): Always install a continuation, even in sync mode. * infrun.c (mark_infrun_async_event_handler): New function. (proceed): In sync mode, mark infrun's event source instead of waiting for events here. (fetch_inferior_event): If the target can't async, do a blocking wait. (prepare_to_wait): In sync mode, mark infrun's event source. (infrun_async_inferior_event_handler): No longer bail out if the target can't async. * infrun.h (mark_infrun_async_event_handler): New declaration. * linux-nat.c (linux_nat_wait_1): Remove calls to set_sigint_trap/clear_sigint_trap. (linux_nat_terminal_inferior): No longer check whether the target can async. * mi/mi-interp.c (mi_on_sync_execution_done): Update and simplify comment. (mi_execute_command_input_handler): No longer check whether the target is async. Update and simplify comment. * target.c (default_target_wait): New function. * target.h (struct target_ops) <to_wait>: Now defaults to default_target_wait. (default_target_wait): Declare. * top.c (wait_sync_command_done): New function, factored out from ... (maybe_wait_sync_command_done): ... this. * top.h (wait_sync_command_done): Declare. * target-delegates.c: Regenerate.
Diffstat (limited to 'gdb/infcmd.c')
-rw-r--r--gdb/infcmd.c143
1 files changed, 47 insertions, 96 deletions
diff --git a/gdb/infcmd.c b/gdb/infcmd.c
index bdde49d..ce49777 100644
--- a/gdb/infcmd.c
+++ b/gdb/infcmd.c
@@ -504,13 +504,12 @@ prepare_execution_command (struct target_ops *target, int background)
if (background && !target->to_can_async_p (target))
error (_("Asynchronous execution not supported on this target."));
- /* If we don't get a request of running in the bg, then we need
- to simulate synchronous (fg) execution. */
- if (!background && target->to_can_async_p (target))
+ if (!background)
{
- /* Simulate synchronous execution. Note no cleanup is necessary
- for this. stdin is re-enabled whenever an error reaches the
- top level. */
+ /* If we get a request for running in the fg, then we need to
+ simulate synchronous (fg) execution. Note no cleanup is
+ necessary for this. stdin is re-enabled whenever an error
+ reaches the top level. */
async_disable_stdin ();
}
}
@@ -937,44 +936,15 @@ step_1 (int skip_subroutines, int single_inst, char *count_string)
make_cleanup (delete_longjmp_breakpoint_cleanup, &thread);
}
- /* In synchronous case, all is well; each step_once call will step once. */
- if (!target_can_async_p ())
- {
- for (; count > 0; count--)
- {
- step_once (skip_subroutines, single_inst, count, thread);
-
- if (!target_has_execution)
- break;
- else
- {
- struct thread_info *tp = inferior_thread ();
+ /* Do only one step for now, before returning control to the event
+ loop. Let the continuation figure out how many other steps we
+ need to do, and handle them one at the time, through
+ step_once. */
+ step_once (skip_subroutines, single_inst, count, thread);
- if (!tp->control.stop_step || !tp->step_multi)
- {
- /* If we stopped for some reason that is not stepping
- there are no further steps to make. */
- tp->step_multi = 0;
- break;
- }
- }
- }
-
- do_cleanups (cleanups);
- }
- else
- {
- /* In the case of an asynchronous target things get complicated;
- do only one step for now, before returning control to the
- event loop. Let the continuation figure out how many other
- steps we need to do, and handle them one at the time, through
- step_once. */
- step_once (skip_subroutines, single_inst, count, thread);
-
- /* We are running, and the continuation is installed. It will
- disable the longjmp breakpoint as appropriate. */
- discard_cleanups (cleanups);
- }
+ /* We are running, and the continuation is installed. It will
+ disable the longjmp breakpoint as appropriate. */
+ discard_cleanups (cleanups);
}
struct step_1_continuation_args
@@ -1033,6 +1003,7 @@ step_once (int skip_subroutines, int single_inst, int count, int thread)
if (count > 0)
{
+ struct step_1_continuation_args *args;
/* Don't assume THREAD is a valid thread id. It is set to -1 if
the longjmp breakpoint was not required. Use the
INFERIOR_PTID thread instead, which is the same thread when
@@ -1116,21 +1087,15 @@ step_once (int skip_subroutines, int single_inst, int count, int thread)
tp->control.stepping_command = 1;
proceed ((CORE_ADDR) -1, GDB_SIGNAL_DEFAULT);
- /* For async targets, register a continuation to do any
- additional steps. For sync targets, the caller will handle
- further stepping. */
- if (target_can_async_p ())
- {
- struct step_1_continuation_args *args =
- XNEW (struct step_1_continuation_args);
-
- args->skip_subroutines = skip_subroutines;
- args->single_inst = single_inst;
- args->count = count;
- args->thread = thread;
+ /* Register a continuation to do any additional steps. */
+ args = XNEW (struct step_1_continuation_args);
+ args = xmalloc (sizeof (*args));
+ args->skip_subroutines = skip_subroutines;
+ args->single_inst = single_inst;
+ args->count = count;
+ args->thread = thread;
- add_intermediate_continuation (tp, step_1_continuation, args, xfree);
- }
+ add_intermediate_continuation (tp, step_1_continuation, args, xfree);
}
}
@@ -1442,7 +1407,7 @@ until_next_command (int from_tty)
proceed ((CORE_ADDR) -1, GDB_SIGNAL_DEFAULT);
- if (target_can_async_p () && is_running (inferior_ptid))
+ if (is_running (inferior_ptid))
{
struct until_next_continuation_args *cont_args;
@@ -1801,8 +1766,6 @@ finish_forward (struct symbol *function, struct frame_info *frame)
proceed ((CORE_ADDR) -1, GDB_SIGNAL_DEFAULT);
discard_cleanups (old_chain);
- if (!target_can_async_p ())
- do_all_continuations (0);
}
/* "finish": Set a temporary breakpoint at the place the selected
@@ -2532,8 +2495,7 @@ attach_command_post_wait (char *args, int from_tty, int async_exec)
/* The user requested a plain `attach', so be sure to leave
the inferior stopped. */
- if (target_can_async_p ())
- async_enable_stdin ();
+ async_enable_stdin ();
/* At least the current thread is already stopped. */
@@ -2663,6 +2625,7 @@ attach_command (char *args, int from_tty)
E.g. Mach 3 or GNU hurd. */
if (!target_attach_no_wait)
{
+ struct attach_command_continuation_args *a;
struct inferior *inferior = current_inferior ();
/* Careful here. See comments in inferior.h. Basically some
@@ -2672,25 +2635,19 @@ attach_command (char *args, int from_tty)
STOP_QUIETLY_NO_SIGSTOP is for. */
inferior->control.stop_soon = STOP_QUIETLY_NO_SIGSTOP;
- if (target_can_async_p ())
- {
- /* sync_execution mode. Wait for stop. */
- struct attach_command_continuation_args *a;
-
- a = XNEW (struct attach_command_continuation_args);
- a->args = xstrdup (args);
- a->from_tty = from_tty;
- a->async_exec = async_exec;
- add_inferior_continuation (attach_command_continuation, a,
- attach_command_continuation_free_args);
-
- /* Done with ARGS. */
- do_cleanups (args_chain);
-
- return;
- }
-
- wait_for_inferior ();
+ /* sync_execution mode. Wait for stop. */
+ a = XNEW (struct attach_command_continuation_args);
+ a->args = xstrdup (args);
+ a->from_tty = from_tty;
+ a->async_exec = async_exec;
+ add_inferior_continuation (attach_command_continuation, a,
+ attach_command_continuation_free_args);
+ /* Done with ARGS. */
+ do_cleanups (args_chain);
+
+ if (!target_is_async_p ())
+ mark_infrun_async_event_handler ();
+ return;
}
/* Done with ARGS. */
@@ -2731,6 +2688,7 @@ notice_new_inferior (ptid_t ptid, int leave_running, int from_tty)
if (is_executing (inferior_ptid))
{
+ struct attach_command_continuation_args *a;
struct inferior *inferior = current_inferior ();
/* We're going to install breakpoints, and poke at memory,
@@ -2741,22 +2699,15 @@ notice_new_inferior (ptid_t ptid, int leave_running, int from_tty)
inferior->control.stop_soon = STOP_QUIETLY_REMOTE;
/* Wait for stop before proceeding. */
- if (target_can_async_p ())
- {
- struct attach_command_continuation_args *a;
+ a = XNEW (struct attach_command_continuation_args);
+ a->args = xstrdup ("");
+ a->from_tty = from_tty;
+ a->async_exec = async_exec;
+ add_inferior_continuation (attach_command_continuation, a,
+ attach_command_continuation_free_args);
- a = XNEW (struct attach_command_continuation_args);
- a->args = xstrdup ("");
- a->from_tty = from_tty;
- a->async_exec = async_exec;
- add_inferior_continuation (attach_command_continuation, a,
- attach_command_continuation_free_args);
-
- do_cleanups (old_chain);
- return;
- }
- else
- wait_for_inferior ();
+ do_cleanups (old_chain);
+ return;
}
async_exec = leave_running;