Update copyright year range in header of all files managed by GDB
[binutils-gdb.git] / gdb / testsuite / gdb.threads / non-stop-fair-events.exp
blob8ce5712f0c1305878f777f6b9f2a7ebce92e3e87
1 # Copyright (C) 2014-2023 Free Software Foundation, Inc.
3 # This program is free software; you can redistribute it and/or modify
4 # it under the terms of the GNU General Public License as published by
5 # the Free Software Foundation; either version 3 of the License, or
6 # (at your option) any later version.
8 # This program is distributed in the hope that it will be useful,
9 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11 # GNU General Public License for more details.
13 # You should have received a copy of the GNU General Public License
14 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
16 # Test that GDB in non-stop mode gives roughly equal priority to
17 # events of all threads.
19 standard_testfile
20 set executable ${testfile}
22 if [target_info exists gdb,nosignals] {
23     verbose "Skipping ${testfile}.exp because of nosignals."
24     return -1
27 set options { "additional_flags=-DTIMEOUT=$timeout" debug pthreads }
28 if {[prepare_for_testing "failed to prepare" $testfile $srcfile $options] == -1} {
29     return -1
32 gdb_test_no_output "set non-stop on"
34 if ![runto_main] {
35     return -1
38 # We want "handle print", to make sure the target backend reports the
39 # signal to the run control core.
40 gdb_test "handle SIGUSR1 print nostop pass" ""
42 # Get current value of VAR from the inferior.  TEST is used as test
43 # message.
45 proc get_value {var test} {
46     global expect_out
47     global gdb_prompt
48     global decimal
50     set value -1
51     gdb_test_multiple "print $var" "$test" {
52         -re ".*= ($decimal).*\r\n$gdb_prompt $" {
53             set value $expect_out(1,string)
54             pass "$test"
55         }
56     }
57     return ${value}
60 set NUM_THREADS [get_value "num_threads" "get num_threads"]
62 # Account for the main thread.
63 incr NUM_THREADS
65 # Probe for displaced stepping support.  We're stopped at the main
66 # breakpoint.  If displaced stepping is supported, we should see
67 # related debug output.
68 set displaced_stepping_enabled 0
69 set msg "check displaced-stepping"
70 gdb_test_no_output "set debug displaced 1"
71 gdb_test_multiple "next" $msg {
72     -re "prepared successfully .*$gdb_prompt $" {
73         set displaced_stepping_enabled 1
74     }
75     -re ".*$gdb_prompt $" {
76     }
78 gdb_test_no_output "set debug displaced 0"
80 # Run threads to their start positions.  This prepares for a new test
81 # sequence.
83 proc restart {} {
84     global gdb_prompt
85     global NUM_THREADS
87     delete_breakpoints
89     gdb_test "print got_sig = 0" " = 0"
91     gdb_breakpoint [gdb_get_line_number "set thread breakpoint here"]
92     gdb_breakpoint [gdb_get_line_number "set kill breakpoint here"]
94     set test "continue -a&"
95     gdb_test_multiple $test $test {
96         -re "Continuing.\r\n$gdb_prompt " {
97             pass $test
98         }
99     }
101     for {set i 1} { $i <= $NUM_THREADS } { incr i } {
102         set test "thread $i restarted"
103         gdb_test_multiple "" $test {
104             -re "breakpoint here" {
105                 # The prompt was already matched in the "continue &"
106                 # test above.  We're now consuming asynchronous output
107                 # that comes after the prompt.
108                 pass $test
109             }
110         }
111     }
113     delete_breakpoints
116 # Run command and wait for the prompt, without end anchor.
118 proc gdb_test_no_anchor {cmd} {
119     global gdb_prompt
121     gdb_test_multiple $cmd $cmd {
122         -re "$gdb_prompt " {
123             pass $cmd
124         }
125     }
128 # Enable/disable debugging.
130 proc enable_debug {enable} {
132     # Comment out to debug problems with the test.
133     return
135     gdb_test_no_anchor "set debug infrun $enable"
136     gdb_test_no_anchor "set debug displaced $enable"
139 # The test proper.  SIGNAL_THREAD is the thread that has been elected
140 # to receive the SIGUSR1 signal.
142 proc test {signal_thread} {
143     global gdb_prompt
144     global NUM_THREADS
145     global timeout
146     global displaced_stepping_enabled
148     with_test_prefix "signal_thread=$signal_thread" {
149         restart
151         # Set all threads stepping the infinite loop line in parallel.
152         for {set i 2} { $i <= $NUM_THREADS } { incr i } {
153             gdb_test "thread $i" \
154                 "child_function.*set thread breakpoint here.*" \
155                 "switch to thread $i to step it"
157             if {$i == $signal_thread} {
158                 gdb_test "print signal_thread = self" " = .*"
159             }
161             gdb_test "step&" "" "set $i thread stepping"
162         }
164         gdb_test "thread 1" "Switching to .*" \
165             "switch to the main thread to queue signal"
167         # Let the main thread queue the signal.
168         gdb_breakpoint "loop_broke"
170         enable_debug 1
172         # On software single-step targets that don't support displaced
173         # stepping, threads keep hitting each others' single-step
174         # breakpoints, and then GDB needs to pause all threads to step
175         # past those.  The end result is that progress in the main
176         # thread will be slower and it may take a bit longer for the
177         # signal to be queued; bump the timeout.
178         if {!$displaced_stepping_enabled && ![can_hardware_single_step]} {
179             # The more threads we have, the longer it takes.
180             set factor $NUM_THREADS
181         } else {
182             set factor 1
183         }
184         with_timeout_factor $factor {
185             gdb_test "print timeout = $timeout" " = $timeout" \
186                 "set timeout in the inferior"
188             set saw_continuing 0
189             set test "continue &"
190             gdb_test_multiple $test $test {
191                 -re "Continuing.\r\n" {
192                     set saw_continuing 1
193                     exp_continue
194                 }
195                 -re "$gdb_prompt " {
196                     gdb_assert $saw_continuing $test
197                 }
198                 -re "infrun:" {
199                     exp_continue
200                 }
201             }
203             set gotit 0
205             # Wait for all threads to finish their steps, and for the main
206             # thread to hit the breakpoint.
207             for {set i 1} { $i <= $NUM_THREADS } { incr i } {
208                 set test "thread $i broke out of loop"
209                 set gotit 0
210                 gdb_test_multiple "" $test {
211                     -re "loop_broke" {
212                         # The prompt was already matched in the "continue
213                         # &" test above.  We're now consuming asynchronous
214                         # output that comes after the prompt.
215                         set gotit 1
216                         pass $test
217                     }
218                     -re "infrun:" {
219                         exp_continue
220                     }
221                 }
222                 if {!$gotit} {
223                     break
224                 }
225             }
226         }
228         enable_debug 0
230         # It's helpful to have this in the log if the test ever
231         # happens to fail.
232         gdb_test "info threads"
234         return $gotit
235     }
238 # The kernel/debug API may always walk its thread list looking for the
239 # first with an event, resulting in giving priority to e.g. the thread
240 # with lowest kernel thread ID.  So test once with the signal pending
241 # in each thread, except the main thread.
242 for {set i 2} { $i <= $NUM_THREADS } { incr i } {
243     if {![test $i]} {
244         # Avoid cascading timeouts, and bail out.
245         return
246     }