1# Copyright (C) 1996, 1997, 2002, 2003, 2007, 2008, 2009, 2010, 2011 2# Free Software Foundation, Inc. 3 4# This program is free software; you can redistribute it and/or modify 5# it under the terms of the GNU General Public License as published by 6# the Free Software Foundation; either version 3 of the License, or 7# (at your option) any later version. 8# 9# This program is distributed in the hope that it will be useful, 10# but WITHOUT ANY WARRANTY; without even the implied warranty of 11# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12# GNU General Public License for more details. 13# 14# You should have received a copy of the GNU General Public License 15# along with this program. If not, see <http://www.gnu.org/licenses/>. 16 17# This file was written by Daniel Jacobowitz <drow@mvista.com> 18# (parts based on pthreads.exp by Fred Fish (fnf@cygnus.com). 19# 20# This test covers the various forms of "set scheduler-locking". 21 22if $tracelevel then { 23 strace $tracelevel 24} 25 26 27set testfile "schedlock" 28set srcfile ${testfile}.c 29set binfile ${objdir}/${subdir}/${testfile} 30 31# The number of threads, including the main thread. 32set NUM 2 33 34if {[gdb_compile_pthreads "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable [list debug "incdir=${objdir}"]] != "" } { 35 return -1 36} 37 38# Now we can proceed with the real testing. 39 40proc get_args { } { 41 global list_count 42 global gdb_prompt 43 global NUM 44 45 set pattern "(\[0-9\]+)" 46 for {set i 1} {[expr $i < $NUM]} {incr i} { 47 append pattern ", (\[0-9\]+)" 48 } 49 50 gdb_test_multiple "print args" "listed args ($list_count)" { 51 -re "\\\$\[0-9\]+ = {$pattern}.*$gdb_prompt $" { 52 set list_count [expr $list_count + 1] 53 pass "listed args ($list_count)" 54 55 set result "" 56 for {set i 1} {[expr $i <= $NUM]} {incr i} { 57 lappend result $expect_out($i,string) 58 } 59 return $result 60 } 61 } 62} 63 64proc stop_process { description } { 65 global gdb_prompt 66 67 # For this to work we must be sure to consume the "Continuing." 68 # message first, or GDB's signal handler may not be in place. 69 after 1000 {send_gdb "\003"} 70 gdb_expect { 71 -re "Program received signal SIGINT.*$gdb_prompt $" 72 { 73 pass $description 74 } 75 timeout 76 { 77 fail "$description (timeout)" 78 } 79 } 80} 81 82proc get_current_thread { description } { 83 global gdb_prompt 84 85 gdb_test_multiple "bt" "$description" { 86 -re "thread_function \\(arg=0x(\[0-9\])\\).*$gdb_prompt $" { 87 pass $description 88 return $expect_out(1,string) 89 } 90 } 91 return "" 92} 93 94proc my_continue { msg } { 95 gdb_test_multiple "continue" "continuing ($msg)" { 96 -re "Continuing" { 97 pass "continue ($msg)" 98 } 99 } 100 101 stop_process "stop all threads ($msg)" 102 103 # Make sure we're in one of the non-main looping threads. 104 gdb_breakpoint [concat [gdb_get_line_number "schedlock.exp: main loop"] " if arg != 0"] 105 gdb_continue_to_breakpoint "return to loop ($msg)" 106 delete_breakpoints 107} 108 109proc step_ten_loops { msg } { 110 global gdb_prompt 111 112 for {set i 0} {[expr $i < 10]} {set i [expr $i + 1]} { 113 set other_step 0 114 gdb_test_multiple "step" "step to increment ($msg $i)" { 115 -re ".*myp\\) \\+\\+;\[\r\n\]+$gdb_prompt $" { 116 pass "step to increment ($msg $i)" 117 } 118 -re "$gdb_prompt $" { 119 if {$other_step == 0} { 120 set other_step 1 121 send_gdb "step\n" 122 exp_continue 123 } else { 124 fail "step to increment ($msg $i)" 125 # FIXME cascade? 126 } 127 } 128 } 129 } 130} 131 132# Start with a fresh gdb. 133 134gdb_exit 135gdb_start 136gdb_reinitialize_dir $srcdir/$subdir 137 138# We'll need this when we send_gdb a ^C to GDB. Need to do it before we 139# run the program and gdb starts saving and restoring tty states. 140# On Ultrix, we don't need it and it is really slow (because shell_escape 141# doesn't use vfork). 142if ![istarget "*-*-ultrix*"] then { 143 gdb_test "shell stty intr '^C'" ".*" 144} 145 146gdb_load ${binfile} 147 148gdb_test_no_output "set print sevenbit-strings" 149gdb_test_no_output "set width 0" 150 151runto_main 152 153# See if scheduler locking is available on this target. 154global gdb_prompt 155gdb_test_multiple "set scheduler-locking off" "scheduler locking set to none" { 156 -re "Target .* cannot support this command" { 157 unsupported "target does not support scheduler locking" 158 return 159 } 160 -re "$gdb_prompt $" { 161 pass "scheduler locking set to none" 162 } 163 timeout { 164 unsupported "target does not support scheduler locking (timeout)" 165 return 166 } 167} 168 169gdb_breakpoint [gdb_get_line_number "schedlock.exp: last thread start"] 170gdb_continue_to_breakpoint "all threads started" 171 172global list_count 173set list_count 0 174 175set start_args [get_args] 176 177# First make sure that all threads are alive. 178my_continue "initial" 179 180set cont_args [get_args] 181 182set bad 0 183for {set i 0} {[expr $i < $NUM]} {set i [expr $i + 1]} { 184 if {[lindex $start_args $i] == [lindex $cont_args $i]} { 185 incr bad 186 } 187} 188if { $bad == 0 } { 189 pass "all threads alive" 190} else { 191 fail "all threads alive ($bad/$NUM did not run)" 192} 193 194# We can't change threads, unfortunately, in current GDB. Use 195# whichever we stopped in. 196set curthread [get_current_thread "find current thread (1)"] 197 198 199 200 201# Test stepping without scheduler locking. 202gdb_test_no_output "set scheduler-locking off" 203 204step_ten_loops "unlocked" 205 206# Make sure we're still in the same thread. 207set newthread [get_current_thread "find current thread (2)"] 208if {$curthread == $newthread} { 209 pass "step without lock does not change thread" 210} else { 211 fail "step without lock does not change thread (switched to thread $newthread)" 212} 213 214set start_args $cont_args 215set cont_args [get_args] 216 217set num_other_threads 0 218for {set i 0} {[expr $i < $NUM]} {set i [expr $i + 1]} { 219 if {[lindex $start_args $i] == [lindex $cont_args $i]} { 220 if {$i == $curthread} { 221 fail "current thread stepped (didn't run)" 222 } 223 } else { 224 if {$i == $curthread} { 225 if {[lindex $start_args $i] == [expr [lindex $cont_args $i] - 10]} { 226 pass "current thread stepped" 227 } else { 228 fail "current thread stepped (wrong amount)" 229 } 230 } else { 231 set num_other_threads [expr $num_other_threads + 1] 232 } 233 } 234} 235if {$num_other_threads > 0} { 236 pass "other threads ran - unlocked" 237} else { 238 fail "other threads ran - unlocked" 239} 240 241# Test continue with scheduler locking 242gdb_test "set scheduler-locking on" "" 243 244my_continue "with lock" 245 246# Make sure we're still in the same thread. 247set newthread [get_current_thread "find current thread (3)"] 248if {$curthread == $newthread} { 249 pass "continue with lock does not change thread" 250} else { 251 fail "continue with lock does not change thread (switched to thread $newthread)" 252} 253 254set start_args $cont_args 255set cont_args [get_args] 256 257set num_other_threads 0 258for {set i 0} {[expr $i < $NUM]} {set i [expr $i + 1]} { 259 if {[lindex $start_args $i] == [lindex $cont_args $i]} { 260 if {$i == $curthread} { 261 fail "current thread ran (didn't run)" 262 } 263 } else { 264 if {$i == $curthread} { 265 pass "current thread ran" 266 } else { 267 incr num_other_threads 268 } 269 } 270} 271if {$num_other_threads > 0} { 272 fail "other threads didn't run - locked" 273} else { 274 pass "other threads didn't run - locked" 275} 276 277# Test stepping with scheduler locking 278step_ten_loops "locked" 279 280# Make sure we're still in the same thread. 281set newthread [get_current_thread "find current thread (2)"] 282if {$curthread == $newthread} { 283 pass "step with lock does not change thread" 284} else { 285 fail "step with lock does not change thread (switched to thread $newthread)" 286} 287 288set start_args $cont_args 289set cont_args [get_args] 290 291set num_other_threads 0 292for {set i 0} {[expr $i < $NUM]} {set i [expr $i + 1]} { 293 if {[lindex $start_args $i] == [lindex $cont_args $i]} { 294 if {$i == $curthread} { 295 fail "current thread stepped locked (didn't run)" 296 } 297 } else { 298 if {$i == $curthread} { 299 if {[lindex $start_args $i] == [expr [lindex $cont_args $i] - 10]} { 300 pass "current thread stepped locked" 301 } else { 302 fail "current thread stepped locked (wrong amount)" 303 } 304 } else { 305 incr num_other_threads 306 } 307 } 308} 309if {$num_other_threads > 0} { 310 fail "other threads didn't run - step locked" 311} else { 312 pass "other threads didn't run - step locked" 313} 314 315return 0 316