From: Natalia Saiapova <natalia.saiapova@intel.com>
To: gdb-patches@sourceware.org
Subject: [PATCH v2 5/6] gdb: refine commands to control scheduler locking.
Date: Tue, 9 Jul 2024 15:04:09 +0000 [thread overview]
Message-ID: <20240709150410.34624-6-natalia.saiapova@intel.com> (raw)
In-Reply-To: <20240709150410.34624-1-natalia.saiapova@intel.com>
In this patch, we introduce new command options for set/show scheduler
locking. New options give the user a finer control over the scheduler.
Introduce
set scheduler-locking <non-step | replay step | replay non-step> | step> <on | off>
show scheduler-locking <non-step | replay step | replay non-step| step>
For example, with these commands a user can get a combined scheduler locking
for stepping commands during the normal execution and for all commands in
replay mode.
The existing scheduler-locking settings still exist and work as shortcuts.
set scheduler-locking step
is equivalent to
set scheduler-locking non-step off
set scheduler-locking replay non-step off
set scheduler-locking replay step on
set scheduler-locking step on
set scheduler-locking on
is equivalent to
set scheduler-locking non-step on
set scheduler-locking replay non-step on
set scheduler-locking replay step on
set scheduler-locking step on
set scheduler-locking replay
is equivalent to
set scheduler-locking non-step off
set scheduler-locking replay non-step on
set scheduler-locking replay step on
set scheduler-locking step off
set scheduler-locking off
is equivalent to
set scheduler-locking non-step off
set scheduler-locking replay non-step off
set scheduler-locking replay step off
set scheduler-locking step off
This is bound to the structure we introduced in the previous commit:
gdb: change the internal representation of scheduler locking.
To introduce it under scheduler-locking I had to change the way the show
command works.
(gdb) show scheduler-locking
scheduler-locking non-step: "off" Scheduler locking for non-stepping
commands is "off" during normal execution.
scheduler-locking replay non-step: "on" Scheduler locking for
non-stepping commands is "on" during replay mode.
scheduler-locking replay step: "on" Scheduler locking for stepping
commands is "on" during replay mode.
scheduler-locking step: "off" Scheduler locking for stepping commands
is "off" during normal execution.
(gdb) show scheduler-locking replay
scheduler-locking replay non-step: "on" Scheduler locking for
non-stepping commands is "on" during replay mode.
scheduler-locking replay step: "on" Scheduler locking for stepping
commands is "on" during replay mode.
(gdb) show scheduler-locking replay step
"on" Scheduler locking for stepping commands is "on" during replay mode.
(gdb) show scheduler-locking non-step
"off" Scheduler locking for non-stepping commands is "off" during
normal execution.
Note, there is a small inconsistency with the "set scheduler-locking step".
If we did not keep the older way of setting the scheduler locking, command
set scheduler-locking step
would be the same as
set scheduler-locking step on
while to be backward compatible, we have it as
set scheduler-locking step on
set scheduler-locking replay step on
Reviewed-By: Eli Zaretskii <eliz@gnu.org>
---
gdb/NEWS | 20 ++
gdb/doc/gdb.texinfo | 70 +++++-
gdb/infrun.c | 224 ++++++++++++++----
.../gdb.mi/user-selected-context-sync.exp | 22 +-
.../gdb.threads/hand-call-in-threads.exp | 10 +-
.../multiple-successive-infcall.exp | 6 +-
gdb/testsuite/gdb.threads/schedlock.exp | 80 ++++++-
gdb/testsuite/lib/gdb.exp | 70 ++++--
8 files changed, 400 insertions(+), 102 deletions(-)
diff --git a/gdb/NEWS b/gdb/NEWS
index 47677cb773a..188596b20e7 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -58,6 +58,26 @@ list .
lines. This makes it more obvious that there is no information, as opposed
to implying there is no inferior loaded.
+set scheduler-locking <command type> (on|off)
+show scheduler-locking <command type>
+ where <command-type> is one of the following:
+ non-step | replay non-step | replay step | step.
+ Extend the scheduler locking settings with a set of set/show
+ commands, which can be used individually to control the scheduler during
+ stepping and non-stepping commands. Stepping commands include step, stepi, next.
+ Non-stepping commands include continue, finish, until, jump, return.
+ 'non-step' -- when on, the scheduler is locked during non-stepping commands
+ in normal mode.
+ 'replay non-step' -- when on, the scheduler is locked during non-stepping
+ commands in replay mode.
+ 'replay step' -- when on, the scheduler is locked during stepping
+ commands in replay mode.
+ 'step' -- when on, the scheduler is locked during stepping commands
+ in normal mode.
+ The older scheduler locking settings can be used as shortcuts, their behavior
+ is preserved.
+ The output of "show scheduler-locking" has changed to support the new settings.
+
* New commands
info missing-debug-handler
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index 86cd420832a..32e2703414d 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -7175,28 +7175,67 @@ On some OSes, you can modify @value{GDBN}'s default behavior by
locking the OS scheduler to allow only a single thread to run.
@table @code
-@item set scheduler-locking @var{mode}
@cindex scheduler-locking
+@item set scheduler-locking @var{type} [@code{on}|@code{off}]
+@cindex scheduler locking type
+@cindex lock scheduler
+Set the scheduler locking settings. It applies to normal execution,
+record mode, and replay mode. You can configure scheduler locking separately
+for stepping and non-stepping commands. Examples of stepping commands are:
+@samp{step}, @samp{stepi}, @samp{next}. Examples of non-stepping commands are
+@samp{continue}, @samp{finish}, @samp{jump}, @samp{until}, @samp{return} or
+inferior function calls.
+
+The following @var{type}-settings are available:
+
+@table @code
+@item non-step
+When @code{on}, the scheduler is locked for non-stepping commands during
+normal execution and record modes. For non-stepping commands other threads
+may not preempt the current thread. This setting is @code{off} by default.
+
+@item replay non-step
+When @code{on}, the scheduler is locked for non-stepping commands during
+replay mode. For non-stepping commands other threads may not preempt
+the current thread. This setting is @code{on} by default.
+
+@item replay step
+When @code{on}, the scheduler is locked for stepping commands during replay
+mode. While stepping, other threads may not preempt the current thread,
+so that the focus of debugging does not change unexpectedly. This setting
+is @code{on} by default.
+
+@item step
+When @code{on}, the scheduler is locked for stepping commands during
+normal execution and record modes. While stepping, other threads may not
+preempt the current thread, so that the focus of debugging does not change
+unexpectedly. This setting is @code{off} by default.
+
+@end table
+
+@item set scheduler-locking @var{shortcut-mode}
@cindex scheduler locking mode
@cindex lock scheduler
-Set the scheduler locking mode. It applies to normal execution,
-record mode, and replay mode. @var{mode} can be one of
-the following:
+Set the scheduler locking mode. It applies to normal execution, record mode,
+and replay mode. @var{shortcut-mode} is a shortcut to set several scheduler
+locking types at once and can be one of the following:
@table @code
@item off
-There is no locking and any thread may run at any time.
+There is no locking and any thread may run at any time. This is
+equivalent to setting all type options to @code{off}.
@item on
-Only the current thread may run when the inferior is resumed. New
-threads created by the resumed thread are held stopped at their entry
-point, before they execute any instruction.
+Only the current thread may run when the inferior is resumed. New threads
+created by the resumed thread are held stopped at their entry point, before
+they execute any instruction. This is equivalent to setting all type options
+to @code{on}.
@item step
Behaves like @code{on} when stepping, and @code{off} otherwise.
Threads other than the current never get a chance to run when you
-step, and they are completely free to run when you use commands like
-@samp{continue}, @samp{until}, or @samp{finish}.
+step, and they are completely free to run when you use non-stepping
+commands.
This mode optimizes for single-stepping; it prevents other threads
from preempting the current thread while you are stepping, so that the
@@ -7205,9 +7244,18 @@ another thread hits a breakpoint during its timeslice, @value{GDBN}
does not change the current thread away from the thread that you are
debugging.
+This is equivalent to set @samp{scheduler-locking step} and
+@samp{scheduler-locking replay step} to @code{on}, while other settings
+are @code{off}.
+
@item replay
Behaves like @code{on} in replay mode, and @code{off} in either record
mode or during normal execution. This is the default mode.
+
+This is equivalent to set @samp{scheduler-locking replay non-step} and
+@samp{scheduler-locking replay step} to @code{on}, while other settings
+are @code{off}.
+
@end table
@item show scheduler-locking
@@ -34171,7 +34219,7 @@ the end or beginning of a replay log if one is being used.
@end itemize
In all-stop mode (@pxref{All-Stop
Mode}), may resume only one thread, or all threads, depending on the
-value of the @samp{scheduler-locking} variable. If @samp{--all} is
+value of the @samp{scheduler-locking} variables. If @samp{--all} is
specified, all threads (in all inferiors) will be resumed. The @samp{--all} option is
ignored in all-stop mode. If the @samp{--thread-group} options is
specified, then all threads in that thread group are resumed.
diff --git a/gdb/infrun.c b/gdb/infrun.c
index 21b7b7c7806..b02966a8afa 100644
--- a/gdb/infrun.c
+++ b/gdb/infrun.c
@@ -77,6 +77,8 @@
#include "extension.h"
#include "disasm.h"
#include "interps.h"
+#include "cli/cli-decode.h"
+#include <set>
/* Prototypes for local functions */
@@ -112,6 +114,12 @@ static bool schedlock_applies (thread_info *);
static bool schedlock_applies (thread_info *, bool);
static bool schedlock_applies_to_opts (const schedlock_options &, bool);
+/* Command lists for the scheduler locking. */
+static cmd_list_element *schedlock_set_cmdlist;
+static cmd_list_element *schedlock_show_cmdlist;
+static cmd_list_element *schedlock_set_replay_cmdlist;
+static cmd_list_element *schedlock_show_replay_cmdlist;
+
/* Asynchronous signal handler registered as event loop source for
when we have pending events ready to be passed to the core. */
static struct async_event_handler *infrun_async_inferior_event_token;
@@ -2346,7 +2354,8 @@ struct schedlock_options
operator bool () const { return value; }
const char *c_str () const { return value ? "on" : "off"; }
- /* Set new value. Return true, if the value has changed. */
+ /* Set new value. Return true, if the value has changed.
+ Also notifies the observer, if the value has changed. */
bool set (bool new_value);
};
@@ -2373,6 +2382,9 @@ schedlock_options::option::set (bool new_value)
if (value != new_value)
{
value = new_value;
+ std::string param_name = "scheduler-locking " + name;
+
+ interps_notify_param_changed (param_name.c_str (), c_str ());
return true;
}
@@ -2393,15 +2405,6 @@ static const char schedlock_off[] = "off";
static const char schedlock_on[] = "on";
static const char schedlock_step[] = "step";
static const char schedlock_replay[] = "replay";
-static const char *const scheduler_enums[] = {
- schedlock_off,
- schedlock_on,
- schedlock_step,
- schedlock_replay,
- nullptr
-};
-
-static const char *scheduler_mode = schedlock_replay;
schedlock schedlock {{{"non-step", false}, {"step", false}},
{{"replay non-step", true}, {"replay step", true}}};
@@ -2422,35 +2425,89 @@ set_schedlock_shortcut_option (const char *shortcut)
/* Check that we got a valid shortcut option. */
gdb_assert (is_on || is_step || is_replay || is_off);
- schedlock.normal.non_step.set (is_on);
- schedlock.normal.step.set (is_on || is_step);
- schedlock.replay.non_step.set (is_on || is_replay);
- schedlock.replay.step.set (is_on || is_replay || is_step);
+ bool any_changed = schedlock.normal.non_step.set (is_on);
+ any_changed = schedlock.normal.step.set (is_on || is_step) || any_changed;
+ any_changed = schedlock.replay.non_step.set (is_on || is_replay) || any_changed;
+ any_changed = schedlock.replay.step.set (is_on || is_replay || is_step)
+ || any_changed;
+
+ /* If at least one parameter has changed, notify the observer
+ in the old-fashioned way. */
+ if (any_changed)
+ interps_notify_param_changed ("scheduler-locking", shortcut);
}
+/* Default callback for set methods of scheduler locking options.
+ Checks that the scheduler locking is supported.
+ If no, it reverts all options to "off" and throws an error. */
+
static void
-show_scheduler_mode (struct ui_file *file, int from_tty,
- struct cmd_list_element *c, const char *value)
+set_schedlock_callback (const char *args, int from_tty, cmd_list_element *c)
{
- gdb_printf (file,
- _("Mode for locking scheduler "
- "during execution is \"%s\".\n"),
- value);
+ if (target_can_lock_scheduler ())
+ return;
+
+ /* Set scheduler locking off and error out. */
+ set_schedlock_shortcut_option (schedlock_off);
+ error (_("Target '%s' cannot support this command."), target_shortname ());
}
+/* Support for shortcut schedlock options: "on", "off", "step", "replay". */
+
static void
-set_schedlock_func (const char *args, int from_tty, struct cmd_list_element *c)
+set_schedlock_step (const char *args, int from_tty, cmd_list_element *c)
{
- if (!target_can_lock_scheduler ())
- {
- scheduler_mode = schedlock_off;
- /* Set scheduler locking off. */
- set_schedlock_shortcut_option (schedlock_off);
- error (_("Target '%s' cannot support this command."),
- target_shortname ());
- }
+ if (!args || !*args)
+ set_schedlock_shortcut_option (schedlock_step);
+ set_schedlock_callback (args, from_tty, nullptr);
+}
- set_schedlock_shortcut_option (scheduler_mode);
+static void
+set_schedlock_replay (const char *args, int from_tty)
+{
+ set_schedlock_shortcut_option (schedlock_replay);
+ set_schedlock_callback (args, from_tty, nullptr);
+}
+
+static void
+set_schedlock_on (const char *args, int from_tty)
+{
+ set_schedlock_shortcut_option (schedlock_on);
+ set_schedlock_callback (args, from_tty, nullptr);
+}
+
+static void
+set_schedlock_off (const char *args, int from_tty)
+{
+ set_schedlock_shortcut_option (schedlock_off);
+ set_schedlock_callback (args, from_tty, nullptr);
+}
+
+/* Default method to show a single option of scheduler locking. */
+
+static void
+show_schedlock_option (ui_file *file, int from_tty,
+ cmd_list_element *c, const char *value)
+{
+ gdb_assert (c->prefix != nullptr);
+ const char *mode;
+ if (strcmp (c->prefix->name, "replay") == 0)
+ mode = "replay mode";
+ else if (strcmp (c->prefix->name, "scheduler-locking") == 0)
+ mode = "normal execution";
+ else
+ gdb_assert_not_reached ("Unexpected command prefix.");
+
+ const char *type;
+ if (strcmp (c->name, "step") == 0)
+ type = "stepping commands";
+ else if (strcmp (c->name, "non-step") == 0)
+ type = "non-stepping commands";
+ else
+ gdb_assert_not_reached ("Unexpected command name.");
+
+ gdb_printf (file, _("\"%s\" Scheduler locking for %s is "
+ "\"%s\" during the %s.\n"), value, type, value, mode);
}
/* True if execution commands resume all threads of all processes by
@@ -8466,15 +8523,7 @@ switch_back_to_stepped_thread (struct execution_control_state *ecs)
return true;
}
- /* If scheduler locking applies even if not stepping, there's no
- need to walk over threads. Above we've checked whether the
- current thread is stepping. If some other thread not the
- event thread is stepping, then it must be that scheduler
- locking is not in effect. */
- if (schedlock_applies (ecs->event_thread))
- return false;
-
- /* Otherwise, we no longer expect a trap in the current thread.
+ /* We no longer expect a trap in the current thread.
Clear the trap_expected flag before switching back -- this is
what keep_going does as well, if we call it. */
ecs->event_thread->control.trap_expected = 0;
@@ -10771,21 +10820,92 @@ By default, the debugger will use the same inferior."),
show_follow_exec_mode_string,
&setlist, &showlist);
- add_setshow_enum_cmd ("scheduler-locking", class_run,
- scheduler_enums, &scheduler_mode, _("\
-Set mode for locking scheduler during execution."), _("\
-Show mode for locking scheduler during execution."), _("\
-off == no locking (threads may preempt at any time)\n\
-on == full locking (no thread except the current thread may run)\n\
- This applies to both normal execution and replay mode.\n\
-step == scheduler locked during stepping commands (step, next, stepi, nexti).\n\
- In this mode, other threads may run during other commands.\n\
- This applies to both normal execution and replay mode.\n\
-replay == scheduler locked in replay mode and unlocked during normal execution."),
- set_schedlock_func, /* traps on target vector */
- show_scheduler_mode,
+ /* Commands for set/show scheduler-locking. */
+
+ add_setshow_prefix_cmd ("scheduler-locking", class_run, _("\
+Scheduler locking settings.\n\
+Configure scheduler locking settings in various conditions."), _("\
+Show scheduler locking settings in various conditions."),
+ &schedlock_set_cmdlist,
+ &schedlock_show_cmdlist,
&setlist, &showlist);
+ add_setshow_boolean_cmd ("non-step", class_run, &schedlock.normal.non_step.value, _("\
+Scheduler locking for non-stepping commands during normal execution."), _("\
+Show scheduler locking for non-stepping commands during normal execution."),
+ _("\
+Controls scheduler locking for non-stepping commands during normal execution.\n\
+Commands include continue, until, finish. The setting does not affect \
+stepping."),
+ set_schedlock_callback,
+ show_schedlock_option,
+ &schedlock_set_cmdlist,
+ &schedlock_show_cmdlist);
+
+ add_setshow_boolean_cmd ("step", class_run, &schedlock.normal.step.value, _("\
+Scheduler locking for stepping commands. W/o arguments locks the scheduler \
+for stepping."), _("\
+Show scheduler locking for stepping commands during normal execution."), _("\
+If argument \"on\" or \"off\", sets scheduler locking behavior for stepping\n\
+commands only during normal execution.\n\
+Commands include step, next, stepi, nexti."),
+ set_schedlock_step,
+ show_schedlock_option,
+ &schedlock_set_cmdlist,
+ &schedlock_show_cmdlist);
+
+ /* Commands for set/show scheduler-locking in replay mode.
+ The base command adds support for the shortcut
+ set scheduler-locking replay
+ command. */
+
+ add_setshow_prefix_cmd ("replay", class_run, _("\
+Scheduler locking settings for replay mode.\n\
+Configure scheduler locking in various conditions such as during continuing\n\
+or stepping."),
+("Show scheduler locking in replay mode."),
+ &schedlock_set_replay_cmdlist,
+ &schedlock_show_replay_cmdlist,
+ &schedlock_set_cmdlist,
+ &schedlock_show_cmdlist);
+ add_prefix_cmd ("replay", class_run, set_schedlock_replay, _("\
+Scheduler locking settings for replay mode. \
+W/o arguments completely locks the scheduler in replay mode."),
+ &schedlock_set_replay_cmdlist,
+ 0, &schedlock_set_cmdlist);
+
+ add_setshow_boolean_cmd ("non-step", class_run, &schedlock.replay.non_step.value, _("\
+Set scheduler locking for non-stepping commands in replay mode."), _("\
+Show scheduler locking for non-stepping commands in replay mode."), _("\
+Controls scheduler locking for non-stepping commands in replay mode.\n\
+Commands include continue, until, finish. The setting does not affect \
+stepping."),
+ set_schedlock_callback,
+ show_schedlock_option,
+ &schedlock_set_replay_cmdlist,
+ &schedlock_show_replay_cmdlist);
+
+ add_setshow_boolean_cmd ("step", class_run, &schedlock.replay.step.value, _("\
+Set scheduler locking for stepping commands in replay mode."), _("\
+Show scheduler locking for stepping commands in replay mode."), _("\
+Controls scheduler locking for stepping commands in replay mode.\n\
+Commands include step, next, stepi, nexti."),
+ set_schedlock_callback,
+ show_schedlock_option,
+ &schedlock_set_replay_cmdlist,
+ &schedlock_show_replay_cmdlist);
+
+/* Commands "set scheduler-locking on" and "set scheduler-locking off"
+ are provided for backward compatibility. */
+ c = add_cmd ("on", class_run, set_schedlock_on, _("\
+[Shortcut] Full locking (no thread except the current thread may run).\n\
+This applies to both normal execution and replay mode."),
+ &schedlock_set_cmdlist);
+
+ c = add_cmd ("off", class_run, set_schedlock_off, _("\
+[Shortcut] No locking (threads may preempt at any time)."),
+ &schedlock_set_cmdlist);
+
add_setshow_boolean_cmd ("schedule-multiple", class_run, &sched_multi, _("\
Set mode for resuming threads of all processes."), _("\
Show mode for resuming threads of all processes."), _("\
diff --git a/gdb/testsuite/gdb.mi/user-selected-context-sync.exp b/gdb/testsuite/gdb.mi/user-selected-context-sync.exp
index 93b91b42f92..c21748def9d 100644
--- a/gdb/testsuite/gdb.mi/user-selected-context-sync.exp
+++ b/gdb/testsuite/gdb.mi/user-selected-context-sync.exp
@@ -255,17 +255,12 @@ proc make_cli_in_mi_re { command cli_in_mi_mode mode event inf cli_thread
# Return the current value of the "scheduler-locking" parameter.
proc show_scheduler_locking { } {
- global gdb_prompt
- global expect_out
-
- set any "\[^\r\n\]*"
-
set test "show scheduler-locking"
- gdb_test_multiple $test $test {
- -re ".*Mode for locking scheduler during execution is \"(${any})\".\r\n$gdb_prompt " {
- pass $test
- return $expect_out(1,string)
- }
+ set schedlock [get_scheduler_locking $test]
+
+ if {$schedlock ne "unknown"} {
+ pass $test
+ return $schedlock
}
error "Couldn't get current scheduler-locking value."
@@ -311,7 +306,7 @@ proc test_continue_to_start { mode inf } {
}
if { $mode == "all-stop" } {
- set previous_schedlock_val [show_scheduler_locking]
+ set previous_schedlock [show_scheduler_locking]
# Set scheduler-locking on, so that we can control threads
# independently.
@@ -342,7 +337,10 @@ proc test_continue_to_start { mode inf } {
}
# Restore scheduler-locking to its original value.
- gdb_test_no_output "set scheduler-locking $previous_schedlock_val"
+ foreach opt {"non-step" "replay non-step" "replay step" "step"} {
+ gdb_test_no_output \
+ "set scheduler-locking $opt [dict get $previous_schedlock $opt]"
+ }
} else { # $mode == "non-stop"
# Put a thread-specific breakpoint for thread 2 of the current
# inferior. We don't put a breakpoint for thread 3, since we
diff --git a/gdb/testsuite/gdb.threads/hand-call-in-threads.exp b/gdb/testsuite/gdb.threads/hand-call-in-threads.exp
index cde2b2d98ac..36c839990e2 100644
--- a/gdb/testsuite/gdb.threads/hand-call-in-threads.exp
+++ b/gdb/testsuite/gdb.threads/hand-call-in-threads.exp
@@ -68,7 +68,10 @@ gdb_test "continue" \
# Before we start making hand function calls, turn on scheduler locking.
gdb_test_no_output "set scheduler-locking on" "enable scheduler locking"
-gdb_test "show scheduler-locking" ".* locking scheduler .* is \"on\"." "show scheduler locking on"
+set test "show scheduler-locking on"
+gdb_assert {[get_scheduler_locking $test \
+ [dict create "non-step" "on" "replay non-step" "on" \
+ "replay step" "on" "step" "on"]] ne "unknown"} $test
# Now hand-call a function in each thread, having the function
# stop without returning.
@@ -139,7 +142,10 @@ gdb_test_multiple "maint print dummy-frames" "all dummies popped" {
# Before we resume the full program, turn off scheduler locking.
gdb_test_no_output "set scheduler-locking off" "disable scheduler locking"
-gdb_test "show scheduler-locking" ".* locking scheduler .* is \"off\"." "show scheduler locking off"
+set test "show scheduler-locking off"
+gdb_assert {[get_scheduler_locking $test \
+ [dict create "non-step" "off" "replay non-step" "off" \
+ "replay step" "off" "step" "off"]] ne "unknown"} $test
# Continue one last time, the program should exit normally.
#
diff --git a/gdb/testsuite/gdb.threads/multiple-successive-infcall.exp b/gdb/testsuite/gdb.threads/multiple-successive-infcall.exp
index 4a97179a5b4..c0f786e6389 100644
--- a/gdb/testsuite/gdb.threads/multiple-successive-infcall.exp
+++ b/gdb/testsuite/gdb.threads/multiple-successive-infcall.exp
@@ -49,8 +49,10 @@ foreach_with_prefix thread {5 4 3} {
gdb_breakpoint [gdb_get_line_number "testmarker01"]
gdb_continue_to_breakpoint "testmarker01"
gdb_test_no_output "set scheduler-locking on"
-gdb_test "show scheduler-locking" \
- "Mode for locking scheduler during execution is \"on\"."
+set test "show scheduler-locking"
+gdb_assert {[get_scheduler_locking $test \
+ [dict create "non-step" "on" "replay non-step" "on" \
+ "replay step" "on" "step" "on"]] ne "unknown"} $test
foreach_with_prefix thread {5 4 3 2 1} {
gdb_test "thread ${thread}" "Switching to .*"
diff --git a/gdb/testsuite/gdb.threads/schedlock.exp b/gdb/testsuite/gdb.threads/schedlock.exp
index bd5d5d2cff3..b81cb8a9907 100644
--- a/gdb/testsuite/gdb.threads/schedlock.exp
+++ b/gdb/testsuite/gdb.threads/schedlock.exp
@@ -94,7 +94,8 @@ proc get_current_thread { description } {
# Make sure we're stopped in the loop, in one of the non-main threads.
proc goto_loop { msg } {
- gdb_breakpoint [concat [gdb_get_line_number "schedlock.exp: main loop"] " if arg != 0"]
+ global srcfile
+ gdb_breakpoint [concat "$srcfile:" [gdb_get_line_number "schedlock.exp: main loop"] " if arg != 0"]
set test "return to loop"
if {$msg != ""} {
@@ -264,16 +265,21 @@ with_test_prefix "schedlock=on: cmd=continue" {
}
# Test stepping/nexting with different modes of scheduler locking.
-proc test_step { schedlock cmd call_function } {
+# Do scheduler-locking off setting before the test if PRESET_SCHEDLOCK_OFF is 1.
+# LOCKED defines whether we expect the thread to be locked. If -1, then
+# determine it first.
+proc test_step { schedlock cmd call_function { preset_schedlock_off 1 } { locked -1 } } {
global NUM
- gdb_test_no_output "set scheduler-locking off"
+ if {$preset_schedlock_off} {
+ gdb_test_no_output "set scheduler-locking off"
+ }
goto_loop ""
set curthread [get_current_thread "before"]
# No need to set to off again. This avoids a duplicate message.
- if {$schedlock != "off"} {
+ if {$preset_schedlock_off && $schedlock != "off"} {
gdb_test_no_output "set scheduler-locking $schedlock"
}
@@ -284,16 +290,18 @@ proc test_step { schedlock cmd call_function } {
step_ten_loops $cmd
- if { $schedlock == "on" || $schedlock == "step" } {
- set locked 1
- } else {
- set locked 0
+ if { $locked == -1 } {
+ if { $schedlock == "on" || $schedlock == "step"} {
+ set locked 1
+ } else {
+ set locked 0
+ }
}
check_result $cmd $curthread $before_args $locked
}
-# Test stepping/nexting with different modes of scheduler locking.
+# Test stepping/nexting with different shortcut modes of scheduler locking.
foreach schedlock {"off" "step" "on"} {
with_test_prefix "schedlock=$schedlock" {
with_test_prefix "cmd=step" {
@@ -312,3 +320,57 @@ foreach schedlock {"off" "step" "on"} {
}
}
}
+
+proc test_schedlock_opts {non_step step} {
+ set test "show scheduler-locking"
+ if {[get_scheduler_locking $test \
+ [dict create "non-step" $non_step "replay non-step" "off" \
+ "replay step" "off" "step" $step]] eq "unknown"} {
+ fail $test
+ } else {
+ pass $test
+ }
+
+ set locked 0
+ if {$step eq "on"} {
+ set locked 1
+ }
+
+ # Stepping tests.
+ with_test_prefix "cmd=step" {
+ test_step "" "step" 0 0 $locked
+ }
+ with_test_prefix "cmd=next" {
+ foreach call_function {0 1} {
+ with_test_prefix "call_function=$call_function" {
+ test_step "" "next" $call_function 0 $locked
+ }
+ }
+ }
+
+ # Continuing tests.
+ set locked 0
+ if {$non_step eq "on"} {
+ set locked 1
+ }
+ with_test_prefix "cmd=continue" {
+ # Use whichever we stopped in.
+ set curthread [get_current_thread "before"]
+ set cont_args [get_args "before"]
+ my_continue "continue"
+ check_result "continue" $curthread $cont_args $locked
+ }
+}
+
+gdb_test_no_output "set scheduler-locking off"
+
+# Test different options of scheduler locking.
+foreach non_step {"off" "on"} {
+ foreach step {"off" "on"} {
+ with_test_prefix "non-step=$non_step step=$step" {
+ gdb_test_no_output "set scheduler-locking non-step $non_step"
+ gdb_test_no_output "set scheduler-locking step $step"
+ test_schedlock_opts $non_step $step
+ }
+ }
+}
diff --git a/gdb/testsuite/lib/gdb.exp b/gdb/testsuite/lib/gdb.exp
index dfe19c9410d..6d313c2a9a1 100644
--- a/gdb/testsuite/lib/gdb.exp
+++ b/gdb/testsuite/lib/gdb.exp
@@ -8966,6 +8966,52 @@ gdb_caching_proc gdb_target_symbol_prefix {} {
return $prefix
}
+# Return a dictionary of scheduler locking settings with keys:
+# non-step, replay non-step, replay step, step.
+# TEST is an optional test name.
+# EXPECTED is a dictionary of expected values for scheduler locking with
+# the same keys. If EXPECTED has less elements than scheduler locking
+# settings, that means that both on and off can be expected for missing
+# settings.
+proc get_scheduler_locking {{test ""} {expected ""}} {
+ global gdb_prompt
+ if {$test eq ""} {
+ set test "reading current scheduler-locking mode"
+ }
+
+ set opts {"non-step" "replay non-step" "replay step" "step"}
+
+ # Fill the missing entries in EXPECTED list.
+ foreach opt $opts {
+ if {![dict exists $expected $opt]} {
+ dict set expected $opt "\(?:on|off\)"
+ }
+ }
+
+ set any "\[^\r\n\]+"
+ set schedlock_regex ""
+ foreach opt $opts {
+ set opt_regex \
+ "${any}$opt: +\"\([dict get $expected $opt]\)\"${any}"
+ set schedlock_regex "$schedlock_regex\[\r\n\]+$opt_regex"
+ }
+
+ set current_schedlock_mode "unknown"
+ gdb_test_multiple "show scheduler-locking" $test {
+ -re -wrap $schedlock_regex {
+ set current_schedlock_mode [dict create]
+ set i 1
+ foreach opt $opts {
+ dict set current_schedlock_mode $opt $expect_out($i,string)
+ incr $i
+ }
+ }
+ -re -wrap "" {}
+ timeout {}
+ }
+ return $current_schedlock_mode
+}
+
# Return 1 if target supports scheduler locking, otherwise return 0.
gdb_caching_proc target_supports_scheduler_locking {} {
@@ -8984,28 +9030,24 @@ gdb_caching_proc target_supports_scheduler_locking {} {
}
set supports_schedule_locking -1
- set current_schedule_locking_mode ""
set test "reading current scheduler-locking mode"
- gdb_test_multiple "show scheduler-locking" $test {
- -re "Mode for locking scheduler during execution is \"(\[\^\"\]*)\".*$gdb_prompt" {
- set current_schedule_locking_mode $expect_out(1,string)
- }
- -re "$gdb_prompt $" {
- set supports_schedule_locking 0
- }
- timeout {
- set supports_schedule_locking 0
- }
+ set current_schedlock [get_scheduler_locking $test]
+ if { $current_schedlock eq "unknown" } {
+ set supports_schedule_locking 0
}
if { $supports_schedule_locking == -1 } {
set test "checking for scheduler-locking support"
- gdb_test_multiple "set scheduler-locking $current_schedule_locking_mode" $test {
- -re "Target '\[^'\]+' cannot support this command\..*$gdb_prompt $" {
+ set regex_schedlock \
+ "set scheduler-locking step [dict get current_schedlock step]"
+
+ # Try to set scheduler-locking run.
+ gdb_test_multiple $regex_schedlock $test {
+ -re -wrap "Target '\[^'\]+' cannot support this command\..*" {
set supports_schedule_locking 0
}
- -re "$gdb_prompt $" {
+ -re -wrap "" {
set supports_schedule_locking 1
}
timeout {
--
2.25.1
Intel Deutschland GmbH
Registered Address: Am Campeon 10, 85579 Neubiberg, Germany
Tel: +49 89 99 8853-0, www.intel.de
Managing Directors: Sean Fennelly, Jeffrey Schneiderman, Tiffany Doon Silva
Chairperson of the Supervisory Board: Nicole Lau
Registered Office: Munich
Commercial Register: Amtsgericht Muenchen HRB 186928
next prev parent reply other threads:[~2024-07-09 15:06 UTC|newest]
Thread overview: 14+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-07-09 15:04 [PATCH v2 0/6] Refinement of scheduler-locking settings Natalia Saiapova
2024-07-09 15:04 ` [PATCH v2 1/6] gdb: use schedlock_applies in user_visible_resume_ptid Natalia Saiapova
2024-07-09 15:04 ` [PATCH v2 2/6] gdb, cli: remove left-over code from "set_logging_on" Natalia Saiapova
2024-07-09 15:04 ` [PATCH v2 3/6] gdb, cli: pass the argument of a set command to its callback Natalia Saiapova
2024-07-09 15:04 ` [PATCH v2 4/6] gdb: change the internal representation of scheduler locking Natalia Saiapova
2024-07-09 15:04 ` Natalia Saiapova [this message]
2024-07-09 15:57 ` [PATCH v2 5/6] gdb: refine commands to control " Eli Zaretskii
2024-07-09 15:04 ` [PATCH v2 6/6] gdb: add eval option to lock the scheduler during infcalls Natalia Saiapova
2024-07-09 16:00 ` Eli Zaretskii
2024-07-12 11:13 ` [PATCH v2 0/6] Refinement of scheduler-locking settings Saiapova, Natalia
2024-08-20 14:42 ` [PING][PATCH " Gerlicher, Klaus
2024-09-10 14:43 ` [PING V2][PATCH " Gerlicher, Klaus
2024-10-02 14:14 ` [PING V3][PATCH " Gerlicher, Klaus
2024-10-22 11:59 ` [PING V4][PATCH " Gerlicher, Klaus
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20240709150410.34624-6-natalia.saiapova@intel.com \
--to=natalia.saiapova@intel.com \
--cc=gdb-patches@sourceware.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).