diff options
Diffstat (limited to 'gdb/testsuite/gdb.threads/linux-dp.exp')
-rw-r--r-- | gdb/testsuite/gdb.threads/linux-dp.exp | 186 |
1 files changed, 186 insertions, 0 deletions
diff --git a/gdb/testsuite/gdb.threads/linux-dp.exp b/gdb/testsuite/gdb.threads/linux-dp.exp new file mode 100644 index 0000000..87dc868 --- /dev/null +++ b/gdb/testsuite/gdb.threads/linux-dp.exp @@ -0,0 +1,186 @@ +# Copyright (C) 1999 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 2 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, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +# Please email any bugs, comments, and/or additions to this file to: +# bug-gdb@gnu.org + +#### Dining Philosophers, on LinuxThreads - Jim Blandy <jimb@cygnus.com> +#### +#### At the moment, GDB's support for LinuxThreads is pretty +#### idiosyncratic --- GDB's output doesn't look much like the output +#### it produces for other thread implementations, messages appear at +#### different times, etc. So these tests are specific to LinuxThreads. +#### +#### However, if all goes well, Linux will soon have a libthread_db +#### interface, and GDB will manage it the same way it does other +#### libthread_db-based systems. Then, we can adjust this file to +#### work with any such system. + +### Other things we ought to test: +### stepping a thread while others are running +### killing and restarting +### quitting gracefully + +if $tracelevel then { + strace $tracelevel +} + +set prms_id 0 +set bug_id 0 + +# This only works with Linux configurations. +if ![istarget *-*-linux-gnu] then { + return +} + +set testfile "linux-dp" +set srcfile ${testfile}.c +set binfile ${objdir}/${subdir}/${testfile} +if {[gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug libs=-lpthread}] != ""} { + gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail." +} + +gdb_start +gdb_reinitialize_dir $srcdir/$subdir +gdb_load ${binfile} +send_gdb "set print sevenbit-strings\n" ; gdb_expect -re "$gdb_prompt $" +runto_main + +# There should be no threads initially. +gdb_test "info threads" "" "info threads 1" + +# Try stepping over the thread creation function. +gdb_breakpoint [gdb_get_line_number "linuxthreads.exp: create philosopher"] +for {set i 0} {$i < 5} {incr i} { + gdb_continue_to_breakpoint "about to create philosopher: $i" + gdb_test "next" "\\\[New Thread .*\\\].*" "create philosopher: $i" +} + +# Run until there are some threads. +gdb_breakpoint [gdb_get_line_number "linuxthreads.exp: info threads 2"] +gdb_continue_to_breakpoint "main thread's sleep" +gdb_test "info threads" "7 Thread .*6 Thread .*5 Thread .*4 Thread .*3 Thread .*2 Thread .* \\(initial thread\\) main \\(argc=1, argv=.*\\) at .*linux-dp.c:.*1 Thread .* \\(manager thread\\).*" "info threads 2" + +# Try setting a thread-specific breakpoint. +gdb_breakpoint "print_philosopher thread 5" +gdb_continue_to_breakpoint "thread 5's print" +gdb_test "where" "print_philosopher.*philosopher.*pthread_start_thread.*" \ + "first thread-specific breakpoint hit" + +# Make sure it's catching the right thread. Try hitting the +# breakpoint ten times, and make sure we don't get anyone else. +set only_five 1 +for {set i 0} {$only_five > 0 && $i < 10} {incr i} { + gdb_continue_to_breakpoint "thread 5's print, pass: $i" + send_gdb "info threads\n" + gdb_expect { + -re "\\* 5 Thread .* print_philosopher .*\r\n$gdb_prompt $" { + # Okay this time. + } + -re ".*$gdb_prompt $" { + set only_five 0 + } + timeout { + set only_five -1 + } + } +} + +set name "thread-specific breakpoint is thread-specific" +if {$only_five == 1} { pass $name } +if {$only_five == 0} { fail $name } +if {$only_five == -1} { fail "$name (timeout)" } + + +### Select a particular thread. +proc select_thread {thread} { + global gdb_prompt + + send_gdb "thread $thread\n" + gdb_expect { + -re "\\\[Switching to thread .*\\\].*\r\n$gdb_prompt $" { + pass "selected thread: $thread" + } + -re "$gdb_prompt $" { + fail "selected thread: $thread" + } + timeout { + fail "selected thread: $thread (timeout)" + } + } +} + +### Select THREAD, check for a plausible backtrace, and make sure +### we're actually selecting a different philosopher each time. +### Return true if the thread had a stack which was not only +### acceptable, but interesting. SEEN should be an array in which +### SEEN(N) exists iff we have found philosopher number N before. +proc check_philosopher_stack {thread seen_name} { + global gdb_prompt + upvar $seen_name seen + + set name "philosopher is distinct: $thread" + set interesting 0 + + select_thread $thread + send_gdb "where\n" + gdb_expect { + -re ".* in philosopher \\(data=(0x\[0-9a-f\]+).*\r\n$gdb_prompt $" { + set data $expect_out(1,string) + if {[info exists seen($data)]} { + fail $name + } else { + pass $name + set seen($data) yep + } + set interesting 1 + } + -re "pthread_start_thread.*\r\n$gdb_prompt $" { + ## Maybe the thread hasn't started yet. + pass $name + } + -re " in \\?\\?.*\r\n$gdb_prompt $" { + ## Sometimes we can't get a backtrace. I'm going to call + ## this a pass, since we do verify that at least one + ## thread was interesting, so we can get more consistent + ## test suite totals. But in my heart, I think it should + ## be an xfail. + pass $name + } + -re "$gdb_prompt $" { + fail $name + } + timeout { + fail "$name (timeout)" + } + } + + return $interesting +} + +set any_interesting 0 +array set seen {} +for {set i 3} {$i <= 7} {incr i} { + if [check_philosopher_stack $i seen] { + set any_interesting 1 + } +} + +if {$any_interesting} { + pass "found an interesting thread" +} else { + fail "found an interesting thread" +} |