diff --git a/gdb/NEWS b/gdb/NEWS
index bdbbadacb89..532179cdca1 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -18,16 +18,20 @@ 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
+set scheduler-locking eval | replay eval | replay run | replay step | run | step (on|off)
+show scheduler-locking (eval | replay eval | 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
+    'eval' -- when on, the scheduler is locked during expression evaluation
+    in normal mode.
+    'replay eval' -- when on, the scheduler is locked during expression
+    evaluation in replay mode.
+    'replay run' -- 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.
-    'run' -- when on, the scheduler is locked during non-stepping commands
+    'run' -- when on, the scheduler is locked during continuing commands
     in normal mode.
     'step' -- when on, the scheduler is locked during stepping commands
     in normal mode.
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index 0560b9a5ea7..3eddcc569df 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -7119,10 +7119,18 @@ record mode, and replay mode.  The scheduler locking can be set separately
 for stepping and non-stepping commands.
 
 @table @code
+@item eval
+When @code{on} the scheduler is locked for expression evaluation during
+normal execution and record modes, such that only the current thread may run.
+
+@item replay eval
+When @code{on} the scheduler is locked for expression evaluation during
+replay mode, such that only the current thread may run.
+
 @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.
+When @code{on} the scheduler is locked for continuing commands during
+replay mode.  For commands like @samp{continue}, @samp{until} or @samp{finish}
+only the current thread may run.
 
 @item replay step
 When @code{on} the scheduler is locked for stepping commands during replay
@@ -7131,10 +7139,9 @@ 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
+When @code{on} the scheduler is locked for continuing 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.
+@samp{until}, or @samp{finish} only the current thread may run.
 
 @item step
 When @code{on} the scheduler is locked for stepping commands during
diff --git a/gdb/infrun.c b/gdb/infrun.c
index daf8cecd601..67412c7148b 100644
--- a/gdb/infrun.c
+++ b/gdb/infrun.c
@@ -110,12 +110,12 @@ static bool step_over_info_valid_p (void);
 
 static bool schedlock_applies_to_thread (thread_info *tp);
 
-static bool schedlock_applies (bool step);
+static bool schedlock_applies (bool step, thread_info *tp = nullptr);
 
 struct schedlock_options;
 
 static bool schedlock_applies_to_opts (const schedlock_options &opts,
-				       bool step);
+				       bool step, thread_info *tp = nullptr);
 
 /* Command lists for the scheduler locking.  */
 static cmd_list_element *schedlock_set_cmdlist;
@@ -2361,8 +2361,8 @@ struct schedlock_options
   };
 
   schedlock_options () = delete;
-  schedlock_options (option run, option step)
-    :  run (std::move (run)), step (std::move (step))
+  schedlock_options (option eval, option run, option step)
+    : eval (std::move (eval)), run (std::move (run)), step (std::move (step))
   {}
 
   /* Forbid accidential copying.  */
@@ -2371,7 +2371,9 @@ struct schedlock_options
   schedlock_options (schedlock_options &&) = default;
   schedlock_options &operator= (schedlock_options &&) = default;
 
-  /* If true, the scheduler is locked during non-stepping.  */
+  /* If true, the scheduler is locked during inferior calls.  */
+  option eval;
+  /* If true, the scheduler is locked during continuing.  */
   option run;
   /* If true, the scheduler is locked during stepping.  */
   option step;
@@ -2406,8 +2408,18 @@ static const char schedlock_on[] = "on";
 static const char schedlock_step[] = "step";
 static const char schedlock_replay[] = "replay";
 
-schedlock schedlock {{{"run", false}, {"step", false}},
-		     {{"replay run", true}, {"replay step", true}}};
+schedlock schedlock {
+  {
+    {"eval", false},
+    {"run", false},
+    {"step", false}
+  },
+  {
+    {"replay eval", true},
+    {"replay run", true},
+    {"replay step", true}
+  }
+};
 
 /* A helper function to set scheduler locking shortcuts:
    set scheduler-locking on: all options are on.
@@ -2427,9 +2439,11 @@ set_schedlock_shortcut_option (const char *shortcut)
 
   bool any_changed = schedlock.normal.run.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.run.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.  */
@@ -2502,7 +2516,9 @@ show_schedlock_option (ui_file *file, int from_tty,
   if (strcmp (c->name, "step") == 0)
     type = "stepping commands";
   else if (strcmp (c->name, "run") == 0)
-    type = "non-stepping commands";
+    type = "continuing commands";
+  else if (strcmp (c->name, "eval") == 0)
+    type = "expression evaluation";
   else
     gdb_assert_not_reached ("Unexpected command name.");
 
@@ -2538,6 +2554,9 @@ 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)
     {
@@ -2545,7 +2564,7 @@ user_visible_resume_ptid (int step)
 	 individually.  */
       resume_ptid = inferior_ptid;
     }
-  else if (schedlock_applies (step))
+  else if (schedlock_applies (step, tp))
     {
       /* User-settable 'scheduler' mode requires solo thread
 	 resume.  */
@@ -3334,13 +3353,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.run && !step) || (opts.step && step));
+  bool in_infcall = (tp != nullptr) && tp->control.in_infcall;
+
+  return ((opts.run && !step && !in_infcall)
+	  || (opts.step && step)
+	  || (opts.eval && in_infcall));
 }
 
 /* Returns true if scheduler locking applies to TP.  */
@@ -3349,19 +3375,19 @@ static bool
 schedlock_applies_to_thread (thread_info *tp)
 {
   bool step = (tp != nullptr) && tp->control.stepping_command;
-  return schedlock_applies (step);
+  return schedlock_applies (step, tp);
 }
 
-/* Returns true if scheduler locking applies.  STEP indicates whether
-   we're about to do a step/next-like command.  */
+/* Returns true if scheduler locking applies to thread TP.
+   STEP indicates whether we're about to do a step/next-like command.  */
 
 static bool
-schedlock_applies (bool step)
+schedlock_applies (bool step, thread_info *tp)
 {
   bool is_replay = target_record_will_replay (minus_one_ptid,
 					      execution_direction);
   schedlock_options &opts = is_replay ? schedlock.replay : schedlock.normal;
-  return schedlock_applies_to_opts (opts, step);
+  return schedlock_applies_to_opts (opts, step, tp);
 }
 
 /* Set process_stratum_target::COMMIT_RESUMED_STATE in all target
@@ -10710,12 +10736,11 @@ Show scheduler locking settings in various conditions."),
 			&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."),
+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\n\
+stepping and expression evaluation."),
 			   set_schedlock_callback,
 			   show_schedlock_option,
 			   &schedlock_set_cmdlist,
@@ -10733,6 +10758,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 expression evaluation during normal execution."), _("\
+Show scheduler locking for expression evaluation during normal execution."),
+			   _("\
+Controls scheduler locking for expression evaluation 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
@@ -10754,11 +10789,11 @@ W/o arguments completely locks the scheduler in replay mode."),
 	   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 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\n\
+stepping and expression evaluation."),
 			   set_schedlock_callback,
 			   show_schedlock_option,
 			   &schedlock_set_replay_cmdlist,
@@ -10774,6 +10809,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 expression evaluation in replay mode."), _("\
+Show scheduler locking for expression evaluation in replay mode."), _("\
+Controls scheduler locking for expression evaluation 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 625a47fb745..01ab4c016ec 100644
--- a/gdb/testsuite/gdb.mi/user-selected-context-sync.exp
+++ b/gdb/testsuite/gdb.mi/user-selected-context-sync.exp
@@ -337,10 +337,12 @@ proc test_continue_to_start { mode inf } {
 		}
 
 		# Restore scheduler-locking to its original value.
-		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]"
+		gdb_test_no_output "set scheduler-locking eval [lindex $previous_schedlock_val 0]"
+		gdb_test_no_output "set scheduler-locking replay eval [lindex $previous_schedlock_val 1]"
+		gdb_test_no_output "set scheduler-locking replay run [lindex $previous_schedlock_val 2]"
+		gdb_test_no_output "set scheduler-locking replay step [lindex $previous_schedlock_val 3]"
+		gdb_test_no_output "set scheduler-locking run [lindex $previous_schedlock_val 4]"
+		gdb_test_no_output "set scheduler-locking step [lindex $previous_schedlock_val 5]"
 	    } 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 d18254910db..e0083a6369c 100644
--- a/gdb/testsuite/gdb.threads/hand-call-in-threads.exp
+++ b/gdb/testsuite/gdb.threads/hand-call-in-threads.exp
@@ -69,7 +69,7 @@ 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 {"on" "on" "on" "on"}] ne "unknown"} \
+gdb_assert {[get_scheduler_locking $test {"on" "on" "on" "on" "on" "on"}] ne "unknown"} \
     $test
 
 # Now hand-call a function in each thread, having the function
@@ -142,7 +142,7 @@ 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"
 set test "show scheduler-locking off"
-gdb_assert {[get_scheduler_locking $test {"off" "off" "off" "off"}] ne "unknown"} \
+gdb_assert {[get_scheduler_locking $test {"off" "off" "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 69e750fea44..75387883301 100644
--- a/gdb/testsuite/gdb.threads/multiple-successive-infcall.exp
+++ b/gdb/testsuite/gdb.threads/multiple-successive-infcall.exp
@@ -50,7 +50,7 @@ gdb_breakpoint [gdb_get_line_number "testmarker01"]
 gdb_continue_to_breakpoint "testmarker01"
 gdb_test_no_output "set scheduler-locking on"
 set test "show scheduler-locking"
-gdb_assert {[get_scheduler_locking $test {"on" "on" "on" "on"}] ne "unknown"} \
+gdb_assert {[get_scheduler_locking $test {"on" "on" "on" "on" "on" "on"}] ne "unknown"} \
 		$test
 
 foreach_with_prefix thread {5 4 3 2 1}  {
diff --git a/gdb/testsuite/gdb.threads/schedlock.exp b/gdb/testsuite/gdb.threads/schedlock.exp
index cf11fd3a0a0..c77aae98864 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 {
@@ -320,9 +320,9 @@ foreach schedlock {"off" "step" "on"} {
     }
 }
 
-proc test_schedlock_opts {run step} {
+proc test_schedlock_opts {eval run step} {
     set test "show scheduler-locking"
-    if {[get_scheduler_locking $test [list "off" "off" $run $step]] eq "unknown"} {
+    if {[get_scheduler_locking $test [list $eval "off" "off" "off" $run $step]] eq "unknown"} {
 	fail $test
     } else {
 	pass $test
@@ -357,6 +357,25 @@ proc test_schedlock_opts {run 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"
@@ -364,10 +383,13 @@ 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
+	foreach eval {"off" "on"} {
+	    with_test_prefix "run=$run step=$step eval=$eval" {
+		gdb_test_no_output "set scheduler-locking eval $eval"
+		gdb_test_no_output "set scheduler-locking run $run"
+		gdb_test_no_output "set scheduler-locking step $step"
+		test_schedlock_opts $eval $run $step
+	    }
 	}
     }
 }
diff --git a/gdb/testsuite/lib/gdb.exp b/gdb/testsuite/lib/gdb.exp
index a7c85c2b20a..4120e2125f4 100644
--- a/gdb/testsuite/lib/gdb.exp
+++ b/gdb/testsuite/lib/gdb.exp
@@ -8574,17 +8574,19 @@ proc get_scheduler_locking {{test ""} {expected ""}} {
     set any "\[^\r\n\]+"
     set on_off "\(?:on|off\)"
 
-    set i [expr 4 - [llength $expected]]
+    set i [expr 6 - [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}"]
+	     "${any}eval: +\"\([lindex $expected 0]\)\"${any}expression evaluation${any}normal execution${any}" \
+	     "${any}replay eval: +\"\([lindex $expected 1]\)\"${any}expression evaluation${any}replay${any}" \
+	     "${any}replay run: +\"\([lindex $expected 2]\)\"${any}continuing${any}replay${any}" \
+	     "${any}replay step: +\"\([lindex $expected 3]\)\"${any}stepping${any}replay${any}" \
+	     "${any}run: +\"\([lindex $expected 4]\)\"${any}continuing${any}normal execution${any}" \
+	     "${any}step: +\"\([lindex $expected 5]\)\"${any}stepping${any}normal execution${any}"]
 
     set current_schedule_locking_mode "unknown"
     gdb_test_multiple "show scheduler-locking" $test {
@@ -8593,7 +8595,9 @@ proc get_scheduler_locking {{test ""} {expected ""}} {
 		[list $expect_out(1,string) \
 		     $expect_out(2,string) \
 		     $expect_out(3,string) \
-		     $expect_out(4,string)]
+		     $expect_out(4,string) \
+		     $expect_out(5,string) \
+		     $expect_out(6,string)]
 	}
 	-re -wrap "" {}
 	timeout {}
@@ -8623,15 +8627,15 @@ gdb_caching_proc target_supports_scheduler_locking {} {
 
     set test "reading current scheduler-locking mode"
     set current_schedule_locking_mode [get_scheduler_locking $test]
-    if { $current_scheduler_locking eq "unknown" } {
+    if { $current_schedule_locking_mode eq "unknown" } {
 	set supports_schedule_locking 0
     }
 
     if { $supports_schedule_locking == -1 } {
 	set test "checking for scheduler-locking support"
 
-	# Try to set scheduler-locking run.
-	gdb_test_multiple "set scheduler-locking  run [lindex $current_schedule_locking_mode 0]" $test {
+	# Try to set scheduler-locking eval.
+	gdb_test_multiple "set scheduler-locking eval [lindex $current_schedule_locking_mode 0]" $test {
 	    -re "Target '\[^'\]+' cannot support this command\..*$gdb_prompt $" {
 		set supports_schedule_locking 0
 	    }
