From: Pedro Alves Date: Wed, 9 Sep 2015 17:23:23 +0000 (+0100) Subject: Merge async and sync code paths some more X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=0b333c5e7d6c3fc65d37ffa11bd21ba52c4adb25;p=binutils-gdb.git 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 * 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) : 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. --- diff --git a/gdb/ChangeLog b/gdb/ChangeLog index bed048a3b35..e4a13bb18aa 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,48 @@ +2015-09-09 Pedro Alves + + * 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) : 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. + 2015-09-09 Markus Metzger * nat/linux-btrace.h (struct btrace_target_info) : Remove. diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c index 50672222ee8..4049d0acb42 100644 --- a/gdb/breakpoint.c +++ b/gdb/breakpoint.c @@ -4662,7 +4662,7 @@ bpstat_do_actions_1 (bpstat *bsp) if (breakpoint_proceeded) { - if (interpreter_async && target_can_async_p ()) + if (interpreter_async) /* If we are in async mode, then the target might be still running, not stopped at any breakpoint, so nothing for us to do here -- just return to the event loop. */ @@ -11588,7 +11588,7 @@ until_break_command (char *arg, int from_tty, int anywhere) be deleted when the target stops. Otherwise, we're already stopped and delete breakpoints via cleanup chain. */ - if (target_can_async_p () && is_running (inferior_ptid)) + if (is_running (inferior_ptid)) { struct until_break_command_continuation_args *args = XNEW (struct until_break_command_continuation_args); diff --git a/gdb/inf-loop.c b/gdb/inf-loop.c index eed881d5144..7b1f7243056 100644 --- a/gdb/inf-loop.c +++ b/gdb/inf-loop.c @@ -73,7 +73,7 @@ inferior_event_handler (enum inferior_event_type event_type, /* Unregister the inferior from the event loop. This is done so that when the inferior is not running we don't get distracted by spurious inferior output. */ - if (target_has_execution) + if (target_has_execution && target_can_async_p ()) target_async (0); } diff --git a/gdb/infcall.c b/gdb/infcall.c index ad5f004da7e..734d6b5219b 100644 --- a/gdb/infcall.c +++ b/gdb/infcall.c @@ -36,6 +36,8 @@ #include "gdbthread.h" #include "event-top.h" #include "observer.h" +#include "top.h" +#include "interps.h" /* If we can't find a function's name from its address, we print this instead. */ @@ -388,10 +390,13 @@ run_inferior_call (struct thread_info *call_thread, CORE_ADDR real_pc) ptid_t call_thread_ptid = call_thread->ptid; int saved_sync_execution = sync_execution; int was_running = call_thread->state == THREAD_RUNNING; + int saved_interpreter_async = interpreter_async; /* Infcalls run synchronously, in the foreground. */ - if (target_can_async_p ()) - sync_execution = 1; + sync_execution = 1; + /* So that we don't print the prompt prematurely in + fetch_inferior_event. */ + interpreter_async = 0; call_thread->control.in_infcall = 1; @@ -404,25 +409,11 @@ run_inferior_call (struct thread_info *call_thread, CORE_ADDR real_pc) TRY { - int was_sync = sync_execution; - proceed (real_pc, GDB_SIGNAL_0); /* Inferior function calls are always synchronous, even if the - target supports asynchronous execution. Do here what - `proceed' itself does in sync mode. */ - if (target_can_async_p ()) - { - wait_for_inferior (); - normal_stop (); - /* If GDB was previously in sync execution mode, then ensure - that it remains so. normal_stop calls - async_enable_stdin, so reset it again here. In other - cases, stdin will be re-enabled by - inferior_event_handler, when an exception is thrown. */ - if (was_sync) - async_disable_stdin (); - } + target supports asynchronous execution. */ + wait_sync_command_done (); } CATCH (e, RETURN_MASK_ALL) { @@ -430,6 +421,13 @@ run_inferior_call (struct thread_info *call_thread, CORE_ADDR real_pc) } END_CATCH + /* If GDB was previously in sync execution mode, then ensure that it + remains so. normal_stop calls async_enable_stdin, so reset it + again here. In other cases, stdin will be re-enabled by + inferior_event_handler, when an exception is thrown. */ + sync_execution = saved_sync_execution; + interpreter_async = saved_interpreter_async; + /* At this point the current thread may have changed. Refresh CALL_THREAD as it could be invalid if its thread has exited. */ call_thread = find_thread_ptid (call_thread_ptid); @@ -470,8 +468,6 @@ run_inferior_call (struct thread_info *call_thread, CORE_ADDR real_pc) if (call_thread != NULL) call_thread->control.in_infcall = saved_in_infcall; - sync_execution = saved_sync_execution; - return caught_error; } diff --git a/gdb/infcmd.c b/gdb/infcmd.c index bdde49dc22f..ce49777d1f1 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; diff --git a/gdb/infrun.c b/gdb/infrun.c index 70dffca440a..273c2bc242a 100644 --- a/gdb/infrun.c +++ b/gdb/infrun.c @@ -131,6 +131,14 @@ infrun_async (int enable) } } +/* See infrun.h. */ + +void +mark_infrun_async_event_handler (void) +{ + mark_async_event_handler (infrun_async_inferior_event_token); +} + /* When set, stop the 'step' command if we enter a function which has no line number information. The normal behavior is that we step over such function. */ @@ -3094,15 +3102,11 @@ proceed (CORE_ADDR addr, enum gdb_signal siggnal) discard_cleanups (old_chain); - /* Wait for it to stop (if not standalone) - and in any case decode why it stopped, and act accordingly. */ - /* Do this only if we are not using the event loop, or if the target - does not support asynchronous execution. */ + /* Tell the event loop to wait for it to stop. If the target + supports asynchronous execution, it'll do this from within + target_resume. */ if (!target_can_async_p ()) - { - wait_for_inferior (); - normal_stop (); - } + mark_async_event_handler (infrun_async_inferior_event_token); } @@ -3766,7 +3770,8 @@ fetch_inferior_event (void *client_data) make_cleanup_restore_integer (&execution_direction); execution_direction = target_execution_direction (); - ecs->ptid = do_target_wait (waiton_ptid, &ecs->ws, TARGET_WNOHANG); + ecs->ptid = do_target_wait (waiton_ptid, &ecs->ws, + target_can_async_p () ? TARGET_WNOHANG : 0); if (debug_infrun) print_target_wait_results (waiton_ptid, ecs->ptid, &ecs->ws); @@ -7520,10 +7525,10 @@ prepare_to_wait (struct execution_control_state *ecs) if (debug_infrun) fprintf_unfiltered (gdb_stdlog, "infrun: prepare_to_wait\n"); - /* This is the old end of the while loop. Let everybody know we - want to wait for the inferior some more and get called again - soon. */ ecs->wait_some_more = 1; + + if (!target_is_async_p ()) + mark_infrun_async_event_handler (); } /* We are done with the step range of a step/next/si/ni command. @@ -8816,14 +8821,6 @@ static const struct internalvar_funcs siginfo_funcs = static void infrun_async_inferior_event_handler (gdb_client_data data) { - /* If the target is closed while this event source is marked, we - will reach here without execution, or a target to call - target_wait on, which is an error. Instead of tracking whether - the target has been popped already, or whether we do have threads - with pending statutes, simply ignore the event. */ - if (!target_is_async_p ()) - return; - inferior_event_handler (INF_REG_EVENT, NULL); } diff --git a/gdb/infrun.h b/gdb/infrun.h index 7978d2c8200..c5b201fc714 100644 --- a/gdb/infrun.h +++ b/gdb/infrun.h @@ -197,6 +197,10 @@ enum gdb_signal gdb_signal_from_command (int num); /* Enables/disables infrun's async event source in the event loop. */ extern void infrun_async (int enable); +/* Call infrun's event handler the next time through the event + loop. */ +extern void mark_infrun_async_event_handler (void); + /* The global queue of threads that need to do a step-over operation to get past e.g., a breakpoint. */ extern struct thread_info *step_over_queue_head; diff --git a/gdb/linux-nat.c b/gdb/linux-nat.c index 51541d5ef12..6b01a51a1fd 100644 --- a/gdb/linux-nat.c +++ b/gdb/linux-nat.c @@ -3442,12 +3442,6 @@ linux_nat_wait_1 (struct target_ops *ops, target_pid_to_str (lp->ptid)); } - if (!target_is_async_p ()) - { - /* Causes SIGINT to be passed on to the attached process. */ - set_sigint_trap (); - } - /* But if we don't find a pending event, we'll have to wait. Always pull all events out of the kernel. We'll randomly select an event LWP out of all that have events, to prevent starvation. */ @@ -3518,9 +3512,6 @@ linux_nat_wait_1 (struct target_ops *ops, ourstatus->kind = TARGET_WAITKIND_NO_RESUMED; - if (!target_is_async_p ()) - clear_sigint_trap (); - restore_child_signals_mask (&prev_mask); return minus_one_ptid; } @@ -3546,9 +3537,6 @@ linux_nat_wait_1 (struct target_ops *ops, sigsuspend (&suspend_mask); } - if (!target_is_async_p ()) - clear_sigint_trap (); - gdb_assert (lp); status = lp->status; @@ -4629,17 +4617,6 @@ static int async_terminal_is_ours = 1; static void linux_nat_terminal_inferior (struct target_ops *self) { - /* Like target_terminal_inferior, use target_can_async_p, not - target_is_async_p, since at this point the target is not async - yet. If it can async, then we know it will become async prior to - resume. */ - if (!target_can_async_p ()) - { - /* Async mode is disabled. */ - child_terminal_inferior (self); - return; - } - child_terminal_inferior (self); /* Calls to target_terminal_*() are meant to be idempotent. */ diff --git a/gdb/mi/mi-interp.c b/gdb/mi/mi-interp.c index 99ce385169c..0935c8f8d91 100644 --- a/gdb/mi/mi-interp.c +++ b/gdb/mi/mi-interp.c @@ -309,16 +309,8 @@ mi_execute_command_wrapper (const char *cmd) static void mi_on_sync_execution_done (void) { - /* MI generally prints a prompt after a command, indicating it's - ready for further input. However, due to an historical wart, if - MI async, and a (CLI) synchronous command was issued, then we - will print the prompt right after printing "^running", even if we - cannot actually accept any input until the target stops. See - mi_on_resume. However, if the target is async but MI is sync, - then we need to output the MI prompt now, to replicate gdb's - behavior when neither the target nor MI are async. (Note this - observer is only called by the asynchronous target event handling - code.) */ + /* If MI is sync, then output the MI prompt now, indicating we're + ready for further input. */ if (!mi_async_p ()) { fputs_unfiltered ("(gdb) \n", raw_stdout); @@ -333,20 +325,12 @@ mi_execute_command_input_handler (char *cmd) { mi_execute_command_wrapper (cmd); - /* MI generally prints a prompt after a command, indicating it's - ready for further input. However, due to an historical wart, if - MI is async, and a synchronous command was issued, then we will - print the prompt right after printing "^running", even if we - cannot actually accept any input until the target stops. See - mi_on_resume. - - If MI is not async, then we print the prompt when the command - finishes. If the target is sync, that means output the prompt - now, as in that case executing a command doesn't return until the - command is done. However, if the target is async, we go back to - the event loop and output the prompt in the - 'synchronous_command_done' observer. */ - if (!target_is_async_p () || !sync_execution) + /* Print a prompt, indicating we're ready for further input, unless + we just started a synchronous command. In that case, we're about + to go back to the event loop and will output the prompt in the + 'synchronous_command_done' observer when the target next + stops. */ + if (!sync_execution) { fputs_unfiltered ("(gdb) \n", raw_stdout); gdb_flush (raw_stdout); diff --git a/gdb/target-delegates.c b/gdb/target-delegates.c index ddcad9426d6..8d51b6c73cc 100644 --- a/gdb/target-delegates.c +++ b/gdb/target-delegates.c @@ -116,12 +116,6 @@ delegate_wait (struct target_ops *self, ptid_t arg1, struct target_waitstatus *a return self->to_wait (self, arg1, arg2, arg3); } -static ptid_t -tdefault_wait (struct target_ops *self, ptid_t arg1, struct target_waitstatus *arg2, int arg3) -{ - noprocess (); -} - static ptid_t debug_wait (struct target_ops *self, ptid_t arg1, struct target_waitstatus *arg2, int arg3) { @@ -4251,7 +4245,7 @@ install_dummy_methods (struct target_ops *ops) ops->to_detach = tdefault_detach; ops->to_disconnect = tdefault_disconnect; ops->to_resume = tdefault_resume; - ops->to_wait = tdefault_wait; + ops->to_wait = default_target_wait; ops->to_fetch_registers = tdefault_fetch_registers; ops->to_store_registers = tdefault_store_registers; ops->to_prepare_to_store = tdefault_prepare_to_store; diff --git a/gdb/target.c b/gdb/target.c index ea541aae4a0..3da984e3790 100644 --- a/gdb/target.c +++ b/gdb/target.c @@ -2233,6 +2233,17 @@ target_wait (ptid_t ptid, struct target_waitstatus *status, int options) return (current_target.to_wait) (¤t_target, ptid, status, options); } +/* See target.h. */ + +ptid_t +default_target_wait (struct target_ops *ops, + ptid_t ptid, struct target_waitstatus *status, + int options) +{ + status->kind = TARGET_WAITKIND_IGNORE; + return minus_one_ptid; +} + char * target_pid_to_str (ptid_t ptid) { diff --git a/gdb/target.h b/gdb/target.h index 37e4edbddcc..0b85adfd13f 100644 --- a/gdb/target.h +++ b/gdb/target.h @@ -471,7 +471,7 @@ struct target_ops ptid_t (*to_wait) (struct target_ops *, ptid_t, struct target_waitstatus *, int TARGET_DEBUG_PRINTER (target_debug_print_options)) - TARGET_DEFAULT_NORETURN (noprocess ()); + TARGET_DEFAULT_FUNC (default_target_wait); void (*to_fetch_registers) (struct target_ops *, struct regcache *, int) TARGET_DEFAULT_IGNORE (); void (*to_store_registers) (struct target_ops *, struct regcache *, int) @@ -1327,6 +1327,13 @@ extern void target_resume (ptid_t ptid, int step, enum gdb_signal signal); extern ptid_t target_wait (ptid_t ptid, struct target_waitstatus *status, int options); +/* The default target_ops::to_wait implementation. */ + +extern ptid_t default_target_wait (struct target_ops *ops, + ptid_t ptid, + struct target_waitstatus *status, + int options); + /* Fetch at least register REGNO, or all regs if regno == -1. No result. */ extern void target_fetch_registers (struct regcache *regcache, int regno); diff --git a/gdb/top.c b/gdb/top.c index 65143d1bba3..6388ba25881 100644 --- a/gdb/top.c +++ b/gdb/top.c @@ -367,6 +367,16 @@ check_frame_language_change (void) /* See top.h. */ +void +wait_sync_command_done (void) +{ + while (gdb_do_one_event () >= 0) + if (!sync_execution) + break; +} + +/* See top.h. */ + void maybe_wait_sync_command_done (int was_sync) { @@ -375,11 +385,7 @@ maybe_wait_sync_command_done (int was_sync) just ran a synchronous command that started the target, wait for that command to end. */ if (!interpreter_async && !was_sync && sync_execution) - { - while (gdb_do_one_event () >= 0) - if (!sync_execution) - break; - } + wait_sync_command_done (); } /* Execute the line P as a command, in the current user context. diff --git a/gdb/top.h b/gdb/top.h index 914a27288f9..e04fc3f4839 100644 --- a/gdb/top.h +++ b/gdb/top.h @@ -50,6 +50,9 @@ extern void execute_command (char *, int); extern void maybe_wait_sync_command_done (int was_sync); +/* Wait for a synchronous execution command to end. */ +extern void wait_sync_command_done (void); + extern void check_frame_language_change (void); /* Prepare for execution of a command.