diff --git a/gdb/testsuite/gdb.threads/step-over-thread-exit.c b/gdb/testsuite/gdb.threads/step-over-thread-exit.c
index 878e5924c5c..218f003b205 100644
--- a/gdb/testsuite/gdb.threads/step-over-thread-exit.c
+++ b/gdb/testsuite/gdb.threads/step-over-thread-exit.c
@@ -18,6 +18,7 @@
 #include <pthread.h>
 #include <assert.h>
 #include <stdlib.h>
+#include <unistd.h>
 #include "../lib/my-syscalls.h"
 
 static void *
@@ -30,13 +31,19 @@ thread_func (void *arg)
   abort ();
 }
 
+/* Number of threads we'll create.  */
+int n_threads = 100;
+
 int
-main (void)
+main (int argc, char **argv)
 {
   int i;
 
-  /* Spawn and join a thread, 100 times.  */
-  for (i = 0; i < 100; i++)
+  if (argc > 1)
+    n_threads = atoi (argv[1]);
+
+  /* Spawn and join a thread, N_THREADS times.  */
+  for (i = 0; i < n_threads; i++)
     {
       pthread_t thread;
       int ret;
@@ -48,5 +55,8 @@ main (void)
       assert (ret == 0);
     }
 
+  /* Some time to make sure that GDB processes the thread exit event
+     before the whole-process exit.  */
+  sleep (3);
   return 0;
 }
