From: Andrew Burgess <aburgess@redhat.com>
To: Klaus Gerlicher <klaus.gerlicher@intel.com>, gdb-patches@sourceware.org
Cc: tom@tromey.com, guinevere@redhat.com, eliz@gnu.org
Subject: Re: [PATCH v8 4/6] gdb: change the internal representation of scheduler locking.
Date: Thu, 23 Jul 2026 14:48:29 +0100 [thread overview]
Message-ID: <87tsppolzm.fsf@redhat.com> (raw)
In-Reply-To: <20260722102746.131536-5-klaus.gerlicher@intel.com>
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
next prev parent reply other threads:[~2026-07-23 13:49 UTC|newest]
Thread overview: 15+ messages / expand[flat|nested] mbox.gz Atom feed top
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 [this message]
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
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=87tsppolzm.fsf@redhat.com \
--to=aburgess@redhat.com \
--cc=eliz@gnu.org \
--cc=gdb-patches@sourceware.org \
--cc=guinevere@redhat.com \
--cc=klaus.gerlicher@intel.com \
--cc=tom@tromey.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox