aboutsummaryrefslogtreecommitdiff
path: root/gdb/target.c
diff options
context:
space:
mode:
authorPedro Alves <palves@redhat.com>2015-08-07 17:24:01 +0100
committerPedro Alves <palves@redhat.com>2015-08-07 17:24:01 +0100
commitfbea99ea8a062e5cd96e2d88336984ed3adc93d4 (patch)
tree8ddafd610809df1cec1e2aa60f0fabd4dbdf791e /gdb/target.c
parent372316f12874a30c62e6d71079ca3b86c786fb7e (diff)
Implement all-stop on top of a target running non-stop mode
This finally implements user-visible all-stop mode running with the target_ops backend always in non-stop mode. This is a stepping stone towards finer-grained control of threads, being able to do interesting things like thread groups, associating groups with breakpoints, etc. From the user's perspective, all-stop mode is really just a special case of being able to stop and resume specific sets of threads, so it makes sense to do this step first. With this, even in all-stop, the target is no longer in charge of stopping all threads before reporting an event to the core -- the core takes care of it when it sees fit. For example, when "next"- or "step"-ing, we can avoid stopping and resuming all threads at each internal single-step, and instead only stop all threads when we're about to present the stop to the user. The implementation is almost straight forward, as the heavy lifting has been done already in previous patches. Basically, we replace checks for "set non-stop on/off" (the non_stop global), with calls to a new target_is_non_stop_p function. In a few places, if "set non-stop off", we stop all threads explicitly, and in a few other places we resume all threads explicitly, making use of existing methods that were added for teaching non-stop to step over breakpoints without displaced stepping. This adds a new "maint set target-non-stop on/off/auto" knob that allows both disabling the feature if we find problems, and force-enable it for development (useful when teaching a target about this. The default is "auto", which means the feature is enabled if a new target method says it should be enabled. The patch implements the method in linux-nat.c, just for illustration, because it still returns false. We'll need a few follow up fixes before turning it on by default. This is a separate target method from indicating regular non-stop support, because e.g., while e.g., native linux-nat.c is close to regression free with all-stop-non-stop (with following patches will fixing the remaining regressions), remote.c+gdbserver will still need more fixing, even though it supports "set non-stop on". Tested on x86_64 Fedora 20, native, with and without "set displaced off", and with and without "maint set target-non-stop on"; and also against gdbserver. gdb/ChangeLog: 2015-08-07 Pedro Alves <palves@redhat.com> * NEWS: Mention "maint set/show target-non-stop". * breakpoint.c (update_global_location_list): Check target_is_non_stop_p instead of non_stop. * infcmd.c (attach_command_post_wait, attach_command): Likewise. * infrun.c (show_can_use_displaced_stepping) (can_use_displaced_stepping_p, start_step_over_inferior): Likewise. (internal_resume_ptid): New function. (resume): Use it. (proceed): Check target_is_non_stop_p instead of non_stop. If in all-stop mode but the target is always in non-stop mode, start all the other threads that are implicitly resumed too. (for_each_just_stopped_thread, fetch_inferior_event) (adjust_pc_after_break, stop_all_threads): Check target_is_non_stop_p instead of non_stop. (handle_inferior_event): Likewise. Handle detach-fork in all-stop with the target always in non-stop mode. (handle_signal_stop) <random signal>: Check target_is_non_stop_p instead of non_stop. (switch_back_to_stepped_thread): Check target_is_non_stop_p instead of non_stop. (keep_going_stepped_thread): Use internal_resume_ptid. (stop_waiting): If in all-stop mode, and the target is in non-stop mode, stop all threads. (keep_going_pass): Likewise, when starting a new in-line step-over sequence. * linux-nat.c (get_pending_status, select_event_lwp) (linux_nat_filter_event, linux_nat_wait_1, linux_nat_wait): Check target_is_non_stop_p instead of non_stop. (linux_nat_always_non_stop_p): New function. (linux_nat_stop): Check target_is_non_stop_p instead of non_stop. (linux_nat_add_target): Install linux_nat_always_non_stop_p. * target-delegates.c: Regenerate. * target.c (target_is_non_stop_p): New function. (target_non_stop_enabled, target_non_stop_enabled_1): New globals. (maint_set_target_non_stop_command) (maint_show_target_non_stop_command): New functions. (_initilize_target): Install "maint set/show target-non-stop" commands. * target.h (struct target_ops) <to_always_non_stop_p>: New field. (target_non_stop_enabled): New declaration. (target_is_non_stop_p): New declaration. gdb/doc/ChangeLog: 2015-08-07 Pedro Alves <palves@redhat.com> * gdb.texinfo (Maintenance Commands): Document "maint set/show target-non-stop".
Diffstat (limited to 'gdb/target.c')
-rw-r--r--gdb/target.c71
1 files changed, 71 insertions, 0 deletions
diff --git a/gdb/target.c b/gdb/target.c
index 4b7d5187c6..3f49079bf1 100644
--- a/gdb/target.c
+++ b/gdb/target.c
@@ -3781,6 +3781,67 @@ maint_show_target_async_command (struct ui_file *file, int from_tty,
"asynchronous mode is %s.\n"), value);
}
+/* Return true if the target operates in non-stop mode even with "set
+ non-stop off". */
+
+static int
+target_always_non_stop_p (void)
+{
+ return current_target.to_always_non_stop_p (&current_target);
+}
+
+/* See target.h. */
+
+int
+target_is_non_stop_p (void)
+{
+ return (non_stop
+ || target_non_stop_enabled == AUTO_BOOLEAN_TRUE
+ || (target_non_stop_enabled == AUTO_BOOLEAN_AUTO
+ && target_always_non_stop_p ()));
+}
+
+/* Controls if targets can report that they always run in non-stop
+ mode. This is just for maintainers to use when debugging gdb. */
+enum auto_boolean target_non_stop_enabled = AUTO_BOOLEAN_AUTO;
+
+/* The set command writes to this variable. If the inferior is
+ executing, target_non_stop_enabled is *not* updated. */
+static enum auto_boolean target_non_stop_enabled_1 = AUTO_BOOLEAN_AUTO;
+
+/* Implementation of "maint set target-non-stop". */
+
+static void
+maint_set_target_non_stop_command (char *args, int from_tty,
+ struct cmd_list_element *c)
+{
+ if (have_live_inferiors ())
+ {
+ target_non_stop_enabled_1 = target_non_stop_enabled;
+ error (_("Cannot change this setting while the inferior is running."));
+ }
+
+ target_non_stop_enabled = target_non_stop_enabled_1;
+}
+
+/* Implementation of "maint show target-non-stop". */
+
+static void
+maint_show_target_non_stop_command (struct ui_file *file, int from_tty,
+ struct cmd_list_element *c,
+ const char *value)
+{
+ if (target_non_stop_enabled == AUTO_BOOLEAN_AUTO)
+ fprintf_filtered (file,
+ _("Whether the target is always in non-stop mode "
+ "is %s (currently %s).\n"), value,
+ target_always_non_stop_p () ? "on" : "off");
+ else
+ fprintf_filtered (file,
+ _("Whether the target is always in non-stop mode "
+ "is %s.\n"), value);
+}
+
/* Temporary copies of permission settings. */
static int may_write_registers_1 = 1;
@@ -3883,6 +3944,16 @@ Tells gdb whether to control the inferior in asynchronous mode."),
&maintenance_set_cmdlist,
&maintenance_show_cmdlist);
+ add_setshow_auto_boolean_cmd ("target-non-stop", no_class,
+ &target_non_stop_enabled_1, _("\
+Set whether gdb always controls the inferior in non-stop mode."), _("\
+Show whether gdb always controls the inferior in non-stop mode."), _("\
+Tells gdb whether to control the inferior in non-stop mode."),
+ maint_set_target_non_stop_command,
+ maint_show_target_non_stop_command,
+ &maintenance_set_cmdlist,
+ &maintenance_show_cmdlist);
+
add_setshow_boolean_cmd ("may-write-registers", class_support,
&may_write_registers_1, _("\
Set permission to write into registers."), _("\