diff --git a/gdb/testsuite/gdb.threads/step-over-thread-exit.exp b/gdb/testsuite/gdb.threads/step-over-thread-exit.exp
index 615bd838763..32f64ce1a3e 100644
--- a/gdb/testsuite/gdb.threads/step-over-thread-exit.exp
+++ b/gdb/testsuite/gdb.threads/step-over-thread-exit.exp
@@ -25,11 +25,29 @@ if { [build_executable "failed to prepare" $testfile \
     return
 }
 
-# Each argument is a different testing axis, most of them obvious.
+# Test stepping/continuing at an exit syscall instruction.
+#
+# Each argument is a different testing axis.
+#
+# STEP_OVER_MODE can be one of:
+#
+#   - none: don't put a breakpoint on the exit syscall instruction.
+#
+#   - inline: put a breakpoint on the exit syscall instruction, and
+#     use in-line stepping to step over it (disable
+#     displaced-stepping).
+#
+#   - displaced: same, but use displaced stepping.
+#
+# SCHEDLOCK can be "on" or "off".
+#
+# CMD is the GDB command to run when at the exit syscall instruction.
+#
 # NS_STOP_ALL is only used if testing "set non-stop on", and indicates
 # whether to have GDB explicitly stop all threads before continuing to
 # thread exit.
-proc test {displaced-stepping non-stop target-non-stop schedlock cmd ns_stop_all} {
+#
+proc test {step_over_mode non-stop target-non-stop schedlock cmd ns_stop_all} {
     if {${non-stop} == "off" && $ns_stop_all} {
 	error "invalid arguments"
     }
@@ -40,23 +58,29 @@ proc test {displaced-stepping non-stop target-non-stop schedlock cmd ns_stop_all
 	clean_restart $::binfile
     }
 
-    gdb_test_no_output "set displaced-stepping ${displaced-stepping}"
-
-    if { ![runto_main] } {
-	return
+    if { $step_over_mode == "none" } {
+	# Nothing to do.
+    } elseif { $step_over_mode == "inline" } {
+	gdb_test_no_output "set displaced-stepping off"
+    } elseif { $step_over_mode == "displaced" } {
+	gdb_test_no_output "set displaced-stepping on"
+    } else {
+	error "Invalid step_over_mode value: $step_over_mode"
     }
 
-    gdb_breakpoint "my_exit_syscall"
-
     if {$schedlock
 	|| (${non-stop} == "on" && $ns_stop_all)} {
-	gdb_test "continue" \
-	    "Thread 2 .*hit Breakpoint $::decimal.* my_exit_syscall .*" \
-	    "continue until syscall"
+
+	gdb_test_no_output "set args 1"
+
+	if { ![runto my_exit_syscall] } {
+	    return
+	}
 
 	if {${non-stop} == "on"} {
 	    # The test only spawns one thread at a time, so this just
-	    # stops the main thread.
+	    # stops the main thread.  IOW, we only need to wait for
+	    # one stop.
 	    gdb_test_multiple "interrupt -a" "" {
 		-re "$::gdb_prompt " {
 		    gdb_test_multiple "" $gdb_test_name {
@@ -66,12 +90,19 @@ proc test {displaced-stepping non-stop target-non-stop schedlock cmd ns_stop_all
 		    }
 		}
 	    }
-	}
 
-	gdb_test "thread 2" "Switching to thread 2 .*"
+	    gdb_test "thread 2" "Switching to thread 2 .*"
+	}
 
 	gdb_test_no_output "set scheduler-locking ${schedlock}"
 
+	# If testing a step-over is requested, leave the breakpoint at
+	# the current instruction to force a step-over; otherwise,
+	# remove it.
+	if { $step_over_mode == "none" } {
+	    delete_breakpoints
+	}
+
 	if {$cmd == "continue"} {
 	    gdb_test "continue" \
 		"No unwaited-for children left." \
@@ -84,9 +115,50 @@ proc test {displaced-stepping non-stop target-non-stop schedlock cmd ns_stop_all
 	    }
 	}
     } else {
+	# Schedlock is off here.
+	#
+	# With "continue" and no scheduler-locking, GDB doesn't stop
+	# with "Command aborted, thread exited." when the thread
+	# exits, it just lets the inferior continue running freely.
+	# So we test that we can move past the thread exit, and that
+	# other threads can be freely scheduled.  We do that by
+	# spawning another thread as soon as the first exit.  We test
+	# that a number of times.  This should also exercise GDB's
+	# handling of inline or displaced step-overs, that GDB handles
+	# the related resource accounting correctly when the stepping
+	# thread exits, etc.
+	#
+	# With "continue" and $step_over_mode == "none" however, after
+	# the first my_exit_syscall breakpoint hit, we will remove the
+	# breakpoint, so no other thread would ever hit it again.  So
+	# might as well just test one thread.
+	#
+	# With step/next, GDB aborts the execution command with
+	# "Command aborted, thread exited." when the stepping thread
+	# exits.  If we let the main spawn another thread as soon as
+	# the first exits, it would be possible for that new thread to
+	# hit the exit syscall insn breakpoint quickly enough that it
+	# would be reported to be user before the first thread exit
+	# would be, which would confuse testing.  To avoid that, we
+	# only spawn one thread, too.
+	#
+	if {$cmd != "continue" || $step_over_mode == "none"} {
+	    set n_threads 1
+	} else {
+	    set n_threads 100
+	}
+
+	gdb_test_no_output "set args $n_threads"
+
+	if { ![runto_main] } {
+	    return
+	}
+
+	gdb_breakpoint "my_exit_syscall"
+
 	gdb_test_no_output "set scheduler-locking ${schedlock}"
 
-	if {$cmd != "continue"} {
+	if {$cmd != "continue" || $step_over_mode == "none"} {
 	    set thread "<unknown>"
 	    gdb_test_multiple "continue" "" {
 		-re -wrap "Thread ($::decimal) .*hit Breakpoint $::decimal.* my_exit_syscall .*" {
@@ -98,10 +170,23 @@ proc test {displaced-stepping non-stop target-non-stop schedlock cmd ns_stop_all
 		    "switch to event thread"
 	    }
 
-	    gdb_test_multiple $cmd "command aborts when thread exits" {
-		-re "Command aborted, thread exited\\.\r\n$::gdb_prompt " {
-		    pass $gdb_test_name
+	    # If testing a step-over is requested, leave the breakpoint at
+	    # the current instruction to force a step-over; otherwise,
+	    # remove it.
+	    if { $step_over_mode == "none" } {
+		delete_breakpoints
+	    }
+
+	    if {$cmd == "continue"} {
+		gdb_continue_to_end "continue to end" "continue" 1
+	    } else {
+		gdb_test_multiple $cmd "command aborts when thread exits" {
+		    -re "Command aborted, thread exited\\.\r\n$::gdb_prompt " {
+			pass $gdb_test_name
+		    }
 		}
+		gdb_test "p \$_thread == $thread" "= 1" \
+		    "selected thread didn't change"
 	    }
 	} else {
 	    for { set i 0 } { $i < 100 } { incr i } {
@@ -130,7 +215,7 @@ proc test {displaced-stepping non-stop target-non-stop schedlock cmd ns_stop_all
     }
 }
 
-foreach_with_prefix displaced-stepping {off auto} {
+foreach_with_prefix step_over_mode {none inline displaced} {
     foreach_with_prefix non-stop {off on} {
 	foreach_with_prefix target-non-stop {off on} {
 	    if {${non-stop} == "on" && ${target-non-stop} == "off"} {
@@ -142,11 +227,11 @@ foreach_with_prefix displaced-stepping {off auto} {
 		foreach_with_prefix cmd {"next" "continue"} {
 		    if {${non-stop} == "on"} {
 			foreach_with_prefix ns_stop_all {0 1} {
-			    test ${displaced-stepping} ${non-stop} ${target-non-stop} \
+			    test ${step_over_mode} ${non-stop} ${target-non-stop} \
 				${schedlock} ${cmd} ${ns_stop_all}
 			}
 		    } else {
-			test ${displaced-stepping} ${non-stop} ${target-non-stop} ${schedlock} ${cmd} 0
+			test ${step_over_mode} ${non-stop} ${target-non-stop} ${schedlock} ${cmd} 0
 		    }
 		}
 	    }
