* [PING PATCH v8 0/6] gdb: refine scheduler locking settings
@ 2026-07-22 10:27 Klaus Gerlicher
2026-07-22 10:27 ` [PATCH v8 1/6] gdb: use schedlock_applies in user_visible_resume_ptid Klaus Gerlicher
` (5 more replies)
0 siblings, 6 replies; 15+ messages in thread
From: Klaus Gerlicher @ 2026-07-22 10:27 UTC (permalink / raw)
To: gdb-patches; +Cc: tom, guinevere, eliz
From: "Gerlicher, Klaus" <klaus.gerlicher@intel.com>
Hi,
kindly pinging on this long-standing patch series to refine scheduler locking
settings in GDB.
This is version 8 of the patch series to refine scheduler locking
settings in GDB.
Previous versions:
V7: https://inbox.sourceware.org/gdb-patches/20260325134328.550990-1-klaus.gerlicher@intel.com/
V6: https://inbox.sourceware.org/gdb-patches/20260204133753.547281-1-klaus.gerlicher@intel.com/
V5: https://inbox.sourceware.org/gdb-patches/20260129095918.2216661-1-klaus.gerlicher@intel.com/
V4: https://inbox.sourceware.org/gdb-patches/20251205135851.2581702-1-klaus.gerlicher@intel.com/
V3: https://inbox.sourceware.org/gdb-patches/20250811132321.486911-1-klaus.gerlicher@intel.com/
Changes since V7:
-----------------
* Rebased onto current master.
Approval status:
Patch 1/6: Approved-By: Tom Tromey <tom@tromey.com>
https://inbox.sourceware.org/gdb-patches/87a4xu9733.fsf@tromey.com/
Patch 2/6: (unchanged from V5, no review comments)
https://inbox.sourceware.org/gdb-patches/20260129095918.2216661-3-klaus.gerlicher@intel.com/
Patch 3/6: Approved-By: Tom Tromey <tom@tromey.com>
https://inbox.sourceware.org/gdb-patches/875x8i970d.fsf@tromey.com/
Patch 4/6: (unchanged from V5, no review comments)
https://inbox.sourceware.org/gdb-patches/20260129095918.2216661-5-klaus.gerlicher@intel.com/
Patch 5/6: Reviewed-By: Eli Zaretskii <eliz@gnu.org> (documentation parts)
https://inbox.sourceware.org/gdb-patches/86ttb4t6kz.fsf@gnu.org/
Patch 6/6: Reviewed-By: Eli Zaretskii <eliz@gnu.org> (documentation parts)
https://inbox.sourceware.org/gdb-patches/86ldx8t6ex.fsf@gnu.org/
Overall series: Reviewed-By: Guinevere Larsen <guinevere@redhat.com>
https://inbox.sourceware.org/gdb-patches/bc6fd851-29c1-436e-a833-a53c0cf5a18d@redhat.com/
Thanks to all reviewers for their thorough feedback throughout the
v3, v4, v5, v6, and v7 iterations.
Best regards,
Klaus
Natalia Saiapova (6):
gdb: use schedlock_applies in user_visible_resume_ptid.
gdb, cli: remove left-over code from "set_logging_on".
gdb, cli: pass the argument of a set command to its callback.
gdb: change the internal representation of scheduler locking.
gdb: refine commands to control scheduler locking.
gdb: add eval option to lock the scheduler during infcalls.
gdb/NEWS | 26 ++
gdb/cli/cli-logging.c | 5 -
gdb/cli/cli-setshow.c | 2 +-
gdb/doc/gdb.texinfo | 77 +++-
gdb/infrun.c | 414 +++++++++++++++---
.../gdb.mi/user-selected-context-sync.exp | 23 +-
.../gdb.threads/hand-call-in-threads.exp | 12 +-
.../multiple-successive-infcall.exp | 7 +-
gdb/testsuite/gdb.threads/schedlock.exp | 105 ++++-
gdb/testsuite/lib/gdb.exp | 71 ++-
10 files changed, 621 insertions(+), 121 deletions(-)
--
2.34.1
Intel Deutschland GmbH
Registered Address: Dornacher Strasse 1, 85622 Feldkirchen, Germany
Tel: +49 89 991 430, www.intel.de
Managing Directors: Harry Demas, Jeffrey Schneiderman, Yin Chong Sorrell
Chairperson of the Supervisory Board: Nicole Lau
Registered Seat: Munich
Commercial Register: Amtsgericht Muenchen HRB 186928
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH v8 1/6] gdb: use schedlock_applies in user_visible_resume_ptid.
2026-07-22 10:27 [PING PATCH v8 0/6] gdb: refine scheduler locking settings Klaus Gerlicher
@ 2026-07-22 10:27 ` Klaus Gerlicher
2026-07-22 19:05 ` Andrew Burgess
2026-07-22 10:27 ` [PATCH v8 2/6] gdb, cli: remove left-over code from "set_logging_on" Klaus Gerlicher
` (4 subsequent siblings)
5 siblings, 1 reply; 15+ messages in thread
From: Klaus Gerlicher @ 2026-07-22 10:27 UTC (permalink / raw)
To: gdb-patches; +Cc: tom, guinevere, eliz
From: Natalia Saiapova <natalia.saiapova@intel.com>
This is a refactoring. The logic in user_visible_resume_ptid is very
similar to schedlock_applies, but uses `step` and `record_will_replay`
parameter instead of `tp->control.stepping_command`.
Refactor schedlock_applies logic into the following two overloaded methods:
bool schedlock_applies (thread_info *tp)
and
bool schedlock_applies (bool step, bool record_will_replay)
such that they share the logic.
Update the call-sites accordingly, where we have only the thread, use
the former, and where we have the bool step or record_will_replay use the
latter.
Approved-By: Tom Tromey <tom@tromey.com>
---
gdb/infrun.c | 40 +++++++++++++++++++++++++---------------
1 file changed, 25 insertions(+), 15 deletions(-)
diff --git a/gdb/infrun.c b/gdb/infrun.c
index c0767e7f764..ace34507cfe 100644
--- a/gdb/infrun.c
+++ b/gdb/infrun.c
@@ -108,6 +108,7 @@ static bool start_step_over (void);
static bool step_over_info_valid_p (void);
static bool schedlock_applies (struct thread_info *tp);
+static bool schedlock_applies (bool step, bool record_will_replay);
static void handle_process_exited (struct execution_control_state *ecs);
@@ -2442,20 +2443,14 @@ user_visible_resume_ptid (int step)
individually. */
resume_ptid = inferior_ptid;
}
- else if ((scheduler_mode == schedlock_on)
- || (scheduler_mode == schedlock_step && step))
+ else if (schedlock_applies (step,
+ target_record_will_replay (inferior_ptid,
+ execution_direction)))
{
/* User-settable 'scheduler' mode requires solo thread
resume. */
resume_ptid = inferior_ptid;
}
- else if ((scheduler_mode == schedlock_replay)
- && target_record_will_replay (inferior_ptid, execution_direction))
- {
- /* User-settable 'scheduler' mode requires solo thread resume in replay
- mode. */
- resume_ptid = inferior_ptid;
- }
else if (inferior_ptid != null_ptid
&& inferior_thread ()->control.in_cond_eval)
{
@@ -3246,17 +3241,32 @@ thread_still_needs_step_over (struct thread_info *tp)
return what;
}
+/* Returns true if scheduler locking applies to TP. */
+
+static bool
+schedlock_applies (thread_info *tp)
+{
+ bool step = false;
+ bool record_will_replay = false;
+ if (tp != nullptr)
+ {
+ step = tp->control.stepping_command;
+ record_will_replay
+ = target_record_will_replay (tp->ptid, execution_direction);
+ }
+ return schedlock_applies (step, record_will_replay);
+}
+
/* Returns true if scheduler locking applies. STEP indicates whether
- we're about to do a step/next-like command to a thread. */
+ we're about to do a step/next-like command and RECORD_WILL_REPLAY
+ indicates whether we're about to replay. */
static bool
-schedlock_applies (struct thread_info *tp)
+schedlock_applies (bool step, bool record_will_replay)
{
return (scheduler_mode == schedlock_on
- || (scheduler_mode == schedlock_step
- && tp->control.stepping_command)
- || (scheduler_mode == schedlock_replay
- && target_record_will_replay (tp->ptid, execution_direction)));
+ || (scheduler_mode == schedlock_step && step)
+ || (scheduler_mode == schedlock_replay && record_will_replay));
}
/* When FORCE_P is false, set process_stratum_target::COMMIT_RESUMED_STATE
--
2.34.1
Intel Deutschland GmbH
Registered Address: Dornacher Strasse 1, 85622 Feldkirchen, Germany
Tel: +49 89 991 430, www.intel.de
Managing Directors: Harry Demas, Jeffrey Schneiderman, Yin Chong Sorrell
Chairperson of the Supervisory Board: Nicole Lau
Registered Seat: Munich
Commercial Register: Amtsgericht Muenchen HRB 186928
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH v8 2/6] gdb, cli: remove left-over code from "set_logging_on".
2026-07-22 10:27 [PING PATCH v8 0/6] gdb: refine scheduler locking settings Klaus Gerlicher
2026-07-22 10:27 ` [PATCH v8 1/6] gdb: use schedlock_applies in user_visible_resume_ptid Klaus Gerlicher
@ 2026-07-22 10:27 ` Klaus Gerlicher
2026-07-22 19:13 ` Andrew Burgess
2026-07-22 10:27 ` [PATCH v8 3/6] gdb, cli: pass the argument of a set command to its callback Klaus Gerlicher
` (3 subsequent siblings)
5 siblings, 1 reply; 15+ messages in thread
From: Klaus Gerlicher @ 2026-07-22 10:27 UTC (permalink / raw)
To: gdb-patches; +Cc: tom, guinevere, eliz
From: Natalia Saiapova <natalia.saiapova@intel.com>
This is a refactoring. Remove the left-over code, which rewrites
the logging filename in "set logging on" command.
The code became unused after the deprecation of "set logging (on|off)"
command. Before the deprecation, the command could also take a file
name and rewrite the logging file, e.g.:
(gdb) set logging on lalala
Copying output to lalala.
Copying debug output to lalala.
After the command was deprecated and reimplemented as an alias to "set
logging enable on", additional input after "on" became invalid:
(gdb) set logging on lalala
Warning: 'set logging on', an alias for the command 'set logging enabled', is deprecated.
Use 'set logging enabled on'.
"on" or "off" expected.
(gdb) set logging on lalala
"on" or "off" expected.
(gdb) set logging enable on lalala
"on" or "off" expected.
(gdb) set logging enable on
Copying output to gdb.txt.
Copying debug output to gdb.txt.
---
gdb/cli/cli-logging.c | 5 -----
1 file changed, 5 deletions(-)
diff --git a/gdb/cli/cli-logging.c b/gdb/cli/cli-logging.c
index c9482d59199..33bb42bb444 100644
--- a/gdb/cli/cli-logging.c
+++ b/gdb/cli/cli-logging.c
@@ -270,11 +270,6 @@ handle_redirections (int from_tty)
static void
set_logging_on (const char *args, int from_tty)
{
- const char *rest = args;
-
- if (rest && *rest)
- logging_filename = rest;
-
handle_redirections (from_tty);
}
--
2.34.1
Intel Deutschland GmbH
Registered Address: Dornacher Strasse 1, 85622 Feldkirchen, Germany
Tel: +49 89 991 430, www.intel.de
Managing Directors: Harry Demas, Jeffrey Schneiderman, Yin Chong Sorrell
Chairperson of the Supervisory Board: Nicole Lau
Registered Seat: Munich
Commercial Register: Amtsgericht Muenchen HRB 186928
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH v8 3/6] gdb, cli: pass the argument of a set command to its callback.
2026-07-22 10:27 [PING PATCH v8 0/6] gdb: refine scheduler locking settings Klaus Gerlicher
2026-07-22 10:27 ` [PATCH v8 1/6] gdb: use schedlock_applies in user_visible_resume_ptid Klaus Gerlicher
2026-07-22 10:27 ` [PATCH v8 2/6] gdb, cli: remove left-over code from "set_logging_on" Klaus Gerlicher
@ 2026-07-22 10:27 ` Klaus Gerlicher
2026-07-22 20:16 ` Andrew Burgess
2026-07-22 10:27 ` [PATCH v8 4/6] gdb: change the internal representation of scheduler locking Klaus Gerlicher
` (2 subsequent siblings)
5 siblings, 1 reply; 15+ messages in thread
From: Klaus Gerlicher @ 2026-07-22 10:27 UTC (permalink / raw)
To: gdb-patches; +Cc: tom, guinevere, eliz
From: Natalia Saiapova <natalia.saiapova@intel.com>
This might be useful, if some commands need to have a special case if
run w/o arguments.
I am going to use it in
gdb: refine commands to control scheduler locking.
to keep the old behaviour of the
set scheduler-locking step
which should set both
set scheduler-locking step on
set scheduler-locking replay step on
To do this, the set-command needs to detect that it was issued without
arguments and have a special handling for this.
Without the special handling, the command
set scheduler-locking step
would set only
set scheduler-locking step on
Approved-By: Tom Tromey <tom@tromey.com>
---
gdb/cli/cli-setshow.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/gdb/cli/cli-setshow.c b/gdb/cli/cli-setshow.c
index 7688da015de..f1f313a4cd0 100644
--- a/gdb/cli/cli-setshow.c
+++ b/gdb/cli/cli-setshow.c
@@ -455,7 +455,7 @@ do_set_command (const char *arg, int from_tty, struct cmd_list_element *c)
error (_("gdb internal error: bad var_type in do_setshow_command"));
}
- c->func (NULL, from_tty, c);
+ c->func (arg, from_tty, c);
if (notify_command_param_changed_p (option_changed, c))
{
--
2.34.1
Intel Deutschland GmbH
Registered Address: Dornacher Strasse 1, 85622 Feldkirchen, Germany
Tel: +49 89 991 430, www.intel.de
Managing Directors: Harry Demas, Jeffrey Schneiderman, Yin Chong Sorrell
Chairperson of the Supervisory Board: Nicole Lau
Registered Seat: Munich
Commercial Register: Amtsgericht Muenchen HRB 186928
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH v8 4/6] gdb: change the internal representation of scheduler locking.
2026-07-22 10:27 [PING PATCH v8 0/6] gdb: refine scheduler locking settings Klaus Gerlicher
` (2 preceding siblings ...)
2026-07-22 10:27 ` [PATCH v8 3/6] gdb, cli: pass the argument of a set command to its callback Klaus Gerlicher
@ 2026-07-22 10:27 ` Klaus Gerlicher
2026-07-23 13:48 ` Andrew Burgess
2026-07-22 10:27 ` [PATCH v8 5/6] gdb: refine commands to control " Klaus Gerlicher
2026-07-22 10:27 ` [PATCH v8 6/6] gdb: add eval option to lock the scheduler during infcalls Klaus Gerlicher
5 siblings, 1 reply; 15+ messages in thread
From: Klaus Gerlicher @ 2026-07-22 10:27 UTC (permalink / raw)
To: gdb-patches; +Cc: tom, guinevere, eliz
From: Natalia Saiapova <natalia.saiapova@intel.com>
Introduce a new structure to manage different options of the scheduler
locking. The options can coexist together and be set individually.
In the next patch
gdb: refine commands to control scheduler locking.
we introduce the commands to control these options. In this patch we do
not introduce new commands and keep the previous API.
New scheduler locking options are:
replay continue -- control continuing commands during replay mode.
replay step -- control stepping commands during replay mode.
continue -- control continuing commands during normal execution.
step -- control stepping commands during normal execution.
Internally they hold a bool value, when true the locking is enabled.
Mapping to the old settings
Old Settings | New settings
-----------------------------------
off | all are false
|
replay | continue = false, step = false,
| replay continue = true, replay step = true
|
step | continue = false, step = true,
| replay continue = false, replay step = true
|
on | all are true
---
gdb/infrun.c | 147 ++++++++++++++++++++++++++++++++++++++++++++++-----
1 file changed, 134 insertions(+), 13 deletions(-)
diff --git a/gdb/infrun.c b/gdb/infrun.c
index ace34507cfe..0eb890bbbc1 100644
--- a/gdb/infrun.c
+++ b/gdb/infrun.c
@@ -107,8 +107,12 @@ static bool start_step_over (void);
static bool step_over_info_valid_p (void);
-static bool schedlock_applies (struct thread_info *tp);
-static bool schedlock_applies (bool step, bool record_will_replay);
+struct schedlock_options;
+static bool schedlock_applies (thread_info *tp);
+static bool schedlock_applies (bool step,
+ bool record_will_replay,
+ thread_info *tp = nullptr);
+static bool schedlock_applies_to_opts (const schedlock_options &, bool step);
static void handle_process_exited (struct execution_control_state *ecs);
@@ -2373,7 +2377,69 @@ infrun_thread_ptid_changed (process_stratum_target *target,
inferior_ptid = new_ptid;
}
-\f
+/* A structure to hold scheduler locking settings for
+ a mode, replay or normal. */
+struct schedlock_options
+{
+ struct option {
+ const std::string name;
+ bool value;
+
+ option () = delete;
+ option (std::string name, bool value)
+ : name (std::move (name)), value (value)
+ {}
+
+ /* Forbid accidential copying. */
+ option (const option &) = delete;
+ option operator= (const option &) = delete;
+ option (option &&) = default;
+ option &operator= (option &&) = default;
+
+ operator bool () const { return value; }
+ const char *c_str () const { return value ? "on" : "off"; }
+ /* Set new value. Return true, if the value has changed. */
+ bool set (bool new_value);
+ };
+
+ schedlock_options () = delete;
+ schedlock_options (option cont, option step)
+ : cont (std::move (cont)), step (std::move (step))
+ {}
+
+ /* Forbid accidential copying. */
+ schedlock_options (const schedlock_options &) = delete;
+ schedlock_options operator= (const schedlock_options &) = delete;
+ schedlock_options (schedlock_options &&) = default;
+ schedlock_options &operator= (schedlock_options &&) = default;
+
+ /* If true, the scheduler is locked during continuing. */
+ option cont;
+ /* If true, the scheduler is locked during stepping. */
+ option step;
+};
+
+bool
+schedlock_options::option::set (bool new_value)
+{
+ if (value != new_value)
+ {
+ value = new_value;
+ return true;
+ }
+
+ return false;
+}
+
+struct schedlock
+{
+ schedlock (schedlock_options opt, schedlock_options replay_opt)
+ : normal (std::move (opt)), replay (std::move (replay_opt))
+ {}
+
+ schedlock_options normal;
+ schedlock_options replay;
+};
static const char schedlock_off[] = "off";
static const char schedlock_on[] = "on";
@@ -2386,7 +2452,42 @@ static const char *const scheduler_enums[] = {
schedlock_replay,
nullptr
};
+
static const char *scheduler_mode = schedlock_replay;
+
+schedlock schedlock {
+ {
+ {"cont", false},
+ {"step", false}
+ },
+ {
+ {"replay cont", true},
+ {"replay step", true}
+ }
+};
+
+/* A helper function to set scheduler locking shortcuts:
+ set scheduler-locking on: all options are on.
+ set scheduler-locking off: all options are off.
+ set scheduler-locking replay: only replay options are on.
+ set scheduler-locking step: only "step" and "replay step" are on. */
+
+static void
+set_schedlock_shortcut_option (const char *shortcut)
+{
+ bool is_on = (shortcut == schedlock_on);
+ bool is_step = (shortcut == schedlock_step);
+ bool is_replay = (shortcut == schedlock_replay);
+ bool is_off = (shortcut == schedlock_off);
+ /* Check that we got a valid shortcut option. */
+ gdb_assert (is_on || is_step || is_replay || is_off);
+
+ schedlock.normal.cont.set (is_on);
+ schedlock.normal.step.set (is_on || is_step);
+ schedlock.replay.cont.set (is_on || is_replay);
+ schedlock.replay.step.set (is_on || is_replay || is_step);
+}
+
static void
show_scheduler_mode (struct ui_file *file, int from_tty,
struct cmd_list_element *c, const char *value)
@@ -2403,9 +2504,13 @@ set_schedlock_func (const char *args, int from_tty, struct 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 ());
}
+
+ set_schedlock_shortcut_option (scheduler_mode);
}
/* True if execution commands resume all threads of all processes by
@@ -2436,6 +2541,10 @@ ptid_t
user_visible_resume_ptid (int step)
{
ptid_t resume_ptid;
+ thread_info *tp = nullptr;
+
+ if (inferior_ptid != null_ptid)
+ tp = inferior_thread ();
if (non_stop)
{
@@ -2445,14 +2554,14 @@ user_visible_resume_ptid (int step)
}
else if (schedlock_applies (step,
target_record_will_replay (inferior_ptid,
- execution_direction)))
+ execution_direction),
+ tp))
{
/* User-settable 'scheduler' mode requires solo thread
resume. */
resume_ptid = inferior_ptid;
}
- else if (inferior_ptid != null_ptid
- && inferior_thread ()->control.in_cond_eval)
+ else if (tp != nullptr && tp->control.in_cond_eval)
{
/* The inferior thread is evaluating a BP condition. Other threads
might be stopped or running and we do not want to change their
@@ -3164,8 +3273,9 @@ clear_proceed_status (int step, bool about_to_proceed)
This is a convenience feature to not require the user to explicitly
stop replaying the other threads. We're assuming that the user's
intent is to resume tracing the recorded process. */
- if (!non_stop && scheduler_mode == schedlock_replay
- && !target_record_will_replay (inferior_ptid, execution_direction))
+ if (!non_stop && schedlock_applies_to_opts (schedlock.replay, step)
+ && !target_record_will_replay (inferior_ptid,
+ execution_direction))
target_record_stop_replaying ();
if (!non_stop && inferior_ptid != null_ptid)
@@ -3241,6 +3351,17 @@ thread_still_needs_step_over (struct thread_info *tp)
return what;
}
+/* Return true if OPTS lock the scheduler.
+ STEP indicates whether a thread is about to step.
+ Note, this does not take into the account the mode (replay or
+ normal execution). */
+
+static bool
+schedlock_applies_to_opts (const schedlock_options &opts, bool step)
+{
+ return ((opts.cont && !step) || (opts.step && step));
+}
+
/* Returns true if scheduler locking applies to TP. */
static bool
@@ -3254,7 +3375,7 @@ schedlock_applies (thread_info *tp)
record_will_replay
= target_record_will_replay (tp->ptid, execution_direction);
}
- return schedlock_applies (step, record_will_replay);
+ return schedlock_applies (step, record_will_replay, tp);
}
/* Returns true if scheduler locking applies. STEP indicates whether
@@ -3262,11 +3383,11 @@ schedlock_applies (thread_info *tp)
indicates whether we're about to replay. */
static bool
-schedlock_applies (bool step, bool record_will_replay)
+schedlock_applies (bool step, bool record_will_replay, thread_info *tp)
{
- return (scheduler_mode == schedlock_on
- || (scheduler_mode == schedlock_step && step)
- || (scheduler_mode == schedlock_replay && record_will_replay));
+ schedlock_options &opts
+ = record_will_replay ? schedlock.replay : schedlock.normal;
+ return schedlock_applies_to_opts (opts, step);
}
/* When FORCE_P is false, set process_stratum_target::COMMIT_RESUMED_STATE
--
2.34.1
Intel Deutschland GmbH
Registered Address: Dornacher Strasse 1, 85622 Feldkirchen, Germany
Tel: +49 89 991 430, www.intel.de
Managing Directors: Harry Demas, Jeffrey Schneiderman, Yin Chong Sorrell
Chairperson of the Supervisory Board: Nicole Lau
Registered Seat: Munich
Commercial Register: Amtsgericht Muenchen HRB 186928
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH v8 5/6] gdb: refine commands to control scheduler locking.
2026-07-22 10:27 [PING PATCH v8 0/6] gdb: refine scheduler locking settings Klaus Gerlicher
` (3 preceding siblings ...)
2026-07-22 10:27 ` [PATCH v8 4/6] gdb: change the internal representation of scheduler locking Klaus Gerlicher
@ 2026-07-22 10:27 ` Klaus Gerlicher
2026-07-23 16:39 ` Andrew Burgess
2026-07-24 9:34 ` Andrew Burgess
2026-07-22 10:27 ` [PATCH v8 6/6] gdb: add eval option to lock the scheduler during infcalls Klaus Gerlicher
5 siblings, 2 replies; 15+ messages in thread
From: Klaus Gerlicher @ 2026-07-22 10:27 UTC (permalink / raw)
To: gdb-patches; +Cc: tom, guinevere, eliz
From: Natalia Saiapova <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 <continue | replay step | replay continue | step> <on | off>
show scheduler-locking <continue | replay step | replay continue | 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 continue off
set scheduler-locking replay continue off
set scheduler-locking replay step on
set scheduler-locking step on
set scheduler-locking on
is equivalent to
set scheduler-locking continue on
set scheduler-locking replay continue on
set scheduler-locking replay step on
set scheduler-locking step on
set scheduler-locking replay
is equivalent to
set scheduler-locking continue off
set scheduler-locking replay continue on
set scheduler-locking replay step on
set scheduler-locking step off
set scheduler-locking off
is equivalent to
set scheduler-locking continue off
set scheduler-locking replay continue 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 continue: "off" Scheduler locking for continuing
commands is "off" during normal execution.
scheduler-locking replay continue: "on" Scheduler locking for
continuing 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 continue: "on" Scheduler locking for
continuing 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 continue
"off" Scheduler locking for continuing 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 | 21 ++
gdb/doc/gdb.texinfo | 66 +++++-
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, 397 insertions(+), 102 deletions(-)
diff --git a/gdb/NEWS b/gdb/NEWS
index 8f40ca5cb11..30d0637518b 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -902,6 +902,27 @@ 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:
+ continue | replay continue | 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 continuing commands. Stepping commands include step, stepi,
+ next. Continuing commands include continue, finish, until, jump, return.
+ 'continue' -- when on, the scheduler is locked during continuing commands
+ in normal mode.
+ 'replay continue' -- when on, the scheduler is locked during continuing
+ 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 0030698dcee..fbf0f6e1da6 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -7456,28 +7456,63 @@ 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 continuing commands. Examples of stepping commands are:
+@samp{step}, @samp{stepi}, @samp{next}. Examples of continuing commands are
+@samp{continue}, @samp{finish}, @samp{jump}, @samp{until}, @samp{return} or
+inferior function calls.
+
+The following @var{type}-settings are available. When a setting is
+@code{on}, the scheduler is locked: other threads may not preempt the
+current thread, so that the focus of debugging does not change unexpectedly.
+
+@table @code
+@item continue
+Applies to continuing commands during normal execution and record modes.
+This setting is @code{off} by default.
+
+@item replay continue
+Applies to continuing commands during replay mode. This setting is
+@code{on} by default.
+
+@item replay step
+Applies to stepping commands during replay mode. This setting is
+@code{on} by default.
+
+@item step
+Applies to stepping commands during normal execution and record modes.
+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 continuing
+commands.
This mode optimizes for single-stepping; it prevents other threads
from preempting the current thread while you are stepping, so that the
@@ -7486,9 +7521,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 continue} and
+@samp{scheduler-locking replay step} to @code{on}, while other settings
+are @code{off}.
+
@end table
@item show scheduler-locking
@@ -34703,7 +34747,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 0eb890bbbc1..b6f7721dbf3 100644
--- a/gdb/infrun.c
+++ b/gdb/infrun.c
@@ -75,6 +75,8 @@
#include "extension.h"
#include "disasm.h"
#include "interps.h"
+#include "cli/cli-decode.h"
+#include <set>
#include "finish-thread-state.h"
#include "buffered-streams.h"
@@ -116,6 +118,12 @@ static bool schedlock_applies_to_opts (const schedlock_options &, bool step);
static void handle_process_exited (struct execution_control_state *ecs);
+/* 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;
@@ -2398,7 +2406,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);
};
@@ -2425,6 +2434,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;
}
@@ -2445,15 +2457,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 {
{
@@ -2482,35 +2485,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.cont.set (is_on);
- schedlock.normal.step.set (is_on || is_step);
- schedlock.replay.cont.set (is_on || is_replay);
- schedlock.replay.step.set (is_on || is_replay || is_step);
+ bool any_changed = schedlock.normal.cont.set (is_on);
+ any_changed = schedlock.normal.step.set (is_on || is_step) || any_changed;
+ any_changed = schedlock.replay.cont.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, "continue") == 0)
+ type = "continuing 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
@@ -8648,15 +8705,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;
@@ -11023,21 +11072,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 ("continue", class_run, &schedlock.normal.cont.value, _("\
+Scheduler locking for continuing commands during normal execution."), _("\
+Show scheduler locking for continuing commands during normal execution."),
+ _("\
+Controls scheduler locking for continuing 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 ("continue", class_run, &schedlock.replay.cont.value, _("\
+Set scheduler locking for continuing commands in replay mode."), _("\
+Show scheduler locking for continuing commands in replay mode."), _("\
+Controls scheduler locking for continuing 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 7555469b579..b7f813320c1 100644
--- a/gdb/testsuite/gdb.mi/user-selected-context-sync.exp
+++ b/gdb/testsuite/gdb.mi/user-selected-context-sync.exp
@@ -257,17 +257,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."
@@ -313,7 +308,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.
@@ -344,7 +339,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 {"continue" "replay continue" "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 2f5eaa5405b..75be13c4c4d 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 "continue" "on" "replay continue" "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 "continue" "off" "replay continue" "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 fdcbaa47c7f..0a33550c65b 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 \"continue\" \"on\" \"replay continue\" \"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 61a9d5ddef5..cda4585ca08 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 != ""} {
@@ -268,16 +269,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"
}
@@ -288,16 +294,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" {
@@ -316,3 +324,57 @@ foreach schedlock {"off" "step" "on"} {
}
}
}
+
+proc test_schedlock_opts {cont step} {
+ set test "show scheduler-locking"
+ if {[get_scheduler_locking $test \
+ [dict create "continue" $cont "replay continue" "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 {$cont 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 cont {"off" "on"} {
+ foreach step {"off" "on"} {
+ with_test_prefix "continue=$cont step=$step" {
+ gdb_test_no_output "set scheduler-locking continue $cont"
+ gdb_test_no_output "set scheduler-locking step $step"
+ test_schedlock_opts $cont $step
+ }
+ }
+}
diff --git a/gdb/testsuite/lib/gdb.exp b/gdb/testsuite/lib/gdb.exp
index a40c87c6727..e852fd1b99a 100644
--- a/gdb/testsuite/lib/gdb.exp
+++ b/gdb/testsuite/lib/gdb.exp
@@ -10192,6 +10192,52 @@ gdb_caching_proc gdb_target_symbol_prefix {} {
return $prefix
}
+# Return a dictionary of scheduler locking settings with keys:
+# continue, replay continue, 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 {"continue" "replay continue" "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 {} {
@@ -10211,28 +10257,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.34.1
Intel Deutschland GmbH
Registered Address: Dornacher Strasse 1, 85622 Feldkirchen, Germany
Tel: +49 89 991 430, www.intel.de
Managing Directors: Harry Demas, Jeffrey Schneiderman, Yin Chong Sorrell
Chairperson of the Supervisory Board: Nicole Lau
Registered Seat: Munich
Commercial Register: Amtsgericht Muenchen HRB 186928
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH v8 6/6] gdb: add eval option to lock the scheduler during infcalls.
2026-07-22 10:27 [PING PATCH v8 0/6] gdb: refine scheduler locking settings Klaus Gerlicher
` (4 preceding siblings ...)
2026-07-22 10:27 ` [PATCH v8 5/6] gdb: refine commands to control " Klaus Gerlicher
@ 2026-07-22 10:27 ` Klaus Gerlicher
2026-07-24 9:52 ` Andrew Burgess
5 siblings, 1 reply; 15+ messages in thread
From: Klaus Gerlicher @ 2026-07-22 10:27 UTC (permalink / raw)
To: gdb-patches; +Cc: tom, guinevere, eliz
From: Natalia Saiapova <natalia.saiapova@intel.com>
This patch adds an "eval" scheduler locking setting to control inferior
function calls separately from other continuing commands.
"continue" handles continuing commands, such as continue, until, return,
finish, jump.
"eval" handles inferior calls.
Show scheduler locking:
(gdb) show scheduler-locking
scheduler-locking continue: "off" Scheduler locking for continuing
commands is "off" during normal execution.
scheduler-locking eval: "off" Scheduler locking for function calls
is "off" during normal execution.
scheduler-locking replay continue: "on" Scheduler locking for
continuing commands is "on" during replay mode.
scheduler-locking replay eval: "on" Scheduler locking for function
calls 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.
Reviewed-By: Eli Zaretskii <eliz@gnu.org>
---
gdb/NEWS | 13 ++--
gdb/doc/gdb.texinfo | 25 +++++---
gdb/infrun.c | 61 +++++++++++++++----
.../gdb.mi/user-selected-context-sync.exp | 3 +-
.../gdb.threads/hand-call-in-threads.exp | 6 +-
.../multiple-successive-infcall.exp | 5 +-
gdb/testsuite/gdb.threads/schedlock.exp | 41 ++++++++++---
gdb/testsuite/lib/gdb.exp | 3 +-
8 files changed, 118 insertions(+), 39 deletions(-)
diff --git a/gdb/NEWS b/gdb/NEWS
index 30d0637518b..0a1f15c153e 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -905,15 +905,20 @@ list .
set scheduler-locking <command type> (on|off)
show scheduler-locking <command type>
where <command-type> is one of the following:
- continue | replay continue | 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 continuing commands. Stepping commands include step, stepi,
+ continue | eval | replay continue | replay eval | 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,
+ continuing and evaluating commands. Stepping commands include step, stepi,
next. Continuing commands include continue, finish, until, jump, return.
+ The evaluating commands are those which invoke inferior calls.
'continue' -- when on, the scheduler is locked during continuing commands
in normal mode.
+ 'eval' -- when on, the scheduler is locked during inferior calls in
+ normal mode.
'replay continue' -- when on, the scheduler is locked during continuing
commands in replay mode.
+ 'replay eval' -- when on, the scheduler is locked during inferior calls
+ 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
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index fbf0f6e1da6..03bbb63ecf6 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -7462,10 +7462,10 @@ locking the OS scheduler to allow only a single thread to run.
@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 continuing commands. Examples of stepping commands are:
-@samp{step}, @samp{stepi}, @samp{next}. Examples of continuing commands are
-@samp{continue}, @samp{finish}, @samp{jump}, @samp{until}, @samp{return} or
-inferior function calls.
+for continuing and stepping commands, as well as function calls.
+Examples of stepping commands are: @samp{step}, @samp{stepi}, @samp{next}.
+Examples of continuing commands are @samp{continue}, @samp{finish},
+@samp{jump}, @samp{until}, @samp{return}.
The following @var{type}-settings are available. When a setting is
@code{on}, the scheduler is locked: other threads may not preempt the
@@ -7476,10 +7476,21 @@ current thread, so that the focus of debugging does not change unexpectedly.
Applies to continuing commands during normal execution and record modes.
This setting is @code{off} by default.
+@item eval
+When @code{on}, the scheduler is locked for function calls during normal
+execution and record modes, such that other threads may not preempt
+the current thread during the inferior call. This setting is @code{off}
+by default.
+
@item replay continue
Applies to continuing commands during replay mode. This setting is
@code{on} by default.
+@item replay eval
+When @code{on}, the scheduler is locked for function calls during replay
+mode, such that other threads may not preempt the current thread during
+the inferior call. This setting is @code{on} by default.
+
@item replay step
Applies to stepping commands during replay mode. This setting is
@code{on} by default.
@@ -7529,9 +7540,9 @@ are @code{off}.
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 continue} and
-@samp{scheduler-locking replay step} to @code{on}, while other settings
-are @code{off}.
+This is equivalent to set @samp{scheduler-locking replay continue},
+@samp{scheduler-locking replay eval} and @samp{scheduler-locking replay step}
+to @code{on}, while other settings are @code{off}.
@end table
diff --git a/gdb/infrun.c b/gdb/infrun.c
index b6f7721dbf3..7f390d7db25 100644
--- a/gdb/infrun.c
+++ b/gdb/infrun.c
@@ -114,7 +114,9 @@ static bool schedlock_applies (thread_info *tp);
static bool schedlock_applies (bool step,
bool record_will_replay,
thread_info *tp = nullptr);
-static bool schedlock_applies_to_opts (const schedlock_options &, bool step);
+static bool schedlock_applies_to_opts (const schedlock_options &,
+ bool step,
+ thread_info *tp = nullptr);
static void handle_process_exited (struct execution_control_state *ecs);
@@ -2412,8 +2414,8 @@ struct schedlock_options
};
schedlock_options () = delete;
- schedlock_options (option cont, option step)
- : cont (std::move (cont)), step (std::move (step))
+ schedlock_options (option eval, option cont, option step)
+ : eval (std::move (eval)), cont (std::move (cont)), step (std::move (step))
{}
/* Forbid accidential copying. */
@@ -2422,6 +2424,8 @@ struct schedlock_options
schedlock_options (schedlock_options &&) = default;
schedlock_options &operator= (schedlock_options &&) = default;
+ /* If true, the scheduler is locked during inferior calls. */
+ option eval;
/* If true, the scheduler is locked during continuing. */
option cont;
/* If true, the scheduler is locked during stepping. */
@@ -2460,10 +2464,12 @@ static const char schedlock_replay[] = "replay";
schedlock schedlock {
{
+ {"eval", false},
{"cont", false},
{"step", false}
},
{
+ {"replay eval", true},
{"replay cont", true},
{"replay step", true}
}
@@ -2487,9 +2493,11 @@ set_schedlock_shortcut_option (const char *shortcut)
bool any_changed = schedlock.normal.cont.set (is_on);
any_changed = schedlock.normal.step.set (is_on || is_step) || any_changed;
+ any_changed = schedlock.normal.eval.set (is_on) || any_changed;
any_changed = schedlock.replay.cont.set (is_on || is_replay) || any_changed;
any_changed = schedlock.replay.step.set (is_on || is_replay || is_step)
|| any_changed;
+ any_changed = schedlock.replay.eval.set (is_on || is_replay) || any_changed;
/* If at least one parameter has changed, notify the observer
in the old-fashioned way. */
@@ -2563,11 +2571,13 @@ show_schedlock_option (ui_file *file, int from_tty,
type = "stepping commands";
else if (strcmp (c->name, "continue") == 0)
type = "continuing commands";
+ else if (strcmp (c->name, "eval") == 0)
+ type = "function calls";
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);
+ "\"%s\" during %s.\n"), value, type, value, mode);
}
/* True if execution commands resume all threads of all processes by
@@ -3410,13 +3420,20 @@ thread_still_needs_step_over (struct thread_info *tp)
/* Return true if OPTS lock the scheduler.
STEP indicates whether a thread is about to step.
+ While the stepping info we take from STEP argument, the inferior call
+ state we get from the thread TP.
Note, this does not take into the account the mode (replay or
normal execution). */
static bool
-schedlock_applies_to_opts (const schedlock_options &opts, bool step)
+schedlock_applies_to_opts (const schedlock_options &opts, bool step,
+ thread_info *tp)
{
- return ((opts.cont && !step) || (opts.step && step));
+ bool in_infcall = (tp != nullptr) && tp->control.in_infcall;
+
+ return ((opts.cont && !step && !in_infcall)
+ || (opts.step && step)
+ || (opts.eval && in_infcall));
}
/* Returns true if scheduler locking applies to TP. */
@@ -3444,7 +3461,7 @@ schedlock_applies (bool step, bool record_will_replay, thread_info *tp)
{
schedlock_options &opts
= record_will_replay ? schedlock.replay : schedlock.normal;
- return schedlock_applies_to_opts (opts, step);
+ return schedlock_applies_to_opts (opts, step, tp);
}
/* When FORCE_P is false, set process_stratum_target::COMMIT_RESUMED_STATE
@@ -11084,11 +11101,10 @@ Show scheduler locking settings in various conditions."),
add_setshow_boolean_cmd ("continue", class_run, &schedlock.normal.cont.value, _("\
Scheduler locking for continuing commands during normal execution."), _("\
-Show scheduler locking for continuing commands during normal execution."),
- _("\
+Show scheduler locking for continuing commands during normal execution."), _("\
Controls scheduler locking for continuing commands during normal execution.\n\
-Commands include continue, until, finish. The setting does not affect \
-stepping."),
+Commands include continue, until, finish. The setting does not affect\n\
+stepping and function calls."),
set_schedlock_callback,
show_schedlock_option,
&schedlock_set_cmdlist,
@@ -11106,6 +11122,16 @@ Commands include step, next, stepi, nexti."),
&schedlock_set_cmdlist,
&schedlock_show_cmdlist);
+ add_setshow_boolean_cmd ("eval", class_run, &schedlock.normal.eval.value, _("\
+Scheduler locking for function calls during normal execution."), _("\
+Show scheduler locking for function calls during normal execution."),
+ _("\
+Controls scheduler locking for function calls during normal execution."),
+ set_schedlock_callback,
+ 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
@@ -11130,8 +11156,8 @@ W/o arguments completely locks the scheduler in replay mode."),
Set scheduler locking for continuing commands in replay mode."), _("\
Show scheduler locking for continuing commands in replay mode."), _("\
Controls scheduler locking for continuing commands in replay mode.\n\
-Commands include continue, until, finish. The setting does not affect \
-stepping."),
+Commands include continue, until, finish. The setting does not affect\n\
+stepping and function calls."),
set_schedlock_callback,
show_schedlock_option,
&schedlock_set_replay_cmdlist,
@@ -11147,6 +11173,15 @@ Commands include step, next, stepi, nexti."),
&schedlock_set_replay_cmdlist,
&schedlock_show_replay_cmdlist);
+ add_setshow_boolean_cmd ("eval", class_run, &schedlock.replay.eval.value, _("\
+Set scheduler locking for function calls in replay mode."), _("\
+Show scheduler locking for function calls in replay mode."), _("\
+Controls scheduler locking for function calls in replay mode."),
+ 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, _("\
diff --git a/gdb/testsuite/gdb.mi/user-selected-context-sync.exp b/gdb/testsuite/gdb.mi/user-selected-context-sync.exp
index b7f813320c1..882c7201e12 100644
--- a/gdb/testsuite/gdb.mi/user-selected-context-sync.exp
+++ b/gdb/testsuite/gdb.mi/user-selected-context-sync.exp
@@ -339,7 +339,8 @@ proc test_continue_to_start { mode inf } {
}
# Restore scheduler-locking to its original value.
- foreach opt {"continue" "replay continue" "replay step" "step"} {
+ foreach opt {"continue" "eval" "replay continue" \
+ "replay eval" "replay step" "step"} {
gdb_test_no_output \
"set scheduler-locking $opt [dict get $previous_schedlock $opt]"
}
diff --git a/gdb/testsuite/gdb.threads/hand-call-in-threads.exp b/gdb/testsuite/gdb.threads/hand-call-in-threads.exp
index 75be13c4c4d..a145019286f 100644
--- a/gdb/testsuite/gdb.threads/hand-call-in-threads.exp
+++ b/gdb/testsuite/gdb.threads/hand-call-in-threads.exp
@@ -70,7 +70,8 @@ gdb_test "continue" \
gdb_test_no_output "set scheduler-locking on" "enable scheduler locking"
set test "show scheduler-locking on"
gdb_assert {[get_scheduler_locking $test \
- [dict create "continue" "on" "replay continue" "on" \
+ [dict create "continue" "on" "eval" "on" \
+ "replay continue" "on" "replay eval" "on" \
"replay step" "on" "step" "on"]] ne "unknown"} $test
# Now hand-call a function in each thread, having the function
@@ -144,7 +145,8 @@ gdb_test_multiple "maint print dummy-frames" "all dummies popped" {
gdb_test_no_output "set scheduler-locking off" "disable scheduler locking"
set test "show scheduler-locking off"
gdb_assert {[get_scheduler_locking $test \
- [dict create "continue" "off" "replay continue" "off" \
+ [dict create "continue" "off" "eval" "off" \
+ "replay continue" "off" "replay eval" "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 0a33550c65b..98e50c92713 100644
--- a/gdb/testsuite/gdb.threads/multiple-successive-infcall.exp
+++ b/gdb/testsuite/gdb.threads/multiple-successive-infcall.exp
@@ -51,8 +51,9 @@ gdb_continue_to_breakpoint "testmarker01"
gdb_test_no_output "set scheduler-locking on"
set test "show scheduler-locking"
gdb_assert {[get_scheduler_locking $test \
- [dict create \"continue\" \"on\" \"replay continue\" \"on\" \
- \"replay step\" \"on\" \"step\" \"on\"]] ne \"unknown\"} $test
+ [dict create "continue" "on" "eval" "on" \
+ "replay continue" "on" "replay eval" "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 cda4585ca08..58f8d9ae4de 100644
--- a/gdb/testsuite/gdb.threads/schedlock.exp
+++ b/gdb/testsuite/gdb.threads/schedlock.exp
@@ -228,7 +228,7 @@ proc check_result { cmd before_thread before_args locked } {
set num_other_threads 0
for {set i 0} {$i < $NUM} {incr i} {
if {[lindex $before_args $i] == [lindex $after_args $i]} {
- if {$i == $before_thread} {
+ if {$i == $before_thread && $cmd ne "infcall"} {
fail "$test (didn't run)"
}
} else {
@@ -325,11 +325,12 @@ foreach schedlock {"off" "step" "on"} {
}
}
-proc test_schedlock_opts {cont step} {
+proc test_schedlock_opts {cont eval step} {
set test "show scheduler-locking"
if {[get_scheduler_locking $test \
- [dict create "continue" $cont "replay continue" "off" \
- "replay step" "off" "step" $step]] eq "unknown"} {
+ [dict create "continue" $cont "eval" $eval \
+ "replay continue" "off" "replay eval" "off" \
+ "replay step" "off" "step" $step]] eq "unknown"} {
fail $test
} else {
pass $test
@@ -364,17 +365,39 @@ proc test_schedlock_opts {cont step} {
my_continue "continue"
check_result "continue" $curthread $cont_args $locked
}
+
+ # Infcall tests.
+ set locked 0
+ if {$eval eq "on"} {
+ set locked 1
+ }
+ with_test_prefix "cmd=infcall" {
+ # Use whichever we stopped in.
+ set curthread [get_current_thread "before-infcall"]
+ set cont_args [get_args "before-infcall"]
+
+ for {set i 0} {[expr $i < 10]} {set i [expr $i + 1]} {
+ with_test_prefix "infcall #$i" {
+ gdb_test "print some_function()" ".*"
+ }
+ }
+
+ check_result "infcall" $curthread $cont_args $locked
+ }
}
gdb_test_no_output "set scheduler-locking off"
# Test different options of scheduler locking.
foreach cont {"off" "on"} {
- foreach step {"off" "on"} {
- with_test_prefix "continue=$cont step=$step" {
- gdb_test_no_output "set scheduler-locking continue $cont"
- gdb_test_no_output "set scheduler-locking step $step"
- test_schedlock_opts $cont $step
+ foreach eval {"off" "on"} {
+ foreach step {"off" "on"} {
+ with_test_prefix "continue=$cont eval=$eval step=$step" {
+ gdb_test_no_output "set scheduler-locking continue $cont"
+ gdb_test_no_output "set scheduler-locking eval $eval"
+ gdb_test_no_output "set scheduler-locking step $step"
+ test_schedlock_opts $cont $eval $step
+ }
}
}
}
diff --git a/gdb/testsuite/lib/gdb.exp b/gdb/testsuite/lib/gdb.exp
index e852fd1b99a..d5652a8c6d7 100644
--- a/gdb/testsuite/lib/gdb.exp
+++ b/gdb/testsuite/lib/gdb.exp
@@ -10205,7 +10205,8 @@ proc get_scheduler_locking {{test ""} {expected ""}} {
set test "reading current scheduler-locking mode"
}
- set opts {"continue" "replay continue" "replay step" "step"}
+ set opts {"continue" "eval" "replay continue" "replay eval" \
+ "replay step" "step"}
# Fill the missing entries in EXPECTED list.
foreach opt $opts {
--
2.34.1
Intel Deutschland GmbH
Registered Address: Dornacher Strasse 1, 85622 Feldkirchen, Germany
Tel: +49 89 991 430, www.intel.de
Managing Directors: Harry Demas, Jeffrey Schneiderman, Yin Chong Sorrell
Chairperson of the Supervisory Board: Nicole Lau
Registered Seat: Munich
Commercial Register: Amtsgericht Muenchen HRB 186928
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH v8 1/6] gdb: use schedlock_applies in user_visible_resume_ptid.
2026-07-22 10:27 ` [PATCH v8 1/6] gdb: use schedlock_applies in user_visible_resume_ptid Klaus Gerlicher
@ 2026-07-22 19:05 ` Andrew Burgess
0 siblings, 0 replies; 15+ messages in thread
From: Andrew Burgess @ 2026-07-22 19:05 UTC (permalink / raw)
To: Klaus Gerlicher, gdb-patches; +Cc: tom, guinevere, eliz
Klaus Gerlicher <klaus.gerlicher@intel.com> writes:
> From: Natalia Saiapova <natalia.saiapova@intel.com>
>
> This is a refactoring. The logic in user_visible_resume_ptid is very
> similar to schedlock_applies, but uses `step` and `record_will_replay`
> parameter instead of `tp->control.stepping_command`.
>
> Refactor schedlock_applies logic into the following two overloaded methods:
> bool schedlock_applies (thread_info *tp)
> and
> bool schedlock_applies (bool step, bool record_will_replay)
> such that they share the logic.
>
> Update the call-sites accordingly, where we have only the thread, use
> the former, and where we have the bool step or record_will_replay use the
> latter.
>
> Approved-By: Tom Tromey <tom@tromey.com>
> ---
> gdb/infrun.c | 40 +++++++++++++++++++++++++---------------
> 1 file changed, 25 insertions(+), 15 deletions(-)
>
> diff --git a/gdb/infrun.c b/gdb/infrun.c
> index c0767e7f764..ace34507cfe 100644
> --- a/gdb/infrun.c
> +++ b/gdb/infrun.c
> @@ -108,6 +108,7 @@ static bool start_step_over (void);
> static bool step_over_info_valid_p (void);
>
> static bool schedlock_applies (struct thread_info *tp);
You dropped the 'struct' from the definition of this function. As
you're changing the next line anyway, maybe drop the 'struct' here too?
> +static bool schedlock_applies (bool step, bool record_will_replay);
>
> static void handle_process_exited (struct execution_control_state *ecs);
>
> @@ -2442,20 +2443,14 @@ user_visible_resume_ptid (int step)
> individually. */
> resume_ptid = inferior_ptid;
> }
> - else if ((scheduler_mode == schedlock_on)
> - || (scheduler_mode == schedlock_step && step))
> + else if (schedlock_applies (step,
> + target_record_will_replay (inferior_ptid,
> + execution_direction)))
> {
> /* User-settable 'scheduler' mode requires solo thread
> resume. */
> resume_ptid = inferior_ptid;
> }
> - else if ((scheduler_mode == schedlock_replay)
> - && target_record_will_replay (inferior_ptid, execution_direction))
> - {
> - /* User-settable 'scheduler' mode requires solo thread resume in replay
> - mode. */
> - resume_ptid = inferior_ptid;
> - }
> else if (inferior_ptid != null_ptid
> && inferior_thread ()->control.in_cond_eval)
> {
> @@ -3246,17 +3241,32 @@ thread_still_needs_step_over (struct thread_info *tp)
> return what;
> }
>
> +/* Returns true if scheduler locking applies to TP. */
> +
> +static bool
> +schedlock_applies (thread_info *tp)
> +{
> + bool step = false;
> + bool record_will_replay = false;
> + if (tp != nullptr)
> + {
> + step = tp->control.stepping_command;
> + record_will_replay
> + = target_record_will_replay (tp->ptid, execution_direction);
> + }
> + return schedlock_applies (step, record_will_replay);
> +}
As far as I can tell the old code didn't have the 'tp != nullptr' check,
and I think every call site already makes the assumption that tp is not
NULL (i.e. if it was NULL GDB would have already crashed).
I think you should just update the comment on this function to say:
"...applies to non-NULL thread TP." and add 'gdb_assert (tp !=
nullptr);' to the function body.
With that, it looks good.
Approved-By: Andrew Burgess <aburgess@redhat.com>
Thanks,
Andrew
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH v8 2/6] gdb, cli: remove left-over code from "set_logging_on".
2026-07-22 10:27 ` [PATCH v8 2/6] gdb, cli: remove left-over code from "set_logging_on" Klaus Gerlicher
@ 2026-07-22 19:13 ` Andrew Burgess
0 siblings, 0 replies; 15+ messages in thread
From: Andrew Burgess @ 2026-07-22 19:13 UTC (permalink / raw)
To: Klaus Gerlicher, gdb-patches; +Cc: tom, guinevere, eliz
Thanks for this clean up. One minor comment inline below.
Klaus Gerlicher <klaus.gerlicher@intel.com> writes:
> From: Natalia Saiapova <natalia.saiapova@intel.com>
>
> This is a refactoring. Remove the left-over code, which rewrites
> the logging filename in "set logging on" command.
>
> The code became unused after the deprecation of "set logging (on|off)"
> command. Before the deprecation, the command could also take a file
> name and rewrite the logging file, e.g.:
> (gdb) set logging on lalala
> Copying output to lalala.
> Copying debug output to lalala.
>
> After the command was deprecated and reimplemented as an alias to "set
> logging enable on", additional input after "on" became invalid:
Here and in two additional places below you say 'enable' instead of
'enabled'. I know 'enable' works fine due to prefix matching, but for
commit messages I think it's best to be accurate.
With that fixed:
Approved-By: Andrew Burgess <aburgess@redhat.com>
Thanks,
Andrew
>
> (gdb) set logging on lalala
> Warning: 'set logging on', an alias for the command 'set logging enabled', is deprecated.
> Use 'set logging enabled on'.
>
> "on" or "off" expected.
> (gdb) set logging on lalala
> "on" or "off" expected.
> (gdb) set logging enable on lalala
> "on" or "off" expected.
> (gdb) set logging enable on
> Copying output to gdb.txt.
> Copying debug output to gdb.txt.
> ---
> gdb/cli/cli-logging.c | 5 -----
> 1 file changed, 5 deletions(-)
>
> diff --git a/gdb/cli/cli-logging.c b/gdb/cli/cli-logging.c
> index c9482d59199..33bb42bb444 100644
> --- a/gdb/cli/cli-logging.c
> +++ b/gdb/cli/cli-logging.c
> @@ -270,11 +270,6 @@ handle_redirections (int from_tty)
> static void
> set_logging_on (const char *args, int from_tty)
> {
> - const char *rest = args;
> -
> - if (rest && *rest)
> - logging_filename = rest;
> -
> handle_redirections (from_tty);
> }
>
> --
> 2.34.1
>
> Intel Deutschland GmbH
>
> Registered Address: Dornacher Strasse 1, 85622 Feldkirchen, Germany
> Tel: +49 89 991 430, www.intel.de
> Managing Directors: Harry Demas, Jeffrey Schneiderman, Yin Chong Sorrell
> Chairperson of the Supervisory Board: Nicole Lau
> Registered Seat: Munich
> Commercial Register: Amtsgericht Muenchen HRB 186928
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH v8 3/6] gdb, cli: pass the argument of a set command to its callback.
2026-07-22 10:27 ` [PATCH v8 3/6] gdb, cli: pass the argument of a set command to its callback Klaus Gerlicher
@ 2026-07-22 20:16 ` Andrew Burgess
2026-07-23 9:06 ` Andrew Burgess
0 siblings, 1 reply; 15+ messages in thread
From: Andrew Burgess @ 2026-07-22 20:16 UTC (permalink / raw)
To: Klaus Gerlicher, gdb-patches; +Cc: tom, guinevere, eliz
Klaus Gerlicher <klaus.gerlicher@intel.com> writes:
> From: Natalia Saiapova <natalia.saiapova@intel.com>
>
> This might be useful, if some commands need to have a special case if
> run w/o arguments.
The body of a commit message should ideally not run-on from the title
line. This first sentence only makes sense after reading the title.
Anyway, I think there's a bug in this commit. For the setting types:
var_uinteger, var_integer, and var_pinteger we call
parse_cli_var_integer which can modify ARG. This means you'll not be
passing through the actual argument of the set command in these cases.
I think the fix is easy enough, just capture the original ARG near the
start of do_set_command.
I think all the setting types are fine, but if you just capture the
original ARG value and use that in the 'c->func' call you'll be covered.
Thanks,
Andrew
>
> I am going to use it in
> gdb: refine commands to control scheduler locking.
> to keep the old behaviour of the
> set scheduler-locking step
> which should set both
> set scheduler-locking step on
> set scheduler-locking replay step on
> To do this, the set-command needs to detect that it was issued without
> arguments and have a special handling for this.
>
> Without the special handling, the command
> set scheduler-locking step
> would set only
> set scheduler-locking step on
>
> Approved-By: Tom Tromey <tom@tromey.com>
> ---
> gdb/cli/cli-setshow.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/gdb/cli/cli-setshow.c b/gdb/cli/cli-setshow.c
> index 7688da015de..f1f313a4cd0 100644
> --- a/gdb/cli/cli-setshow.c
> +++ b/gdb/cli/cli-setshow.c
> @@ -455,7 +455,7 @@ do_set_command (const char *arg, int from_tty, struct cmd_list_element *c)
> error (_("gdb internal error: bad var_type in do_setshow_command"));
> }
>
> - c->func (NULL, from_tty, c);
> + c->func (arg, from_tty, c);
>
> if (notify_command_param_changed_p (option_changed, c))
> {
> --
> 2.34.1
>
> Intel Deutschland GmbH
>
> Registered Address: Dornacher Strasse 1, 85622 Feldkirchen, Germany
> Tel: +49 89 991 430, www.intel.de
> Managing Directors: Harry Demas, Jeffrey Schneiderman, Yin Chong Sorrell
> Chairperson of the Supervisory Board: Nicole Lau
> Registered Seat: Munich
> Commercial Register: Amtsgericht Muenchen HRB 186928
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH v8 3/6] gdb, cli: pass the argument of a set command to its callback.
2026-07-22 20:16 ` Andrew Burgess
@ 2026-07-23 9:06 ` Andrew Burgess
0 siblings, 0 replies; 15+ messages in thread
From: Andrew Burgess @ 2026-07-23 9:06 UTC (permalink / raw)
To: Klaus Gerlicher, gdb-patches; +Cc: tom, guinevere, eliz
Andrew Burgess <aburgess@redhat.com> writes:
> Klaus Gerlicher <klaus.gerlicher@intel.com> writes:
>
>> From: Natalia Saiapova <natalia.saiapova@intel.com>
>>
>> This might be useful, if some commands need to have a special case if
>> run w/o arguments.
>
> The body of a commit message should ideally not run-on from the title
> line. This first sentence only makes sense after reading the title.
>
> Anyway, I think there's a bug in this commit. For the setting types:
> var_uinteger, var_integer, and var_pinteger we call
> parse_cli_var_integer which can modify ARG. This means you'll not be
> passing through the actual argument of the set command in these cases.
>
> I think the fix is easy enough, just capture the original ARG near the
> start of do_set_command.
>
> I think all the setting types are fine, but if you just capture the
> original ARG value and use that in the 'c->func' call you'll be covered.
It occurred to me that we can easily add some tests for this new
feature. If you checkout gdb/maint-test-settings.c and look for the
"test-settings" you'll see a bunch of dummy maintenance settings. These
are used by a number of tests, like gdb.base/settings.exp.
Could we not add a set callback to each of these settings that just
prints the value that you're now passing through? Then the tests, like
settings.exp can be updated to check that we print back the expected
string.
Thanks,
Andrew
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH v8 4/6] gdb: change the internal representation of scheduler locking.
2026-07-22 10:27 ` [PATCH v8 4/6] gdb: change the internal representation of scheduler locking Klaus Gerlicher
@ 2026-07-23 13:48 ` Andrew Burgess
0 siblings, 0 replies; 15+ messages in thread
From: Andrew Burgess @ 2026-07-23 13:48 UTC (permalink / raw)
To: Klaus Gerlicher, gdb-patches; +Cc: tom, guinevere, eliz
Klaus Gerlicher <klaus.gerlicher@intel.com> writes:
> From: Natalia Saiapova <natalia.saiapova@intel.com>
>
> Introduce a new structure to manage different options of the scheduler
> locking. The options can coexist together and be set individually.
> In the next patch
>
> gdb: refine commands to control scheduler locking.
>
> we introduce the commands to control these options. In this patch we do
> not introduce new commands and keep the previous API.
>
> New scheduler locking options are:
> replay continue -- control continuing commands during replay mode.
> replay step -- control stepping commands during replay mode.
> continue -- control continuing commands during normal execution.
> step -- control stepping commands during normal execution.
>
> Internally they hold a bool value, when true the locking is enabled.
>
> Mapping to the old settings
>
> Old Settings | New settings
> -----------------------------------
> off | all are false
> |
> replay | continue = false, step = false,
> | replay continue = true, replay step = true
> |
> step | continue = false, step = true,
> | replay continue = false, replay step = true
> |
> on | all are true
> ---
> gdb/infrun.c | 147 ++++++++++++++++++++++++++++++++++++++++++++++-----
> 1 file changed, 134 insertions(+), 13 deletions(-)
>
> diff --git a/gdb/infrun.c b/gdb/infrun.c
> index ace34507cfe..0eb890bbbc1 100644
> --- a/gdb/infrun.c
> +++ b/gdb/infrun.c
> @@ -107,8 +107,12 @@ static bool start_step_over (void);
>
> static bool step_over_info_valid_p (void);
>
> -static bool schedlock_applies (struct thread_info *tp);
> -static bool schedlock_applies (bool step, bool record_will_replay);
> +struct schedlock_options;
> +static bool schedlock_applies (thread_info *tp);
> +static bool schedlock_applies (bool step,
> + bool record_will_replay,
> + thread_info *tp = nullptr);
> +static bool schedlock_applies_to_opts (const schedlock_options &, bool step);
>
> static void handle_process_exited (struct execution_control_state *ecs);
>
> @@ -2373,7 +2377,69 @@ infrun_thread_ptid_changed (process_stratum_target *target,
> inferior_ptid = new_ptid;
> }
>
> -\f
> +/* A structure to hold scheduler locking settings for
> + a mode, replay or normal. */
> +struct schedlock_options
> +{
> + struct option {
The opening '{' needs to be on the next line.
Personally, I'm a fan of nesting classes like this, but in a couple of
my recent patches I've been specifically asked not to nest classes like
this, so I think the GDB style is to avoid such nesting.
> + const std::string name;
> + bool value;
It would be better if these were made private. The NAME is easy to do,
it's only used within member functions. VALUE is a little harder, but I
had a play, and I added these member functions to the
schedlock_options::option class:
void make_cli_option (const char *name, const char *set_doc,
const char *show_doc, const char *help_doc,
cmd_func_ftype *set_func,
cmd_list_element **set_list,
cmd_list_element **show_list)
{
add_setshow_boolean_cmd (name, class_run, &m_value,
set_doc, show_doc, help_doc,
set_func,
show_schedlock_option,
set_list,
show_list);
}
void make_cli_option (const char *name, const char *set_doc,
const char *show_doc, const char *help_doc,
cmd_list_element **set_list,
cmd_list_element **show_list)
{
make_cli_option (name, set_doc, show_doc, help_doc,
set_schedlock_callback, set_list, show_list);
}
These can then be used instead of direct calls to
add_setshow_boolean_cmd in the 'INIT_GDB_FILE (infrun)' function.
> +
> + option () = delete;
> + option (std::string name, bool value)
> + : name (std::move (name)), value (value)
> + {}
> +
> + /* Forbid accidential copying. */
> + option (const option &) = delete;
> + option operator= (const option &) = delete;
Use: 'DISABLE_COPY_AND_ASSIGN (option);' instead. There's also a typo:
s/accidential/accidental/, but I think the comment can go with the use
of DISABLE_COPY_AND_ASSIGN.
> + option (option &&) = default;
> + option &operator= (option &&) = default;
> +
> + operator bool () const { return value; }
> + const char *c_str () const { return value ? "on" : "off"; }
> + /* Set new value. Return true, if the value has changed. */
> + bool set (bool new_value);
> + };
> +
> + schedlock_options () = delete;
> + schedlock_options (option cont, option step)
> + : cont (std::move (cont)), step (std::move (step))
> + {}
> +
> + /* Forbid accidential copying. */
> + schedlock_options (const schedlock_options &) = delete;
> + schedlock_options operator= (const schedlock_options &) = delete;
> + schedlock_options (schedlock_options &&) = default;
> + schedlock_options &operator= (schedlock_options &&) = default;
Same as above, use DISABLE_COPY_AND_ASSIGN and then remove the comment
with typo.
> +
> + /* If true, the scheduler is locked during continuing. */
> + option cont;
> + /* If true, the scheduler is locked during stepping. */
> + option step;
> +};
> +
> +bool
> +schedlock_options::option::set (bool new_value)
> +{
> + if (value != new_value)
> + {
> + value = new_value;
> + return true;
> + }
> +
> + return false;
> +}
> +
> +struct schedlock
New types should get a header comment.
> +{
> + schedlock (schedlock_options opt, schedlock_options replay_opt)
> + : normal (std::move (opt)), replay (std::move (replay_opt))
> + {}
> +
> + schedlock_options normal;
> + schedlock_options replay;
> +};
>
> static const char schedlock_off[] = "off";
> static const char schedlock_on[] = "on";
> @@ -2386,7 +2452,42 @@ static const char *const scheduler_enums[] = {
> schedlock_replay,
> nullptr
> };
> +
> static const char *scheduler_mode = schedlock_replay;
> +
> +schedlock schedlock {
Make this static maybe? Rather than overloading the name 'schedlock'
for both the type and the variable, could we not find a better name for
one or both of these?
Actually, I'm not entirely convinced that the 'schedlock' type adds much
value above just having two separate variables with better names, e.g.:
schedlock_options schedlock_options_normal;
schedlock_options schedlock_options_replay;
This isn't a hard requirement though, if you are committed to the
current structure then I'll not object.
> + {
> + {"cont", false},
> + {"step", false}
> + },
> + {
> + {"replay cont", true},
> + {"replay step", true}
> + }
> +};
> +
> +/* A helper function to set scheduler locking shortcuts:
> + set scheduler-locking on: all options are on.
> + set scheduler-locking off: all options are off.
> + set scheduler-locking replay: only replay options are on.
> + set scheduler-locking step: only "step" and "replay step" are on. */
> +
> +static void
> +set_schedlock_shortcut_option (const char *shortcut)
> +{
> + bool is_on = (shortcut == schedlock_on);
> + bool is_step = (shortcut == schedlock_step);
> + bool is_replay = (shortcut == schedlock_replay);
> + bool is_off = (shortcut == schedlock_off);
> + /* Check that we got a valid shortcut option. */
> + gdb_assert (is_on || is_step || is_replay || is_off);
> +
> + schedlock.normal.cont.set (is_on);
> + schedlock.normal.step.set (is_on || is_step);
> + schedlock.replay.cont.set (is_on || is_replay);
> + schedlock.replay.step.set (is_on || is_replay || is_step);
> +}
> +
> static void
> show_scheduler_mode (struct ui_file *file, int from_tty,
> struct cmd_list_element *c, const char *value)
> @@ -2403,9 +2504,13 @@ set_schedlock_func (const char *args, int from_tty, struct 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 ());
> }
> +
> + set_schedlock_shortcut_option (scheduler_mode);
> }
>
> /* True if execution commands resume all threads of all processes by
> @@ -2436,6 +2541,10 @@ ptid_t
> user_visible_resume_ptid (int step)
> {
> ptid_t resume_ptid;
> + thread_info *tp = nullptr;
> +
> + if (inferior_ptid != null_ptid)
> + tp = inferior_thread ();
>
> if (non_stop)
> {
> @@ -2445,14 +2554,14 @@ user_visible_resume_ptid (int step)
> }
> else if (schedlock_applies (step,
> target_record_will_replay (inferior_ptid,
> - execution_direction)))
> + execution_direction),
> + tp))
> {
> /* User-settable 'scheduler' mode requires solo thread
> resume. */
> resume_ptid = inferior_ptid;
> }
> - else if (inferior_ptid != null_ptid
> - && inferior_thread ()->control.in_cond_eval)
> + else if (tp != nullptr && tp->control.in_cond_eval)
> {
> /* The inferior thread is evaluating a BP condition. Other threads
> might be stopped or running and we do not want to change their
> @@ -3164,8 +3273,9 @@ clear_proceed_status (int step, bool about_to_proceed)
> This is a convenience feature to not require the user to explicitly
> stop replaying the other threads. We're assuming that the user's
> intent is to resume tracing the recorded process. */
> - if (!non_stop && scheduler_mode == schedlock_replay
> - && !target_record_will_replay (inferior_ptid, execution_direction))
> + if (!non_stop && schedlock_applies_to_opts (schedlock.replay, step)
> + && !target_record_will_replay (inferior_ptid,
> + execution_direction))
There's a change in behaviour here which isn't called out in the commit
message. In fact the commit message gives the impression that this
commit is a refactor and retains the existing behaviour.
Previously we called `target_record_stop_replaying` only when in reply
mode, but now we call it when in both replay mode and the more general
'on' mode.
The comment above this `if` is definitely out of date.
I had an LLM give a summary of what changed, here's what it said:
Setup: Several threads have been recorded. The current thread (thread
1) has reached the end of its replay log and is no longer
replaying. Threads 2 and 3 are still mid-replay. set
scheduler-locking on is active.
Old behavior: target_record_stop_replaying() is not called because
scheduler_mode != schedlock_replay. Threads 2 and 3
remain in replay mode. They don't run (they're locked),
but their replay state is preserved. If the user later
does set scheduler-locking off and continues, threads 2
and 3 resume replaying from where they left off.
New behavior: schedlock_applies_to_opts(schedlock.replay, step) is
true (because schedlock_on sets replay.cont = true,
replay.step = true), so target_record_stop_replaying()
is called. Threads 2 and 3 are pulled out of replay
mode. If the user later switches to set
scheduler-locking off and continues, those threads
execute live instead of replaying — their replay state
has been silently lost.
The same applies to schedlock_step when stepping: threads that were
replaying get their replay state cleared even though they're locked
and wouldn't have run during the step.
This seems like it makes sense, but I don't claim to be an expert at the
record/replay logic.
Maybe this change is intentional? If it is then I think it should be
called out and described in the commit message. The comment definitely
needs to be updated.
> target_record_stop_replaying ();
>
> if (!non_stop && inferior_ptid != null_ptid)
> @@ -3241,6 +3351,17 @@ thread_still_needs_step_over (struct thread_info *tp)
> return what;
> }
>
> +/* Return true if OPTS lock the scheduler.
> + STEP indicates whether a thread is about to step.
> + Note, this does not take into the account the mode (replay or
> + normal execution). */
Rephrase the last sentence to avoid 'Note, ' and remove an extra 'the':
This function does not take into account the mode (replay or normal
execution).
Thanks,
Andrew
> +
> +static bool
> +schedlock_applies_to_opts (const schedlock_options &opts, bool step)
> +{
> + return ((opts.cont && !step) || (opts.step && step));
> +}
> +
> /* Returns true if scheduler locking applies to TP. */
>
> static bool
> @@ -3254,7 +3375,7 @@ schedlock_applies (thread_info *tp)
> record_will_replay
> = target_record_will_replay (tp->ptid, execution_direction);
> }
> - return schedlock_applies (step, record_will_replay);
> + return schedlock_applies (step, record_will_replay, tp);
> }
>
> /* Returns true if scheduler locking applies. STEP indicates whether
> @@ -3262,11 +3383,11 @@ schedlock_applies (thread_info *tp)
> indicates whether we're about to replay. */
>
> static bool
> -schedlock_applies (bool step, bool record_will_replay)
> +schedlock_applies (bool step, bool record_will_replay, thread_info *tp)
> {
> - return (scheduler_mode == schedlock_on
> - || (scheduler_mode == schedlock_step && step)
> - || (scheduler_mode == schedlock_replay && record_will_replay));
> + schedlock_options &opts
> + = record_will_replay ? schedlock.replay : schedlock.normal;
> + return schedlock_applies_to_opts (opts, step);
> }
>
> /* When FORCE_P is false, set process_stratum_target::COMMIT_RESUMED_STATE
> --
> 2.34.1
>
> Intel Deutschland GmbH
>
> Registered Address: Dornacher Strasse 1, 85622 Feldkirchen, Germany
> Tel: +49 89 991 430, www.intel.de
> Managing Directors: Harry Demas, Jeffrey Schneiderman, Yin Chong Sorrell
> Chairperson of the Supervisory Board: Nicole Lau
> Registered Seat: Munich
> Commercial Register: Amtsgericht Muenchen HRB 186928
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH v8 5/6] gdb: refine commands to control scheduler locking.
2026-07-22 10:27 ` [PATCH v8 5/6] gdb: refine commands to control " Klaus Gerlicher
@ 2026-07-23 16:39 ` Andrew Burgess
2026-07-24 9:34 ` Andrew Burgess
1 sibling, 0 replies; 15+ messages in thread
From: Andrew Burgess @ 2026-07-23 16:39 UTC (permalink / raw)
To: Klaus Gerlicher, gdb-patches; +Cc: tom, guinevere, eliz
Klaus Gerlicher <klaus.gerlicher@intel.com> writes:
> From: Natalia Saiapova <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 <continue | replay step | replay continue | step> <on | off>
> show scheduler-locking <continue | replay step | replay continue | 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 continue off
> set scheduler-locking replay continue off
> set scheduler-locking replay step on
> set scheduler-locking step on
>
> set scheduler-locking on
> is equivalent to
> set scheduler-locking continue on
> set scheduler-locking replay continue on
> set scheduler-locking replay step on
> set scheduler-locking step on
>
> set scheduler-locking replay
> is equivalent to
> set scheduler-locking continue off
> set scheduler-locking replay continue on
> set scheduler-locking replay step on
> set scheduler-locking step off
>
> set scheduler-locking off
> is equivalent to
> set scheduler-locking continue off
> set scheduler-locking replay continue 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 continue: "off" Scheduler locking for continuing
> commands is "off" during normal execution.
> scheduler-locking replay continue: "on" Scheduler locking for
> continuing 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.
I don't like the structure of these messages. Generally GDB's 'show'
message output should read as a proper sentence. I haven't tried to
figure out the problems that motivated this solution but I suspect
there's more detail behind this ....
> (gdb) show scheduler-locking replay step
> "on" Scheduler locking for stepping commands is "on" during replay mode.
That's really not nice at all. The random "on" at the beginning.
It feels like the leading "on" comes from a desire to have 'show
scheduler-locking' print something like:
(gdb) show scheduler-locking
scheduler-locking continue: "off" Scheduler locking for continuing commands is "off" during the normal execution.
scheduler-locking replay continue: "on" Scheduler locking for continuing commands is "on" during the replay mode.
scheduler-locking replay step: "on" Scheduler locking for stepping commands is "on" during the replay mode.
with the value appearing here after the option name at the start of the line.
But this feels like a separate design choice from the core idea behind
this patch. If we look at 'show style' we see:
(gdb) show style
style address background: The "address" style background color is: none
style address foreground: The "address" style foreground color is: blue
style address intensity: The "address" style display intensity is: normal
Here there's no repeat of the value string. Similar with 'show
breakpoint':
(gdb) show breakpoint
breakpoint always-inserted: Always inserted breakpoint mode is off.
breakpoint auto-hw: Automatic usage of hardware breakpoints is on.
breakpoint condition-evaluation: Breakpoint condition evaluation mode is auto (currently host).
For this patch at least I would suggest falling inline with GDB's
existing style, so the output would look something like:
(gdb) show scheduler-locking
scheduler-locking continue: Scheduler locking for continuing commands is "off" during the normal execution.
scheduler-locking replay continue: Scheduler locking for continuing commands is "on" during the replay mode.
scheduler-locking replay step: Scheduler locking for stepping commands is "on" during the replay mode.
You'll notice too the 'during the normal execution' and 'during the
replay mode' which (a) doesn't match the text in the commit message, and
(b) doesn't read well. I have some more thoughts on how this text is
built below...
>
> (gdb) show scheduler-locking continue
> "off" Scheduler locking for continuing 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 | 21 ++
> gdb/doc/gdb.texinfo | 66 +++++-
> 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, 397 insertions(+), 102 deletions(-)
>
> diff --git a/gdb/NEWS b/gdb/NEWS
> index 8f40ca5cb11..30d0637518b 100644
> --- a/gdb/NEWS
> +++ b/gdb/NEWS
> @@ -902,6 +902,27 @@ 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:
> + continue | replay continue | 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 continuing commands. Stepping commands include step, stepi,
> + next. Continuing commands include continue, finish, until, jump, return.
> + 'continue' -- when on, the scheduler is locked during continuing commands
> + in normal mode.
> + 'replay continue' -- when on, the scheduler is locked during continuing
> + 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 0030698dcee..fbf0f6e1da6 100644
> --- a/gdb/doc/gdb.texinfo
> +++ b/gdb/doc/gdb.texinfo
> @@ -7456,28 +7456,63 @@ 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}]
The use of @code{on} and @code{off} is wrong. I know you're just
copying what's already here, but we might as well try to start fixing
this rather than adding more. @kbd would seem a better choice, it's
something a user would type at the keyboard after all, or just @samp
again would be fine. But definitely not @code. There are multiple
instances of this below.
Also Use @r{[} @r{|} and @r{]} on the @item line. This too is pretty
inconsistent in our docs, but I thought use or @r{} was preferred.
> +@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 continuing commands. Examples of stepping commands are:
> +@samp{step}, @samp{stepi}, @samp{next}. Examples of continuing commands are
> +@samp{continue}, @samp{finish}, @samp{jump}, @samp{until}, @samp{return} or
> +inferior function calls.
> +
> +The following @var{type}-settings are available. When a setting is
> +@code{on}, the scheduler is locked: other threads may not preempt the
> +current thread, so that the focus of debugging does not change unexpectedly.
> +
> +@table @code
> +@item continue
> +Applies to continuing commands during normal execution and record modes.
> +This setting is @code{off} by default.
> +
> +@item replay continue
> +Applies to continuing commands during replay mode. This setting is
> +@code{on} by default.
> +
> +@item replay step
> +Applies to stepping commands during replay mode. This setting is
> +@code{on} by default.
> +
> +@item step
> +Applies to stepping commands during normal execution and record modes.
> +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 continuing
> +commands.
>
> This mode optimizes for single-stepping; it prevents other threads
> from preempting the current thread while you are stepping, so that the
> @@ -7486,9 +7521,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
Typo: "This is equivalent to SETTING ...."
> +@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 continue} and
> +@samp{scheduler-locking replay step} to @code{on}, while other settings
> +are @code{off}.
> +
> @end table
>
> @item show scheduler-locking
> @@ -34703,7 +34747,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 0eb890bbbc1..b6f7721dbf3 100644
> --- a/gdb/infrun.c
> +++ b/gdb/infrun.c
> @@ -75,6 +75,8 @@
> #include "extension.h"
> #include "disasm.h"
> #include "interps.h"
> +#include "cli/cli-decode.h"
> +#include <set>
The include of <set> appears unnecessary.
> #include "finish-thread-state.h"
> #include "buffered-streams.h"
>
> @@ -116,6 +118,12 @@ static bool schedlock_applies_to_opts (const schedlock_options &, bool step);
>
> static void handle_process_exited (struct execution_control_state *ecs);
>
> +/* 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;
> @@ -2398,7 +2406,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);
> };
>
> @@ -2425,6 +2434,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;
> }
>
> @@ -2445,15 +2457,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 {
> {
> @@ -2482,35 +2485,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.cont.set (is_on);
> - schedlock.normal.step.set (is_on || is_step);
> - schedlock.replay.cont.set (is_on || is_replay);
> - schedlock.replay.step.set (is_on || is_replay || is_step);
> + bool any_changed = schedlock.normal.cont.set (is_on);
> + any_changed = schedlock.normal.step.set (is_on || is_step) || any_changed;
> + any_changed = schedlock.replay.cont.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, "continue") == 0)
> + type = "continuing 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);
First the "the" here is probably wrong, this causes "the replay mode"
and "the normal execution" neither of which read very well.
But we should really avoid building sentences like this as it doesn't
play well with the internationalisation -- you can't always just drop in
replacement words like this and build a correct sentence in different
languages.
If we really wanted to retain the full sentence feel then we should pick
between 4 different complete strings and just merge the value string
in.
Next, GDB 'show' messages usually place the value near to the end of the
message text. Though you get it close, I wonder if we could do better
and get value right at the end?
Bringing all these points together, I wonder if the answer is to treat
MODE and TYPE as if they are separate from the sentence, like this:
Scheduler locking for "stepping commands" in "normal execution" is "on".
I'm not 100% sure I like that too much though... maybe selecting between
the 4 possible choices would be better? Then we could have:
Scheduler locking for stepping commands in normal execution is "on".
which does seem better I think...
> }
>
> /* True if execution commands resume all threads of all processes by
> @@ -8648,15 +8705,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;
I think I convinced myself that this removal is fine, but it would be
nice to see changes like this discussed in the commit message.
> -
> - /* 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;
> @@ -11023,21 +11072,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 ("continue", class_run, &schedlock.normal.cont.value, _("\
> +Scheduler locking for continuing commands during normal execution."), _("\
> +Show scheduler locking for continuing commands during normal execution."),
> + _("\
> +Controls scheduler locking for continuing 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 \
Please replace W/o with 'Without', especially for user docs.
> +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."),
Missing '_' here, it should be:
_("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."),
Replace W/o here too please.
> + &schedlock_set_replay_cmdlist,
> + 0, &schedlock_set_cmdlist);
> +
> + add_setshow_boolean_cmd ("continue", class_run, &schedlock.replay.cont.value, _("\
> +Set scheduler locking for continuing commands in replay mode."), _("\
> +Show scheduler locking for continuing commands in replay mode."), _("\
> +Controls scheduler locking for continuing 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. */
Indentation of the comment is wrong.
> + 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);
I think the "[Shortcut]" prefix should be removed and the text maybe
expanded. For example I'd say "Full scheduler locking" rather than just
"Full locking". With the context of which command this is then the
shorter text is probably fine, but there's no penalty for being explicit.
> +
> + c = add_cmd ("off", class_run, set_schedlock_off, _("\
> +[Shortcut] No locking (threads may preempt at any time)."),
> + &schedlock_set_cmdlist);
Both of the assignments to `c` here appear unnecessary.
> +
> 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 7555469b579..b7f813320c1 100644
> --- a/gdb/testsuite/gdb.mi/user-selected-context-sync.exp
> +++ b/gdb/testsuite/gdb.mi/user-selected-context-sync.exp
> @@ -257,17 +257,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."
> @@ -313,7 +308,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.
> @@ -344,7 +339,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 {"continue" "replay continue" "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 2f5eaa5405b..75be13c4c4d 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 "continue" "on" "replay continue" "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 "continue" "off" "replay continue" "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 fdcbaa47c7f..0a33550c65b 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 \"continue\" \"on\" \"replay continue\" \"on\" \
> + \"replay step\" \"on\" \"step\" \"on\"]] ne \"unknown\"} $test
I'm seeing:
WARNING: While evaluating expression in gdb_assert: invalid character "\"
in expression "... \"step\" \"on\"]] ne \"unknown\""
UNRESOLVED: gdb.threads/multiple-successive-infcall.exp: show scheduler-locking
here. I think the problem is that '\"' isn't required within the {...}
of the gdb_assert. Which I just spotted is what you have in
gdb.threads/hand-call-in-threads.exp.
>
> 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 61a9d5ddef5..cda4585ca08 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 != ""} {
> @@ -268,16 +269,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"
> }
>
> @@ -288,16 +294,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" {
> @@ -316,3 +324,57 @@ foreach schedlock {"off" "step" "on"} {
> }
> }
> }
> +
> +proc test_schedlock_opts {cont step} {
Proc needs a comment.
> + set test "show scheduler-locking"
> + if {[get_scheduler_locking $test \
> + [dict create "continue" $cont "replay continue" "off" \
> + "replay step" "off" "step" $step]] eq "unknown"} {
> + fail $test
> + } else {
> + pass $test
> + }
This should be written using gdb_assert.
> +
> + 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 {$cont 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 cont {"off" "on"} {
> + foreach step {"off" "on"} {
> + with_test_prefix "continue=$cont step=$step" {
> + gdb_test_no_output "set scheduler-locking continue $cont"
> + gdb_test_no_output "set scheduler-locking step $step"
> + test_schedlock_opts $cont $step
There's no testing of the replay options. I guess calling
test_schedlock_opts isn't possible as that would require setting up a
recorded session, but the first thing test_schedlock_opts does is check
the option values are as expected, maybe just doing that would provide a
minimal level of coverage?
> + }
> + }
> +}
> diff --git a/gdb/testsuite/lib/gdb.exp b/gdb/testsuite/lib/gdb.exp
> index a40c87c6727..e852fd1b99a 100644
> --- a/gdb/testsuite/lib/gdb.exp
> +++ b/gdb/testsuite/lib/gdb.exp
> @@ -10192,6 +10192,52 @@ gdb_caching_proc gdb_target_symbol_prefix {} {
> return $prefix
> }
>
> +# Return a dictionary of scheduler locking settings with keys:
> +# continue, replay continue, 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 {"continue" "replay continue" "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
I think this should be 'incr i'. The existing code will try to
increment a variable called "1". What this tells me is that there must
be a gap in the testing. You're using $expect_out(1,string) for every
iteration of the loop, and I assume that the tests pass. I haven't
checked, but my guess is that you change all settings together, so you
expect all values to be the same? Maybe you should add some tests that
check each value can be set individually?
Thanks,
Andrew
> + }
> + }
> + -re -wrap "" {}
> + timeout {}
> + }
> + return $current_schedlock_mode
> +}
> +
> # Return 1 if target supports scheduler locking, otherwise return 0.
>
> gdb_caching_proc target_supports_scheduler_locking {} {
> @@ -10211,28 +10257,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.34.1
>
> Intel Deutschland GmbH
>
> Registered Address: Dornacher Strasse 1, 85622 Feldkirchen, Germany
> Tel: +49 89 991 430, www.intel.de
> Managing Directors: Harry Demas, Jeffrey Schneiderman, Yin Chong Sorrell
> Chairperson of the Supervisory Board: Nicole Lau
> Registered Seat: Munich
> Commercial Register: Amtsgericht Muenchen HRB 186928
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH v8 5/6] gdb: refine commands to control scheduler locking.
2026-07-22 10:27 ` [PATCH v8 5/6] gdb: refine commands to control " Klaus Gerlicher
2026-07-23 16:39 ` Andrew Burgess
@ 2026-07-24 9:34 ` Andrew Burgess
1 sibling, 0 replies; 15+ messages in thread
From: Andrew Burgess @ 2026-07-24 9:34 UTC (permalink / raw)
To: Klaus Gerlicher, gdb-patches; +Cc: tom, guinevere, eliz
Klaus Gerlicher <klaus.gerlicher@intel.com> writes:
> From: Natalia Saiapova <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 <continue | replay step | replay continue | step> <on | off>
> show scheduler-locking <continue | replay step | replay continue | 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 continue off
> set scheduler-locking replay continue off
> set scheduler-locking replay step on
> set scheduler-locking step on
>
> set scheduler-locking on
> is equivalent to
> set scheduler-locking continue on
> set scheduler-locking replay continue on
> set scheduler-locking replay step on
> set scheduler-locking step on
>
> set scheduler-locking replay
> is equivalent to
> set scheduler-locking continue off
> set scheduler-locking replay continue on
> set scheduler-locking replay step on
> set scheduler-locking step off
>
> set scheduler-locking off
> is equivalent to
> set scheduler-locking continue off
> set scheduler-locking replay continue 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 continue: "off" Scheduler locking for continuing
> commands is "off" during normal execution.
> scheduler-locking replay continue: "on" Scheduler locking for
> continuing 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 continue: "on" Scheduler locking for
> continuing 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 continue
> "off" Scheduler locking for continuing 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 | 21 ++
> gdb/doc/gdb.texinfo | 66 +++++-
> 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, 397 insertions(+), 102 deletions(-)
>
> diff --git a/gdb/NEWS b/gdb/NEWS
> index 8f40ca5cb11..30d0637518b 100644
> --- a/gdb/NEWS
> +++ b/gdb/NEWS
> @@ -902,6 +902,27 @@ 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:
This sentence should start wit ha capital letter.
Thanks,
Andrew
> + continue | replay continue | 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 continuing commands. Stepping commands include step, stepi,
> + next. Continuing commands include continue, finish, until, jump, return.
> + 'continue' -- when on, the scheduler is locked during continuing commands
> + in normal mode.
> + 'replay continue' -- when on, the scheduler is locked during continuing
> + 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 0030698dcee..fbf0f6e1da6 100644
> --- a/gdb/doc/gdb.texinfo
> +++ b/gdb/doc/gdb.texinfo
> @@ -7456,28 +7456,63 @@ 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 continuing commands. Examples of stepping commands are:
> +@samp{step}, @samp{stepi}, @samp{next}. Examples of continuing commands are
> +@samp{continue}, @samp{finish}, @samp{jump}, @samp{until}, @samp{return} or
> +inferior function calls.
> +
> +The following @var{type}-settings are available. When a setting is
> +@code{on}, the scheduler is locked: other threads may not preempt the
> +current thread, so that the focus of debugging does not change unexpectedly.
> +
> +@table @code
> +@item continue
> +Applies to continuing commands during normal execution and record modes.
> +This setting is @code{off} by default.
> +
> +@item replay continue
> +Applies to continuing commands during replay mode. This setting is
> +@code{on} by default.
> +
> +@item replay step
> +Applies to stepping commands during replay mode. This setting is
> +@code{on} by default.
> +
> +@item step
> +Applies to stepping commands during normal execution and record modes.
> +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 continuing
> +commands.
>
> This mode optimizes for single-stepping; it prevents other threads
> from preempting the current thread while you are stepping, so that the
> @@ -7486,9 +7521,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 continue} and
> +@samp{scheduler-locking replay step} to @code{on}, while other settings
> +are @code{off}.
> +
> @end table
>
> @item show scheduler-locking
> @@ -34703,7 +34747,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 0eb890bbbc1..b6f7721dbf3 100644
> --- a/gdb/infrun.c
> +++ b/gdb/infrun.c
> @@ -75,6 +75,8 @@
> #include "extension.h"
> #include "disasm.h"
> #include "interps.h"
> +#include "cli/cli-decode.h"
> +#include <set>
> #include "finish-thread-state.h"
> #include "buffered-streams.h"
>
> @@ -116,6 +118,12 @@ static bool schedlock_applies_to_opts (const schedlock_options &, bool step);
>
> static void handle_process_exited (struct execution_control_state *ecs);
>
> +/* 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;
> @@ -2398,7 +2406,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);
> };
>
> @@ -2425,6 +2434,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;
> }
>
> @@ -2445,15 +2457,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 {
> {
> @@ -2482,35 +2485,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.cont.set (is_on);
> - schedlock.normal.step.set (is_on || is_step);
> - schedlock.replay.cont.set (is_on || is_replay);
> - schedlock.replay.step.set (is_on || is_replay || is_step);
> + bool any_changed = schedlock.normal.cont.set (is_on);
> + any_changed = schedlock.normal.step.set (is_on || is_step) || any_changed;
> + any_changed = schedlock.replay.cont.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, "continue") == 0)
> + type = "continuing 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
> @@ -8648,15 +8705,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;
> @@ -11023,21 +11072,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 ("continue", class_run, &schedlock.normal.cont.value, _("\
> +Scheduler locking for continuing commands during normal execution."), _("\
> +Show scheduler locking for continuing commands during normal execution."),
> + _("\
> +Controls scheduler locking for continuing 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 ("continue", class_run, &schedlock.replay.cont.value, _("\
> +Set scheduler locking for continuing commands in replay mode."), _("\
> +Show scheduler locking for continuing commands in replay mode."), _("\
> +Controls scheduler locking for continuing 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 7555469b579..b7f813320c1 100644
> --- a/gdb/testsuite/gdb.mi/user-selected-context-sync.exp
> +++ b/gdb/testsuite/gdb.mi/user-selected-context-sync.exp
> @@ -257,17 +257,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."
> @@ -313,7 +308,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.
> @@ -344,7 +339,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 {"continue" "replay continue" "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 2f5eaa5405b..75be13c4c4d 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 "continue" "on" "replay continue" "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 "continue" "off" "replay continue" "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 fdcbaa47c7f..0a33550c65b 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 \"continue\" \"on\" \"replay continue\" \"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 61a9d5ddef5..cda4585ca08 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 != ""} {
> @@ -268,16 +269,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"
> }
>
> @@ -288,16 +294,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" {
> @@ -316,3 +324,57 @@ foreach schedlock {"off" "step" "on"} {
> }
> }
> }
> +
> +proc test_schedlock_opts {cont step} {
> + set test "show scheduler-locking"
> + if {[get_scheduler_locking $test \
> + [dict create "continue" $cont "replay continue" "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 {$cont 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 cont {"off" "on"} {
> + foreach step {"off" "on"} {
> + with_test_prefix "continue=$cont step=$step" {
> + gdb_test_no_output "set scheduler-locking continue $cont"
> + gdb_test_no_output "set scheduler-locking step $step"
> + test_schedlock_opts $cont $step
> + }
> + }
> +}
> diff --git a/gdb/testsuite/lib/gdb.exp b/gdb/testsuite/lib/gdb.exp
> index a40c87c6727..e852fd1b99a 100644
> --- a/gdb/testsuite/lib/gdb.exp
> +++ b/gdb/testsuite/lib/gdb.exp
> @@ -10192,6 +10192,52 @@ gdb_caching_proc gdb_target_symbol_prefix {} {
> return $prefix
> }
>
> +# Return a dictionary of scheduler locking settings with keys:
> +# continue, replay continue, 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 {"continue" "replay continue" "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 {} {
> @@ -10211,28 +10257,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.34.1
>
> Intel Deutschland GmbH
>
> Registered Address: Dornacher Strasse 1, 85622 Feldkirchen, Germany
> Tel: +49 89 991 430, www.intel.de
> Managing Directors: Harry Demas, Jeffrey Schneiderman, Yin Chong Sorrell
> Chairperson of the Supervisory Board: Nicole Lau
> Registered Seat: Munich
> Commercial Register: Amtsgericht Muenchen HRB 186928
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH v8 6/6] gdb: add eval option to lock the scheduler during infcalls.
2026-07-22 10:27 ` [PATCH v8 6/6] gdb: add eval option to lock the scheduler during infcalls Klaus Gerlicher
@ 2026-07-24 9:52 ` Andrew Burgess
0 siblings, 0 replies; 15+ messages in thread
From: Andrew Burgess @ 2026-07-24 9:52 UTC (permalink / raw)
To: Klaus Gerlicher, gdb-patches; +Cc: tom, guinevere, eliz
Klaus Gerlicher <klaus.gerlicher@intel.com> writes:
> From: Natalia Saiapova <natalia.saiapova@intel.com>
>
> This patch adds an "eval" scheduler locking setting to control inferior
> function calls separately from other continuing commands.
>
> "continue" handles continuing commands, such as continue, until, return,
> finish, jump.
> "eval" handles inferior calls.
>
> Show scheduler locking:
> (gdb) show scheduler-locking
> scheduler-locking continue: "off" Scheduler locking for continuing
> commands is "off" during normal execution.
> scheduler-locking eval: "off" Scheduler locking for function calls
> is "off" during normal execution.
> scheduler-locking replay continue: "on" Scheduler locking for
> continuing commands is "on" during replay mode.
> scheduler-locking replay eval: "on" Scheduler locking for function
> calls 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.
>
> Reviewed-By: Eli Zaretskii <eliz@gnu.org>
> ---
> gdb/NEWS | 13 ++--
> gdb/doc/gdb.texinfo | 25 +++++---
> gdb/infrun.c | 61 +++++++++++++++----
> .../gdb.mi/user-selected-context-sync.exp | 3 +-
> .../gdb.threads/hand-call-in-threads.exp | 6 +-
> .../multiple-successive-infcall.exp | 5 +-
> gdb/testsuite/gdb.threads/schedlock.exp | 41 ++++++++++---
> gdb/testsuite/lib/gdb.exp | 3 +-
> 8 files changed, 118 insertions(+), 39 deletions(-)
>
> diff --git a/gdb/NEWS b/gdb/NEWS
> index 30d0637518b..0a1f15c153e 100644
> --- a/gdb/NEWS
> +++ b/gdb/NEWS
> @@ -905,15 +905,20 @@ list .
> set scheduler-locking <command type> (on|off)
> show scheduler-locking <command type>
> where <command-type> is one of the following:
> - continue | replay continue | 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 continuing commands. Stepping commands include step, stepi,
> + continue | eval | replay continue | replay eval | 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,
> + continuing and evaluating commands. Stepping commands include step, stepi,
> next. Continuing commands include continue, finish, until, jump, return.
> + The evaluating commands are those which invoke inferior calls.
> 'continue' -- when on, the scheduler is locked during continuing commands
> in normal mode.
> + 'eval' -- when on, the scheduler is locked during inferior calls in
> + normal mode.
We need to be careful referencing "normal mode". With the context of
this patch I understand you mean "not replay mode", but as a user
approaching the NEWS file without the context of this patch, "normal
mode" doesn't have much meaning. This comment also applies to the text
for 'continue' which I didn't spot before.
For 'eval' it would be nice to be more explicit, especially as this
links to some confusion later in this patch. Inferior calls can be
driven directly by the user, e.g. 'print some_user_function()' but can
also be more indirect, e.g. 'break LOC if (some_user_function())'. In
this second case the call can happen at some arbitrary time in the
future. What are the expectations for the 'eval' setting in these two
cases?
> 'replay continue' -- when on, the scheduler is locked during continuing
> commands in replay mode.
> + 'replay eval' -- when on, the scheduler is locked during inferior calls
> + 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
> diff --git a/gdb/infrun.c b/gdb/infrun.c
> index b6f7721dbf3..7f390d7db25 100644
> --- a/gdb/infrun.c
> +++ b/gdb/infrun.c
> @@ -2563,11 +2571,13 @@ show_schedlock_option (ui_file *file, int from_tty,
> type = "stepping commands";
> else if (strcmp (c->name, "continue") == 0)
> type = "continuing commands";
> + else if (strcmp (c->name, "eval") == 0)
> + type = "function calls";
> 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);
> + "\"%s\" during %s.\n"), value, type, value, mode);
Ah, that's why the text in the previous commit didn't match the code.
We already discussed this text in the last commit, but whatever else
happens, this fix shouldn't live here.
> }
>
> /* True if execution commands resume all threads of all processes by
> @@ -3410,13 +3420,20 @@ thread_still_needs_step_over (struct thread_info *tp)
>
> /* Return true if OPTS lock the scheduler.
> STEP indicates whether a thread is about to step.
> + While the stepping info we take from STEP argument, the inferior call
> + state we get from the thread TP.
> Note, this does not take into the account the mode (replay or
> normal execution). */
>
> static bool
> -schedlock_applies_to_opts (const schedlock_options &opts, bool step)
> +schedlock_applies_to_opts (const schedlock_options &opts, bool step,
> + thread_info *tp)
> {
> - return ((opts.cont && !step) || (opts.step && step));
> + bool in_infcall = (tp != nullptr) && tp->control.in_infcall;
> +
> + return ((opts.cont && !step && !in_infcall)
> + || (opts.step && step)
We don't consider IN_INFCALL here. Does this trigger if we are stepping
over a conditional breakpoint where the condition includes an inferior
function call? What is the expected and actual behaviour here? Is this
case tested? It seems like this change is worth discussing even if the
code as written is correct, as it's surprising (at least to me).
> + || (opts.eval && in_infcall));
> }
>
> /* Returns true if scheduler locking applies to TP. */
In a previous comment we discussed the schedlock_applies_to_opts call in
clear_proceed_status. I was surprised that this doesn't now pass
through the thread pointer. If it did then schedlock_applies_to_opts
would no longer need to default the thread pointer to NULL.
In fact, I would go as far as to say that even if passing NULL in that
case is correct then schedlock_applies_to_op should remove the default
argument value and clear_proceed_status should explicitly pass NULL and
should gain a comment explaining why passing NULL is the correct
solution.
> diff --git a/gdb/testsuite/gdb.threads/schedlock.exp b/gdb/testsuite/gdb.threads/schedlock.exp
> index cda4585ca08..58f8d9ae4de 100644
> --- a/gdb/testsuite/gdb.threads/schedlock.exp
> +++ b/gdb/testsuite/gdb.threads/schedlock.exp
> @@ -364,17 +365,39 @@ proc test_schedlock_opts {cont step} {
> my_continue "continue"
> check_result "continue" $curthread $cont_args $locked
> }
> +
> + # Infcall tests.
> + set locked 0
> + if {$eval eq "on"} {
> + set locked 1
> + }
> + with_test_prefix "cmd=infcall" {
> + # Use whichever we stopped in.
> + set curthread [get_current_thread "before-infcall"]
> + set cont_args [get_args "before-infcall"]
> +
> + for {set i 0} {[expr $i < 10]} {set i [expr $i + 1]} {
This should be:
for { set i 0 } { $i < 10 } { incr i } {
> + with_test_prefix "infcall #$i" {
> + gdb_test "print some_function()" ".*"
> + }
> + }
> +
> + check_result "infcall" $curthread $cont_args $locked
> + }
> }
>
> gdb_test_no_output "set scheduler-locking off"
>
> # Test different options of scheduler locking.
> foreach cont {"off" "on"} {
> - foreach step {"off" "on"} {
> - with_test_prefix "continue=$cont step=$step" {
> - gdb_test_no_output "set scheduler-locking continue $cont"
> - gdb_test_no_output "set scheduler-locking step $step"
> - test_schedlock_opts $cont $step
> + foreach eval {"off" "on"} {
> + foreach step {"off" "on"} {
> + with_test_prefix "continue=$cont eval=$eval step=$step" {
> + gdb_test_no_output "set scheduler-locking continue $cont"
> + gdb_test_no_output "set scheduler-locking eval $eval"
> + gdb_test_no_output "set scheduler-locking step $step"
> + test_schedlock_opts $cont $eval $step
> + }
> }
> }
> }
Thanks,
Andrew
^ permalink raw reply [flat|nested] 15+ messages in thread
end of thread, other threads:[~2026-07-24 9:53 UTC | newest]
Thread overview: 15+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-07-22 10:27 [PING PATCH v8 0/6] gdb: refine scheduler locking settings Klaus Gerlicher
2026-07-22 10:27 ` [PATCH v8 1/6] gdb: use schedlock_applies in user_visible_resume_ptid Klaus Gerlicher
2026-07-22 19:05 ` Andrew Burgess
2026-07-22 10:27 ` [PATCH v8 2/6] gdb, cli: remove left-over code from "set_logging_on" Klaus Gerlicher
2026-07-22 19:13 ` Andrew Burgess
2026-07-22 10:27 ` [PATCH v8 3/6] gdb, cli: pass the argument of a set command to its callback Klaus Gerlicher
2026-07-22 20:16 ` Andrew Burgess
2026-07-23 9:06 ` Andrew Burgess
2026-07-22 10:27 ` [PATCH v8 4/6] gdb: change the internal representation of scheduler locking Klaus Gerlicher
2026-07-23 13:48 ` Andrew Burgess
2026-07-22 10:27 ` [PATCH v8 5/6] gdb: refine commands to control " Klaus Gerlicher
2026-07-23 16:39 ` Andrew Burgess
2026-07-24 9:34 ` Andrew Burgess
2026-07-22 10:27 ` [PATCH v8 6/6] gdb: add eval option to lock the scheduler during infcalls Klaus Gerlicher
2026-07-24 9:52 ` Andrew Burgess
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox