diff options
author | Pedro Alves <palves@redhat.com> | 2015-09-09 18:23:23 +0100 |
---|---|---|
committer | Pedro Alves <palves@redhat.com> | 2015-09-09 18:23:23 +0100 |
commit | 0b333c5e7d6c3fc65d37ffa11bd21ba52c4adb25 (patch) | |
tree | 3adaca984618d51de1b6dd44a48b83417b01f919 /gdb/infcmd.c | |
parent | ea4a7f9986ed4614d8ffb85ccd4fa4bb49b6d420 (diff) | |
download | gdb-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.c | 143 |
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; |