diff --git a/gdb/NEWS b/gdb/NEWS
index 4358494a6b6..bdbbadacb89 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -18,6 +18,23 @@ disassemble
 
 * New commands
 
+set scheduler-locking replay run | replay step | run | step (on|off)
+show scheduler-locking (replay run | replay step | run | step)
+  Extend the scheduler locking settings with a set of set/show
+  commands, which can be used individually to control the scheduler during
+  various commands.
+    'replay run' -- when on, the scheduler is locked during non-stepping
+    commands in replay mode.
+    'replay step' -- when on, the scheduler is locked during stepping
+    commands in replay mode.
+    'run' -- when on, the scheduler is locked during non-stepping commands
+    in normal 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 not changed.
+  The output of "show scheduler-locking" has changed to support the new settings.
+
 info missing-debug-handler
   List all the registered missing debug handlers.
 
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index 42a91235661..0560b9a5ea7 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -7110,22 +7110,56 @@ 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.  The scheduler locking can be set separately
+for stepping and non-stepping commands.
+
+@table @code
+@item replay run
+When @code{on} the scheduler is locked for non-stepping commands during
+replay mode.  For commands like @samp{continue}, @samp{until}, @samp{finish},
+or expression evaluation only the current thread may run.
+
+@item replay step
+When @code{on} the scheduler is locked for stepping commands during replay
+mode.  This mode optimizes for single-stepping; only the current thread is
+resumed while you are stepping, so that the focus of debugging does not change
+unexpectedly.
+
+@item run
+When @code{on} the scheduler is locked for non-stepping commands during
+normal execution and record modes.  For commands like @samp{continue},
+@samp{until}, @samp{finish}, or expression evaluation only the current
+thread may run.
+
+@item step
+When @code{on} the scheduler is locked for stepping commands during
+normal execution and record modes.  This mode optimizes for single-stepping;
+only the current thread is resumed while you are stepping, so that the focus
+of debugging does not change unexpectedly.
+
+@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:
+One can choose to not set the scheduler locking settings individually but use
+the following predefined shortcut modes.
 
 @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 options to @code{off}.
 
 @item on
-Only the current thread may run when the inferior is resumed.  New
+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.
+point, before they execute any instruction.  This is
+equivalent to setting all options to @code{on}.
 
 @item step
 Behaves like @code{on} when stepping, and @code{off} otherwise.
@@ -7140,9 +7174,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 run} and
+@samp{scheduler-locking replay step} to @code{on}, while other settings
+are @code{off}.
+
 @end table
 
 @item show scheduler-locking
@@ -33949,7 +33992,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 f70f615abf8..daf8cecd601 100644
--- a/gdb/infrun.c
+++ b/gdb/infrun.c
@@ -77,6 +77,7 @@
 #include "extension.h"
 #include "disasm.h"
 #include "interps.h"
+#include "cli/cli-decode.h"
 
 /* Prototypes for local functions */
 
@@ -116,6 +117,12 @@ struct schedlock_options;
 static bool schedlock_applies_to_opts (const schedlock_options &opts,
 				       bool step);
 
+/* 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;
@@ -2348,7 +2355,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);
   };
 
@@ -2375,6 +2383,8 @@ 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;
     }
 
@@ -2395,15 +2405,6 @@ static const char schedlock_off[] = "off";
 static const char schedlock_on[] = "on";
 static const char schedlock_step[] = "step";
 static const char schedlock_replay[] = "replay";
-static const char *const scheduler_enums[] = {
-  schedlock_off,
-  schedlock_on,
-  schedlock_step,
-  schedlock_replay,
-  nullptr
-};
-
-static const char *scheduler_mode = schedlock_replay;
 
 schedlock schedlock {{{"run", false}, {"step", false}},
 		     {{"replay run", true}, {"replay step", true}}};
@@ -2424,35 +2425,89 @@ set_schedlock_shortcut_option (const char *shortcut)
   /* Check that we got a valid shortcut option.  */
   gdb_assert (is_on || is_step || is_replay || is_off);
 
-  schedlock.normal.run.set (is_on);
-  schedlock.normal.step.set (is_on || is_step);
-  schedlock.replay.run.set (is_on || is_replay);
-  schedlock.replay.step.set (is_on || is_replay || is_step);
+  bool any_changed = schedlock.normal.run.set (is_on);
+  any_changed = schedlock.normal.step.set (is_on || is_step) || any_changed;
+  any_changed = schedlock.replay.run.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);
+}
+
+static void
+set_schedlock_replay (const char *args, int from_tty)
+{
+  set_schedlock_shortcut_option (schedlock_replay);
+  set_schedlock_callback (args, from_tty, nullptr);
+}
 
