You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */
-static int global = 0;
+#include <stdlib.h>
+#include <pthread.h>
+#include <unistd.h>
+#include <assert.h>
+
+/* Used for thread synchronisation. */
+
+pthread_mutex_t g_mutex = PTHREAD_MUTEX_INITIALIZER;
+pthread_cond_t g_cond = PTHREAD_COND_INITIALIZER;
+
+/* This is set by GDB. */
+
+volatile int wait_for_gdb = 1;
+
+/* This is used to create some work for GDB to step through. */
+
+volatile int global_var = 0;
+
+/* A simple thread worker function. */
+
+void*
+worker_thread_func (void *arg)
+{
+ int res;
+
+ /* Grab the mutex. This completes once the main thread is waiting. */
+ res = pthread_mutex_lock (&g_mutex);
+ assert (res == 0);
+
+ /* Wake the main thread, letting it know that we are here. At this
+ point the main thread is still blocked as we hold G_MUTEX. */
+ res = pthread_cond_signal (&g_cond);
+
+ /* Now we wait. This releases G_MUTEX and allows the main thread to
+ continue. */
+ res = pthread_cond_wait (&g_cond, &g_mutex);
+ assert (res == 0);
+
+ /* Unlock the mutex. We're all done now. */
+ res = pthread_mutex_unlock (&g_mutex);
+ assert (res == 0);
+
+ return NULL;
+}
int
-main ()
+main (void)
{
- global++;
- global++;
+ pthread_t thr;
+ int res;
+
+ /* Lock G_MUTEX before creating the worker thread. */
+ pthread_mutex_lock (&g_mutex);
+
+ res = pthread_create (&thr, NULL, worker_thread_func, NULL);
+ assert (res == 0);
+
+ /* Release G_MUTEX and wait for the worker thread. */
+ res = pthread_cond_wait (&g_cond, &g_mutex);
+ assert (res == 0);
+
+ global_var++; /* Break here. */
+ global_var++; /* Second. */
+ global_var++; /* Third. */
+
+ while (wait_for_gdb)
+ sleep(1);
+
+ /* Notify the worker thread, it will exit once G_MUTEX is released. */
+ pthread_cond_signal (&g_cond);
+ pthread_mutex_unlock (&g_mutex);
+
+ /* Wait for the worker to actually exit. */
+ res = pthread_join (thr, NULL);
+ assert (res == 0);
+
+ /* Clean up the mutex and condition variable. */
+ pthread_mutex_destroy (&g_mutex);
+ pthread_cond_destroy (&g_cond);
+
return 0;
}
standard_testfile
-if { [prepare_for_testing "failed to prepare" $testfile $srcfile] } {
+if { [prepare_for_testing "failed to prepare" $testfile $srcfile \
+ {debug pthreads}] } {
return
}
return
}
-gdb_test "inferior 1" ".*Switching to inferior 1 .* to thread 1 .*" \
- "inferior switch is not suppressed"
+delete_breakpoints
+
+gdb_breakpoint [gdb_get_line_number "Break here"]
+gdb_continue_to_breakpoint "threads created"
+
+if {![use_gdb_stub]} {
+ gdb_test "add-inferior -exec $binfile" ".*" \
+ "add a second inferior"
+
+ gdb_test "inferior 2" ".*Switching to inferior 2 .*" \
+ "inferior switch is not suppressed"
+ gdb_test "info breakpoints"
+ gdb_test "info inferiors"
+ gdb_test "info connections"
+ gdb_run_cmd
+ gdb_test_multiple "" "stop at breakpoint in inferior 2" {
+ -wrap -re "Breakpoint ${::decimal}(?:\\.${::decimal})?, main .*" {
+ pass $gdb_test_name
+ }
+ }
+}
gdb_test_no_output "set suppress-cli-notifications on"
-gdb_test_no_output "inferior 1" "inferior switch is suppressed"
+if {![use_gdb_stub]} {
+ gdb_test_no_output "inferior 1" \
+ "inferior switch is suppressed when changing inferior"
+}
+gdb_test_no_output "inferior 1" \
+ "inferior switch is suppressed when same inferior selected"
gdb_test_no_output "next" "stepping is suppressed"
+gdb_test_no_output "thread 2" "switch to a new thread"
+gdb_test_no_output "thread 2" "switch to the same thread"
# Now check that suppression can be turned back off.
gdb_test_no_output "set suppress-cli-notifications off"
-gdb_test "inferior 1" ".*Switching to inferior 1 .* to thread 1 .*" \
- "inferior switch is not suppressed again"
-gdb_test "next" "return 0;" "stepping is not suppressed"
+gdb_test "thread 1" \
+ [multi_line \
+ "\\\[Switching to thread 1\[^\r\n\]*\\\]" \
+ "#0\\s+main\[^\r\n\]+" \
+ "\[^\r\n\]+Second\\. \\*/"]
+gdb_test_no_output "set wait_for_gdb = 0" \
+ "set wait_for_gdb in first inferior"
+
+if {![use_gdb_stub]} {
+ gdb_test "inferior 2" ".*Switching to inferior 2 .* to thread 2\\.1 .*" \
+ "inferior switch is not suppressed again"
+ gdb_test "next" ".*Second.*" "stepping is not suppressed"
+ gdb_test_no_output "set wait_for_gdb = 0" \
+ "set wait_for_gdb in second inferior"
+}
match_re_or_ensure_no_output $mi_re "select thread, event on MI "
}
- # Do the 'thread' command to select the same thread. We shouldn't receive
- # an event on MI, since we won't actually switch thread.
-
- set mi_re ""
+ # Do the 'thread' command to select the same thread. We
+ # should see the same thread events.
with_spawn_id $gdb_main_spawn_id {
gdb_test "thread 1.2" $cli_re "select thread again"
match_re_or_ensure_no_output $mi_re "select thread, event on MI again"
}
+ # Use the 'frame' command to select frame 1. In either mode
+ # the current thread is stopped, so this should work.
+ with_spawn_id $gdb_main_spawn_id {
+ gdb_test "frame 1" [make_cli_re $mode -1 -1 1] \
+ "select frame 1"
+ }
+
+ with_spawn_id $mi_spawn_id {
+ match_re_or_ensure_no_output [make_mi_re $mode 2 1 event] \
+ "select frame 1, event on MI"
+ }
+
+ # Reselect the current thread. GDB will switch back to
+ # frame #0, and send CLI and MI notifications.
+ with_spawn_id $gdb_main_spawn_id {
+ gdb_test "thread 1.2" $cli_re \
+ "select thread again, resetting frame"
+ }
+
+ with_spawn_id $mi_spawn_id {
+ match_re_or_ensure_no_output $mi_re \
+ "select thread again, resetting frame, event on MI"
+ }
+
# Try the 'thread' command without arguments.
set cli_re "\\\[Current thread is 1\\.2.*\\\]"
match_re_or_ensure_no_output $mi_re "select thread, event on MI"
}
- # Do the 'thread' command to select the third thread again. Again, we
- # shouldn't receive an event on MI.
-
- set mi_re ""
+ # Do the 'thread' command to select the third thread again.
+ # We should get the same thread events again as selecting the
+ # same thread still resets the frame to #0.
with_spawn_id $gdb_main_spawn_id {
gdb_test "thread 1.3" $cli_re "select thread again"
match_re_or_ensure_no_output $mi_re "select thread again, event on MI"
}
+ # In non-stop mode the current thread is still running, so we
+ # cannot change the selected frame.
+ if { $mode eq "all-stop" } {
+ # Use the 'frame' command to select frame 1.
+ with_spawn_id $gdb_main_spawn_id {
+ gdb_test "frame 1" [make_cli_re $mode -1 -1 1] \
+ "select frame 1"
+ }
+
+ with_spawn_id $mi_spawn_id {
+ match_re_or_ensure_no_output [make_mi_re $mode 3 1 event] \
+ "select frame 1, event on MI"
+ }
+
+ # Reselect the current thread. GDB will switch back to
+ # frame #0, and send CLI and MI notifications.
+ with_spawn_id $gdb_main_spawn_id {
+ gdb_test "thread 1.3" $cli_re \
+ "select thread again, resetting frame"
+ }
+
+ with_spawn_id $mi_spawn_id {
+ match_re_or_ensure_no_output $mi_re \
+ "select thread again, resetting frame, event on MI"
+ }
+ }
+
# Try the 'thread' command without arguments.
set cli_re "\\\[Current thread is 1\\.3 ${any}\\\]"
match_re_or_ensure_no_output "$cli_re\r\n" "select thread, event on CLI"
}
- # Do the 'thread' command to select the same thread. We shouldn't
- # receive an event on CLI, since we won't actually switch thread.
-
- set mi_re [make_cli_in_mi_re $command $cli_in_mi_mode $mode 0 -1 1.2 2 0]
- set cli_re ""
+ # Do the 'thread' command to select the same thread. We
+ # should see the same thread events.
with_spawn_id $mi_spawn_id {
mi_gdb_test $command $mi_re "select thread again"
}
with_spawn_id $gdb_main_spawn_id {
- match_re_or_ensure_no_output $cli_re "select thread again, event on CLI"
+ match_re_or_ensure_no_output "$cli_re\r\n" "select thread again, event on CLI"
+ }
+
+ # In non-stop mode the current thread is still running, so we
+ # cannot change the selected frame. Use 'frame' command to
+ # select frame 1.
+ set f_command [make_cli_in_mi_command $cli_in_mi_mode "frame 1"]
+ set f_cli_re [make_cli_re $mode -1 -1 1]
+ set f_mi_re [make_cli_in_mi_re $f_command \
+ $cli_in_mi_mode $mode 1 -1 -1 2 1]
+
+ with_spawn_id $mi_spawn_id {
+ mi_gdb_test $f_command $f_mi_re "select frame 1"
+ }
+
+ with_spawn_id $gdb_main_spawn_id {
+ match_re_or_ensure_no_output "$f_cli_re\r\n" \
+ "select frame 1, event on CLI"
+ }
+
+ # Reselect the current thread. GDB will switch back to
+ # frame #0, and send CLI and MI notifications.
+ with_spawn_id $mi_spawn_id {
+ mi_gdb_test $command $mi_re \
+ "select thread again, resetting frame"
+ }
+
+ with_spawn_id $gdb_main_spawn_id {
+ match_re_or_ensure_no_output "$cli_re\r\n" \
+ "select thread again, resetting frame, event on CLI"
}
# Try the 'thread' command without arguments.
match_re_or_ensure_no_output "$cli_re\r\n" "select thread, event on CLI"
}
- # Do the 'thread' command to select the third thread again. Again, we
- # shouldn't receive an event on MI.
-
- if { $mode == "all-stop" } {
- set mi_re [make_cli_in_mi_re $command $cli_in_mi_mode $mode 0 -1 1.3 3 0]
- } else {
- set mi_re [make_cli_in_mi_re $command $cli_in_mi_mode $mode 0 -1 1.3 3 -1]
- }
- set cli_re ""
+ # Do the 'thread' command to select the third thread again.
+ # We should see the same thread events.
with_spawn_id $mi_spawn_id {
mi_gdb_test $command $mi_re "select thread again"
}
with_spawn_id $gdb_main_spawn_id {
- match_re_or_ensure_no_output $cli_re "select thread again, event on CLI"
+ match_re_or_ensure_no_output "$cli_re\r\n" "select thread again, event on CLI"
+ }
+
+ # In non-stop mode the current thread is now running, so we
+ # cannot switch frames. In all-stop mode all threads are
+ # stopped, so frame switching is fine.
+ if { $mode eq "all-stop" } {
+ # Use 'frame' command to select frame 1.
+ set f_command [make_cli_in_mi_command $cli_in_mi_mode "frame 1"]
+ set f_cli_re [make_cli_re $mode -1 -1 1]
+ set f_mi_re [make_cli_in_mi_re $f_command \
+ $cli_in_mi_mode $mode 1 -1 -1 3 1]
+ with_spawn_id $mi_spawn_id {
+ mi_gdb_test $f_command $f_mi_re "select frame 1"
+ }
+
+ with_spawn_id $gdb_main_spawn_id {
+ match_re_or_ensure_no_output "$f_cli_re\r\n" \
+ "select frame 1, event on CLI"
+ }
+
+ # Reselect the current thread. GDB will switch back to
+ # frame #0, and send CLI and MI notifications.
+ with_spawn_id $mi_spawn_id {
+ mi_gdb_test $command $mi_re \
+ "select thread again, resetting frame"
+ }
+
+ with_spawn_id $gdb_main_spawn_id {
+ match_re_or_ensure_no_output "$cli_re\r\n" \
+ "select thread again, resetting frame, event on CLI"
+ }
}
+
# Try the 'thread' command without arguments.
set command [make_cli_in_mi_command $cli_in_mi_mode "thread"]