+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.
+
2015-09-09 Markus Metzger <markus.t.metzger@intel.com>
* nat/linux-btrace.h (struct btrace_target_info) <ptr_bits>: Remove.
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. */
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);
/* 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);
}
#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. */
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;
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)
{
}
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);
if (call_thread != NULL)
call_thread->control.in_infcall = saved_in_infcall;
- sync_execution = saved_sync_execution;
-
return caught_error;
}
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 ();
}
}
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
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
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);
}
}
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;
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
/* 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. */
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
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. */
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,
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;
}
}
+/* 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. */
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);
}
\f
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);
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.
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);
}
/* 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;
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. */
ourstatus->kind = TARGET_WAITKIND_NO_RESUMED;
- if (!target_is_async_p ())
- clear_sigint_trap ();
-
restore_child_signals_mask (&prev_mask);
return minus_one_ptid;
}
sigsuspend (&suspend_mask);
}
- if (!target_is_async_p ())
- clear_sigint_trap ();
-
gdb_assert (lp);
status = lp->status;
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. */
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);
{
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);
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)
{
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;
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)
{
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)
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);
/* 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)
{
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.
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.