1# Copyright (C) 2004, 2007, 2008, 2010, 2011 Free Software Foundation, Inc. 2 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. 7# 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. 12# 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/>. 15 16# Test making hand function calls in multiple threads. 17 18set NR_THREADS 4 19 20if $tracelevel then { 21 strace $tracelevel 22} 23 24set testfile "hand-call-in-threads" 25set srcfile ${testfile}.c 26set binfile ${objdir}/${subdir}/${testfile} 27 28if {[gdb_compile_pthreads "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable [list debug "incdir=${objdir}" "additional_flags=-DNR_THREADS=$NR_THREADS"]] != "" } { 29 return -1 30} 31 32# Some targets can't do function calls, so don't even bother with this 33# test. 34if [target_info exists gdb,cannot_call_functions] { 35 setup_xfail "*-*-*" 2416 36 fail "This target can not call functions" 37 continue 38} 39 40proc get_dummy_frame_number { } { 41 global gdb_prompt 42 43 gdb_test_multiple "bt" "" { 44 -re "#(\[0-9\]*) *<function called from gdb>.*$gdb_prompt $" { 45 return $expect_out(1,string) 46 } 47 -re "$gdb_prompt $" { 48 return "" 49 } 50 timeout { 51 return "" 52 } 53 } 54 return "" 55} 56 57gdb_exit 58gdb_start 59gdb_reinitialize_dir $srcdir/$subdir 60gdb_load ${binfile} 61 62if { ![runto_main] } { 63 fail "Can't run to main" 64 return 0 65} 66 67gdb_test "break all_threads_running" \ 68 "Breakpoint 2 at .*: file .*${srcfile}, line .*" \ 69 "breakpoint on all_threads_running" 70 71gdb_test "break hand_call" \ 72 "Breakpoint 3 at .*: file .*${srcfile}, line .*" \ 73 "breakpoint on hand_call" 74 75# Run the program and make sure GDB reports that we stopped after 76# hitting breakpoint 2 in all_threads_running(). 77 78gdb_test "continue" \ 79 ".*Breakpoint 2, all_threads_running ().*" \ 80 "run to all_threads_running" 81 82# Before we start making hand function calls, turn on scheduler locking. 83 84gdb_test_no_output "set scheduler-locking on" "enable scheduler locking" 85gdb_test "show scheduler-locking" ".* locking scheduler .* is \"on\"." "show scheduler locking on" 86 87# Now hand-call a function in each thread, having the function 88# stop without returning. 89 90# Add one for the main thread. 91set total_nr_threads [expr $NR_THREADS + 1] 92 93# Thread numbering in gdb is origin-1, so begin numbering at 1. 94for { set i 1 } { $i <= $total_nr_threads } { incr i } { 95 set thread_nr $i 96 gdb_test "thread $thread_nr" ".*" \ 97 "prepare to make hand call, thread $thread_nr" 98 gdb_test "call hand_call()" "Breakpoint 3, .*" \ 99 "hand call, thread $thread_nr" 100} 101 102# Now have each hand-called function return. 103 104# Turn confirmation off for the "return" command. 105gdb_test_no_output "set confirm off" 106 107clear_xfail "*-*-*" 108 109for { set i 1 } { $i <= $total_nr_threads } { incr i } { 110 set thread_nr $i 111 gdb_test "thread $thread_nr" ".*" \ 112 "prepare to discard hand call, thread $thread_nr" 113 set frame_number [get_dummy_frame_number] 114 if { "$frame_number" == "" } { 115 fail "dummy stack frame number, thread $thread_nr" 116 # Need something. 117 set frame_number 0 118 } else { 119 pass "dummy stack frame number, thread $thread_nr" 120 } 121 # Pop the dummy frame. 122 gdb_test "frame $frame_number" ".*" "setting frame, thread $thread_nr" 123 gdb_test "return" ".*" "discard hand call, thread $thread_nr" 124 # In case getting the dummy frame number failed, re-enable for next iter. 125 clear_xfail "*-*-*" 126} 127 128# Make sure all dummy frames got popped. 129 130gdb_test_multiple "maint print dummy-frames" "all dummies popped" { 131 -re ".*stack=.*$gdb_prompt $" { 132 fail "all dummies popped" 133 } 134 -re ".*$gdb_prompt $" { 135 pass "all dummies popped" 136 } 137} 138 139# Before we resume the full program, turn off scheduler locking. 140gdb_test_no_output "set scheduler-locking off" "disable scheduler locking" 141gdb_test "show scheduler-locking" ".* locking scheduler .* is \"off\"." "show scheduler locking off" 142 143# Continue one last time, the program should exit normally. 144# 145# ??? This currently doesn't work because gdb doesn't know how to singlestep 146# over reported breakpoints that weren't in the last thread to run. 147# Commented out until then. 148# 149# For reference sake ... 150# An alternative is to manually work around the issue by manually setting 151# the thread back to the first thread: the program is still at the 152# all_threads_running breakpoint, which wasn't the last thread to run, 153# and gdb doesn't know how to singlestep over reported breakpoints that 154# weren't in the last thread to run. 155#gdb_test "thread 1" ".*" "set thread to 1, prepare to resume" 156# 157#gdb_continue_to_end "hand-call-in-threads" 158 159return 0 160