-  set_schedlock_shortcut_option (scheduler_mode);
+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, "run") == 0)
+    type = "non-stepping commands";
+  else
+    gdb_assert_not_reached ("Unexpected command name.");
+
+  gdb_printf (file, _("\"%s\"\tScheduler locking for %s is "
+		      "\"%s\" during the %s.\n"), value, type, value, mode);
 }
 
 /* True if execution commands resume all threads of all processes by
@@ -8354,14 +8409,6 @@ 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_to_thread (ecs->event_thread))
-	return false;
-
       /* Otherwise, 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.  */
@@ -10652,21 +10699,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 ("run", class_run, &schedlock.normal.run.value, _("\
+Scheduler locking for non-stepping commands during normal execution."), _("\
+Show scheduler locking for non-stepping commands during normal execution."),
+			   _("\
+Controls scheduler locking for non-stepping commands during normal execution.\n\
+Commands include continue, until, finish.  The setting does not affect \
+stepping."),
+			   set_schedlock_callback,
+			   show_schedlock_option,
+			   &schedlock_set_cmdlist,
+			   &schedlock_show_cmdlist);
+
+  add_setshow_boolean_cmd ("step", class_run, &schedlock.normal.step.value, _("\
+Scheduler locking for stepping commands.  W/o arguments locks the scheduler \
+for stepping."), _("\
+Show scheduler locking for stepping commands during normal execution."), _("\
+If argument \"on\" or \"off\", sets scheduler locking behavior for stepping\n\
+commands only during normal execution.\n\
+Commands include step, next, stepi, nexti."),
+			   set_schedlock_step,
+			   show_schedlock_option,
+			   &schedlock_set_cmdlist,
+			   &schedlock_show_cmdlist);
+
+  /* Commands for set/show scheduler-locking in replay mode.
+     The base command adds support for the shortcut
+       set scheduler-locking replay
+     command.  */
+
+  add_setshow_prefix_cmd ("replay", class_run, _("\
+Scheduler locking settings for replay mode.\n\
+Configure scheduler locking in various conditions such as during continuing\n\
+or stepping."),
+("Show scheduler locking in replay mode."),
+			&schedlock_set_replay_cmdlist,
+			&schedlock_show_replay_cmdlist,
+			&schedlock_set_cmdlist,
+			&schedlock_show_cmdlist);
+  add_prefix_cmd ("replay", class_run, set_schedlock_replay, _("\
+Scheduler locking settings for replay mode. \
+W/o arguments completely locks the scheduler in replay mode."),
+		  &schedlock_set_replay_cmdlist,
+	   0, &schedlock_set_cmdlist);
+
+  add_setshow_boolean_cmd ("run", class_run, &schedlock.replay.run.value, _("\
+Set scheduler locking for non-stepping commands in replay mode."), _("\
+Show scheduler locking for non-stepping commands in replay mode."), _("\
+Controls scheduler locking for non-stepping commands in replay mode.\n\
+Commands include continue, until, finish.  The setting does not affect \
+stepping."),
+			   set_schedlock_callback,
+			   show_schedlock_option,
+			   &schedlock_set_replay_cmdlist,
+			   &schedlock_show_replay_cmdlist);
+
+  add_setshow_boolean_cmd ("step", class_run, &schedlock.replay.step.value, _("\
+Set scheduler locking for stepping commands in replay mode."), _("\
+Show scheduler locking for stepping commands in replay mode."), _("\
+Controls scheduler locking for stepping commands in replay mode.\n\
+Commands include step, next, stepi, nexti."),
+			   set_schedlock_callback,
+			   show_schedlock_option,
+			   &schedlock_set_replay_cmdlist,
+			   &schedlock_show_replay_cmdlist);
+
+/* Commands "set scheduler-locking on" and "set scheduler-locking off"
+   are provided for backward compatibility.  */
+  c = add_cmd ("on", class_run, set_schedlock_on, _("\
+[Shortcut] Full locking (no thread except the current thread may run).\n\
+This applies to both normal execution and replay mode."),
+	   &schedlock_set_cmdlist);
+
+  c = add_cmd ("off", class_run, set_schedlock_off, _("\
+[Shortcut] No locking (threads may preempt at any time)."),
+	   &schedlock_set_cmdlist);
+
   add_setshow_boolean_cmd ("schedule-multiple", class_run, &sched_multi, _("\
 Set mode for resuming threads of all processes."), _("\
 Show mode for resuming threads of all processes."), _("\
diff --git a/gdb/testsuite/gdb.mi/user-selected-context-sync.exp b/gdb/testsuite/gdb.mi/user-selected-context-sync.exp
index 4889c31aff3..625a47fb745 100644
--- a/gdb/testsuite/gdb.mi/user-selected-context-sync.exp
+++ b/gdb/testsuite/gdb.mi/user-selected-context-sync.exp
@@ -255,17 +255,12 @@ proc make_cli_in_mi_re { command cli_in_mi_mode mode event inf cli_thread
 # Return the current value of the "scheduler-locking" parameter.
 
 proc show_scheduler_locking { } {
-    global gdb_prompt
-    global expect_out
-
-    set any "\[^\r\n\]*"
-
     set test "show scheduler-locking"
-    gdb_test_multiple $test $test {
-	-re ".*Mode for locking scheduler during execution is \"(${any})\".\r\n$gdb_prompt " {
-	    pass $test
-	    return $expect_out(1,string)
-	}
+    set schedlock [get_scheduler_locking $test]
+
+    if {$schedlock ne "unknown"} {
+	pass $test
+	return $schedlock
     }
 
     error "Couldn't get current scheduler-locking value."
@@ -342,7 +337,10 @@ proc test_continue_to_start { mode inf } {
 		}
 
 		# Restore scheduler-locking to its original value.
-		gdb_test_no_output "set scheduler-locking $previous_schedlock_val"
+		gdb_test_no_output "set scheduler-locking replay run [lindex $previous_schedlock_val 0]"
+		gdb_test_no_output "set scheduler-locking replay step [lindex $previous_schedlock_val 1]"
+		gdb_test_no_output "set scheduler-locking run [lindex $previous_schedlock_val 2]"
+		gdb_test_no_output "set scheduler-locking step [lindex $previous_schedlock_val 3]"
 	    } 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 58039ddd30e..d18254910db 100644
--- a/gdb/testsuite/gdb.threads/hand-call-in-threads.exp
+++ b/gdb/testsuite/gdb.threads/hand-call-in-threads.exp
@@ -68,7 +68,9 @@ 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 {"on" "on" "on" "on"}] ne "unknown"} \
+    $test
 
 # Now hand-call a function in each thread, having the function
 # stop without returning.
@@ -139,7 +141,9 @@ 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 {"off" "off" "off" "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 bd037a02674..69e750fea44 100644
--- a/gdb/testsuite/gdb.threads/multiple-successive-infcall.exp
+++ b/gdb/testsuite/gdb.threads/multiple-successive-infcall.exp
@@ -49,8 +49,9 @@ 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 {"on" "on" "on" "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 3c60f6b3478..cf11fd3a0a0 100644
--- a/gdb/testsuite/gdb.threads/schedlock.exp
+++ b/gdb/testsuite/gdb.threads/schedlock.exp
@@ -94,7 +94,8 @@ proc get_current_thread { description } {
 # Make sure we're stopped in the loop, in one of the non-main threads.
 
 proc goto_loop { msg } {
-    gdb_breakpoint [concat [gdb_get_line_number "schedlock.exp: main loop"] " if arg != 0"]
+    global srcfile
+    gdb_breakpoint [concat "$srcfile:" [gdb_get_line_number "schedlock.exp: main loop"] " if arg != 0"]
 
     set test "return to loop"
     if {$msg != ""} {
@@ -264,16 +265,21 @@ with_test_prefix "schedlock=on: cmd=continue" {
 }
 
 # Test stepping/nexting with different modes of scheduler locking.
-proc test_step { schedlock cmd call_function } {
+# Do scheduler-locking off setting before the test if PRESET_SCHEDLOCK_OFF is 1.
+# LOCKED defines whether we expect the thread to be locked.  If -1, then
+# determine it first.
+proc test_step { schedlock cmd call_function { preset_schedlock_off 1 } { locked -1 } } {
     global NUM
 
-    gdb_test_no_output "set scheduler-locking off"
+    if {$preset_schedlock_off} {
+	gdb_test_no_output "set scheduler-locking off"
+    }
     goto_loop ""
 
     set curthread [get_current_thread "before"]
 
     # No need to set to off again.  This avoids a duplicate message.
-    if {$schedlock != "off"} {
+    if {$preset_schedlock_off && $schedlock != "off"} {
 	gdb_test_no_output "set scheduler-locking $schedlock"
     }
 
@@ -284,16 +290,17 @@ proc test_step { schedlock cmd call_function } {
 
     step_ten_loops $cmd
 
-    if { $schedlock == "on" || $schedlock == "step" } {
-	set locked 1
-    } else {
-	set locked 0
+    if { $locked == -1 } {
+	if { $schedlock == "on" || $schedlock == "step"} {
+	    set locked 1
+	} else {
+	    set locked 0
+	}
     }
-
     check_result $cmd $curthread $before_args $locked
 }
 
-# Test stepping/nexting with different modes of scheduler locking.
+# Test stepping/nexting with different shortcut modes of scheduler locking.
 foreach schedlock {"off" "step" "on"} {
     with_test_prefix "schedlock=$schedlock" {
 	with_test_prefix "cmd=step" {
@@ -312,3 +319,55 @@ foreach schedlock {"off" "step" "on"} {
 	}
     }
 }
+
+proc test_schedlock_opts {run step} {
+    set test "show scheduler-locking"
+    if {[get_scheduler_locking $test [list "off" "off" $run $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 {$run 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 run {"off" "on"} {
+    foreach step {"off" "on"} {
+	with_test_prefix "run=$run step=$step" {
+	    gdb_test_no_output "set scheduler-locking run $run"
+	    gdb_test_no_output "set scheduler-locking step $step"
+	    test_schedlock_opts $run $step
+	}
+    }
+}
diff --git a/gdb/testsuite/lib/gdb.exp b/gdb/testsuite/lib/gdb.exp
index eb8f6998b1e..a7c85c2b20a 100644
--- a/gdb/testsuite/lib/gdb.exp
+++ b/gdb/testsuite/lib/gdb.exp
@@ -8565,6 +8565,42 @@ gdb_caching_proc gdb_target_symbol_prefix {} {
     return $prefix
 }
 
+proc get_scheduler_locking {{test ""} {expected ""}} {
+    global gdb_prompt
+    if {$test eq ""} {
+	set test "reading current scheduler-locking mode"
+    }
+
+    set any "\[^\r\n\]+"
+    set on_off "\(?:on|off\)"
+
+    set i [expr 4 - [llength $expected]]
+    while {$i > 0} {
+	incr i -1
+	lappend expected $on_off
+    }
+    set schedlock_regex \
+	[multi_line \
+	     "${any}replay run: +\"\([lindex $expected 0]\)\"${any}non-stepping${any}replay${any}" \
+	     "${any}replay step: +\"\([lindex $expected 1]\)\"${any}stepping${any}replay${any}" \
+	     "${any}run: +\"\([lindex $expected 2]\)\"${any}non-stepping${any}normal execution${any}" \
+	     "${any}step: +\"\([lindex $expected 3]\)\"${any}stepping${any}normal execution${any}"]
+
+    set current_schedule_locking_mode "unknown"
+    gdb_test_multiple "show scheduler-locking" $test {
+	-re -wrap $schedlock_regex {
+	    set current_schedule_locking_mode \
+		[list $expect_out(1,string) \
+		     $expect_out(2,string) \
+		     $expect_out(3,string) \
+		     $expect_out(4,string)]
+	}
+	-re -wrap "" {}
+	timeout {}
+    }
+    return $current_schedule_locking_mode
+}
+
 # Return 1 if target supports scheduler locking, otherwise return 0.
 
 gdb_caching_proc target_supports_scheduler_locking {} {
@@ -8586,21 +8622,16 @@ gdb_caching_proc target_supports_scheduler_locking {} {
     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_schedule_locking_mode [get_scheduler_locking $test]
+    if { $current_scheduler_locking 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 {
+
+	# Try to set scheduler-locking run.
+	gdb_test_multiple "set scheduler-locking  run [lindex $current_schedule_locking_mode 0]" $test {
 	    -re "Target '\[^'\]+' cannot support this command\..*$gdb_prompt $" {
 		set supports_schedule_locking 0
 	    }
