| # Copyright 2025-2026 Free Software Foundation, Inc. | |
| # | |
| # This program is free software; you can redistribute it and/or modify | |
| # it under the terms of the GNU General Public License as published by | |
| # the Free Software Foundation; either version 3 of the License, or | |
| # (at your option) any later version. | |
| # | |
| # This program is distributed in the hope that it will be useful, | |
| # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| # GNU General Public License for more details. | |
| # | |
| # You should have received a copy of the GNU General Public License | |
| # along with this program. If not, see <http://www.gnu.org/licenses/>. | |
| # In all-stop mode, set one inferior running in the background, then | |
| # continue a second inferior. When the second inferior hits a breakpoint, | |
| # both inferiors should be stopped. | |
| # This tests the use of native and remote targets. If we try to run | |
| # it with a board that forces native targets to become remote, then | |
| # this doesn't really make sense (for this test). | |
| require {string equal [target_info gdb_protocol] ""} | |
| source $srcdir/$subdir/multi-target.exp.tcl | |
| load_lib gdbserver-support.exp | |
| require allow_gdbserver_tests | |
| # This overrides the call in multi-target.exp.tcl. | |
| standard_testfile | |
| if { [build_executable "failed to build" $testfile $srcfile] } { | |
| return | |
| } | |
| # Start two inferiors, TARGET_TYPE_1 and TARGET_TYPE_2 are strings, either | |
| # 'extended-remote' or 'native', and control the connection type of each | |
| # inferior. | |
| # | |
| # Set the first inferior running in the background, then continue theA | |
| # second inferior allowing it to hit a breakpoint. | |
| # | |
| # Once the breakpoint is hit, both inferiors should be stopped. | |
| proc run_test { target_type_1 target_type_2 } { | |
| cleanup_gdbservers | |
| clean_restart | |
| gdb_test "disconnect" ".*" | |
| gdb_test_no_output "set sysroot" | |
| # multi-target depends on target running in non-stop mode. Force it | |
| # on for remote targets, until this is the default. | |
| gdb_test_no_output "maint set target-non-stop on" | |
| # Run in all-stop mode. | |
| gdb_test_no_output "set non-stop off" | |
| if {![add_inferior 2 $target_type_1 $::binfile]} { | |
| return 0 | |
| } | |
| if {![add_inferior 3 $target_type_2 $::binfile]} { | |
| return 0 | |
| } | |
| # Check we see all the expected threads. | |
| gdb_test "info threads" \ | |
| [multi_line \ | |
| "\\s+Id\\s+Target Id\\s+Frame\\s*" \ | |
| "\\s+2\\.1\\s+\[^\r\n\]+" \ | |
| "\\*\\s+3\\.1\\s+\[^\r\n\]+"] \ | |
| "check expected threads exist" | |
| # The breakpoint will be set in both inferiors, but only inferior 3 | |
| # will hit it as 'wait_for_gdb' is cleared only in that inferior. | |
| gdb_breakpoint breakpt | |
| gdb_test "thread apply 3.1 set wait_for_gdb = 0" | |
| # Let inferior 2 run in the background. | |
| gdb_test "thread 2.1" | |
| gdb_test -no-prompt-anchor "continue&" | |
| # Run inferior 3 until it hits a breakpoint. | |
| gdb_test "thread 3.1" | |
| gdb_test "continue" \ | |
| [multi_line \ | |
| "Thread 3\\.1 \[^\r\n\]+ hit Breakpoint \[^\r\n\]+, breakpt \\(\\) \[^\r\n\]+" \ | |
| "$::decimal\\s+\[^\r\n\]+"] \ | |
| "continue to breakpt function" | |
| # Check the state of all threads. None should be running. | |
| set saw_inferior_2 false | |
| set saw_inferior_3 false | |
| gdb_test_multiple "info threads" "check threads after stop" { | |
| -re "^info threads\r\n" { | |
| exp_continue | |
| } | |
| -re "^\\s+Id\\s+Target Id\\s+Frame\\s*\r\n" { | |
| exp_continue | |
| } | |
| -re "^\\s+2\\.1\\s+\[^\r\n\]+\\s+\\(running\\)\\s*\r\n" { | |
| # Don't count this as seeing inferior 2 as the thread is | |
| # incorrectly still marked as running. By not setting the | |
| # SAW_INFERIOR_2 flag this test will now fail. | |
| exp_continue | |
| } | |
| -re "^\\s+2\\.1\\s+\[^\r\n\]+\r\n" { | |
| set saw_inferior_2 true | |
| exp_continue | |
| } | |
| -re "^\\*\\s+3\\.1\\s+\[^\r\n\]+\r\n" { | |
| set saw_inferior_3 true | |
| exp_continue | |
| } | |
| -re "^$::gdb_prompt $" { | |
| gdb_assert { $saw_inferior_2 && $saw_inferior_3 } \ | |
| $gdb_test_name | |
| } | |
| -re "^\[^\r\n\]*\r\n" { | |
| exp_continue | |
| } | |
| } | |
| } | |
| set all_target_types { extended-remote native } | |
| foreach_with_prefix target_type_1 $all_target_types { | |
| foreach_with_prefix target_type_2 $all_target_types { | |
| run_test $target_type_1 $target_type_2 | |
| } | |
| } | |
| multi_target_cleanup |