From mboxrd@z Thu Jan 1 00:00:00 1970 From: Jimmy Guo To: gdb-patches@sourceware.cygnus.com Subject: gdb.threads testsuite patch Date: Thu, 22 Jul 1999 18:52:00 -0000 Message-id: References: X-SW-Source: 1999-q3/msg00082.html This patch contains merged gdb.threads testsuite, and it concludes the HP <-> Cygnus gdb testsuite merge patches for now :) File renames / moves (a tar file of gdb.threads has been ftp'd over as ftp.cygnus.com:/incoming/hp_gdb.threads.tar): Old New --- --- gdb.hp/attach2.exp attach2.exp compiler.c gdb.hp/more-steps.c more-steps.c gdb.hp/more-steps.exp more-steps.exp gdb.hp/quicksort.c quicksort.c gdb.hp/quicksort.exp quicksort.exp gdb.hp/start-stop.c start-stop.c gdb.hp/start-stop.exp start-stop.exp gdb.hp/thr-lib.c thr-lib.c gdb.hp/thr-lib.exp thr-lib.exp gdb.hp/thr-lib.h thr-lib.h gdb.hp/thr-liblib.c thr-liblib.c gdb.hp/thr-stg.exp thr-stg.exp - Jimmy Guo, guo@cup.hp.com /opt/gnu/bin/diff -r -c -N ../gdb-19990719/gdb/testsuite/gdb.threads gdb/testsuite/gdb.threads diff -r -c -N ../gdb-19990719/gdb/testsuite/gdb.threads/Makefile.in gdb/testsuite/gdb.threads/Makefile.in *** ../gdb-19990719/gdb/testsuite/gdb.threads/Makefile.in Fri Oct 11 17:10:37 1996 --- gdb/testsuite/gdb.threads/Makefile.in Thu Jul 22 17:50:35 1999 *************** *** 1,7 **** VPATH = @srcdir@ srcdir = @srcdir@ ! EXECUTABLES = pthreads all: @echo "Nothing to be done for all..." --- 1,9 ---- VPATH = @srcdir@ srcdir = @srcdir@ ! EXECUTABLES = more-steps pthreads quicksort step start-stop thr-lib ! ! MISCELLANEOUS = thr-liblib.sl all: @echo "Nothing to be done for all..." *************** *** 15,21 **** check: clean mostlyclean: ! -rm -f *~ *.o a.out xgdb *.x *.ci *.tmp core* $(EXECUTABLES) distclean maintainer-clean realclean: clean -rm -f Makefile config.status config.log config.h --- 17,25 ---- check: clean mostlyclean: ! -rm -f *~ *.o *.ci ! -rm -f core $(EXECUTABLES) ! -rm -f $(MISCELLANEOUS) distclean maintainer-clean realclean: clean -rm -f Makefile config.status config.log config.h *************** *** 24,29 **** --- 28,34 ---- $(SHELL) ./config.status --recheck config.h: stamp-h ; @true + stamp-h: config.in config.status CONFIG_HEADERS=config.h:config.in $(SHELL) config.status diff -r -c -N ../gdb-19990719/gdb/testsuite/gdb.threads/attach2.exp gdb/testsuite/gdb.threads/attach2.exp *** ../gdb-19990719/gdb/testsuite/gdb.threads/attach2.exp Wed Dec 31 16:00:00 1969 --- gdb/testsuite/gdb.threads/attach2.exp Thu Jul 22 17:50:37 1999 *************** *** 0 **** --- 1,263 ---- + # attach.exp -- Expect script to test attaching to a threaded pgm + # Copyright (C) 1992 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@prep.ai.mit.edu + + if $tracelevel then { + strace $tracelevel + } + + if { ![istarget "hppa*-*-hpux11.*"] } { + verbose "HPUX thread test ignored for non-hppa or pre-HP/UX-10.30 targets." + return 0 + } + + set testfile quicksort + set srcfile ${srcdir}/${subdir}/${testfile}.c + set binfile ${objdir}/${subdir}/${testfile} + + if [get_compiler_info ${binfile}] { + return -1 + } + + set oldtimeout $timeout + set oldverbose $verbose + + # To build the executable we need to link against the thread library. + # + if { $hp_cc_compiler } { + set additional_flags "additional_flags=-Ae" + } else { + set additional_flags "" + } + + if { [gdb_compile "${srcdir}/${subdir}/${testfile}.c" "${binfile}" executable [list debug $additional_flags ldflags=-lpthread]] != "" } { + gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail." + } + + # Because we can't attach over nfs, copy binfile to /tmp/${binfile}.${pid} + # and replace binfile with a symbolic link + + set pid [pid] + exec /bin/cp -f ${binfile} /tmp/attach2.${pid} + exec rm -f ${binfile} + exec ln -s /tmp/attach2.${pid} ${binfile} + + # Thread stuff is _slow_; prepare for long waits. + # + # Further, this test has some "null" lines designed + # to consume output from gdb that was too late to be + # matched (sequence is "gdb_test" sends; timeout and + # on to next send; result finally comes in; mismatch). + # + # The null command is 'gdb_test "p \$pc" ".*" ""' + # NOTE: this command undoes any up/down stuff! + # + proc pre_timeout { how_long } { + global timeout + + set timeout [expr "$timeout + $how_long"] + } + + proc post_timeout {} { + global timeout + global oldtimeout + + set timeout $oldtimeout + gdb_test "p \$pc" ".*" "" + } + + # We used to wait 5 seconds , but tiamat is faster than + # hydra...or is it that the OS allocates time differently(?). + # + set delay 5 + if { ![istarget "hppa*-*-hpux11.*"] } { + set delay 45 + } + + gdb_exit + gdb_start + gdb_reinitialize_dir $srcdir/$subdir + + # Start the application running and get its pid. + # Then we wait for it to get started and attach. + # + set testpid [eval exec $binfile 1 &] + exec sleep $delay + + # Now attach to the file. + # + pre_timeout 100 + gdb_test "file $binfile" ".*" "Force switch to gdb64 if necessary." + gdb_test "attach $testpid" ".*Attaching to.*process.*Reading symbols from.*done.*" "attach to target" + post_timeout + + # Wait for things to quiesce. + # + exec sleep 0 + + send_gdb "bt\n" + + set do_return 0 + set do_go_to_118 0 + pre_timeout 400 + gdb_expect { + -re ".*sleep.*work_init.*main.*$gdb_prompt $" { + pass "at expected location" + } + -re ".*drand48.*$gdb_prompt $" { + set do_go_to_118 1 + } + -re ".*pthread_mutex_lock.*$gdb_prompt $" { + set do_go_to_118 1 + } + -re ".*pthread_mutex_unlock.*$gdb_prompt $" { + set do_go_to_118 1 + } + -re ".*main.*$gdb_prompt $" { + set do_go_to_118 1 + } + -re ".*No stack.*$gdb_prompt $" { + fail "Failed attach, change wait amount down, rest would fail" + set do_return 1 + } + -re ".*$gdb_prompt $" { + # Who knows? + # + set do_go_to_118 1 + } + timeout { + set do_return 1 + fail "timeout on bt, avoiding rest of test" + } + } + post_timeout + + # Too late; just give up. + # + if { $do_return } { + set timeout $oldtimeout + set verbose $oldverbose + return 0 + } + + # Maybe too early--set a temp break and continue. + # We have to set this on both paths, so that we can + # know what numbers breakpoints will be. + # + gdb_test "tb 118" ".*Breakpoint 1.*118.*" + if { $do_go_to_118 } { + pre_timeout 100 + send_gdb "c\n" + gdb_expect { + -re ".*at.*118.*118.*$gdb_prompt $" { + # Ok, just keep going + } + -re ".*Program exited.*$gdb_prompt $" { + fail "Attached too late, set wait amount downwards" + set timeout $oldtimeout + set verbose $oldverbose + return 0 + } + -re ".*$gdb_prompt $" { + fail "Unexpected result on attach" + set timeout $oldtimeout + set verbose $oldverbose + return 0 + } + timeout { + fail "timeout on continue " + } + } + post_timeout + } + gdb_test "delete 1" ".*" "delete bp 1 if it is still there." + + # Look at the threads. + # + pre_timeout 100 + gdb_test "info thread" ".*7.*6.*5.*4.*3.*2.*\\\* 1.*thread.*" "first info thread" + post_timeout + + # We expect to be inside the "sleep" call, so check that. + # + if { [expr "!$do_go_to_118"] } { + gdb_test "up" ".*\#1.*(nanosleep|_sigtimedwait|sigtimedwait).*" "up 1" + gdb_test "up" ".*\#2.*sleep.*" "up 2" + pre_timeout 100 + gdb_test "up" ".*\#3.*work_init.*$testfile.*c:11\[48\].*sleep.*" "up 3" + post_timeout + } else { + send_user "Skipped three tests\n" + } + + # Get out of that call. + # + gdb_test "b 120" ".*Breakpoint 2.*120.*" "set bp" + pre_timeout 100 + gdb_test "c" ".*Breakpoint 2.*at.*120.*" "hit bp" + post_timeout + + # Look at the threads. + # + pre_timeout 100 + gdb_test "info thread" ".*7.*6.*5.*4.*3.*2.*1.*thread.*$testfile.*c*120.*" "2nd info thread" + post_timeout + + # Do some more stuff, to make sure we can + # + gdb_test "thread 3" ".*Switching to.*thread.*ksleep.*" "switch thread" + + if [istarget "hppa2.0w-*-*"] { + gdb_test "up" ".*in .stub.*from.*libpthread.*" "up 5" + } else { + gdb_test "up" ".*_lwp_cond_timedwait.*" "up 5" + } + gdb_test "up" ".*pthread_cond_wait.*" "up 6" + gdb_test "up" ".*\#3.*worker.*144.*" "up 7" + gdb_test "up" ".*(__pthread_exit|__pthread_create_system).*" "up 8" + gdb_test "up" ".*Initial.*cannot go up.*" "found thread base" + + gdb_test "b 145 thr 3" ".*Breakpoint 3.*145.*" "thread-specific bp" + gdb_test "i b" ".*2.*breakpoint.*at.*120.*3.*breakpoint.*at.*145 thread 3.*" "show thread-specific bp" + gdb_test "del 2" ".*" + + gdb_test "c" ".*Breakpoint 3.*145.*" "hit thread-specific bp" + gdb_test "i th" ".*\\\* 3.*145.*" "at correct thread" + + pre_timeout 100 + gdb_test "n" ".*146.*" "next from thread-specific bp" + post_timeout + + gdb_test "d 3" ".*" + gdb_test "c" ".*Program exited normally\..*" "run to finish" + + # Done! + # + gdb_exit + + set timeout $oldtimeout + set verbose $oldverbose + + # Cleanup the file placed in /tmp and the symlink + # + exec rm -f ${binfile} /tmp/attach2.${pid} + + return 0 + + diff -r -c -N ../gdb-19990719/gdb/testsuite/gdb.threads/compiler.c gdb/testsuite/gdb.threads/compiler.c *** ../gdb-19990719/gdb/testsuite/gdb.threads/compiler.c Wed Dec 31 16:00:00 1969 --- gdb/testsuite/gdb.threads/compiler.c Thu Jul 22 17:48:46 1999 *************** *** 0 **** --- 1,31 ---- + /* Often the behavior of any particular test depends upon what compiler was + used to compile the test. As each test is compiled, this file is + preprocessed by the same compiler used to compile that specific test + (different tests might be compiled by different compilers, particularly + if compiled at different times), and used to generate a *.ci (compiler + info) file for that test. + + I.E., when callfuncs is compiled, a callfuncs.ci file will be generated, + which can then be sourced by callfuncs.exp to give callfuncs.exp access + to information about the compilation environment. + + TODO: It might be a good idea to add expect code that tests each + definition made with 'set" to see if one already exists, and if so + warn about conflicts if it is being set to something else. */ + + /* This needs to be kept in sync with whatis.c and gdb.exp(get_compiler_info). + If this ends up being hairy, we could use a common header file. */ + + #if defined (__STDC__) || defined (_AIX) + set signed_keyword_not_used 0 + #else + set signed_keyword_not_used 1 + #endif + + #if defined (__GNUC__) + set gcc_compiled __GNUC__ + #else + set gcc_compiled 0 + #endif + + return 0 diff -r -c -N ../gdb-19990719/gdb/testsuite/gdb.threads/more-steps.c gdb/testsuite/gdb.threads/more-steps.c *** ../gdb-19990719/gdb/testsuite/gdb.threads/more-steps.c Wed Dec 31 16:00:00 1969 --- gdb/testsuite/gdb.threads/more-steps.c Thu Jul 22 17:50:38 1999 *************** *** 0 **** --- 1,140 ---- + /* BeginSourceFile more_steps.c + + This file creates a lot of threads which then execute + in parallel, so that wdb can be tested on handling + simultaneous thread events. + + To compile: + + cc -Ae +DA1.0 -g -o more_steps -lpthread more_steps.c + + To run: + + more_threads + */ + + #include + #include + #include + #include + #include + + #define TRUE 1 + #define FALSE 0 + #define N_THREADS 3 + #define PHASES 3 + + typedef enum { + ZERO, + ONE, + TWO, + THREE + } phase_t; + + /* Uncomment to turn on debugging output */ + /* #define DEBUG */ + + /* Locks. + */ + int lock_one; /* Main W, others R */ + int lock_two; /* ditto */ + int lock_end[ N_THREADS ]; /* Main R, others R[i] */ + int phase[ N_THREADS ]; + + /* Routine for each thread to run. + */ + void *spin( vp ) + void * vp; + { + int me = (int) vp; + int i; + + lock_end[ me ] = TRUE; + + phase[ me ] = ONE; + + while( lock_one ); + + phase[ me ] = TWO; + + while( lock_two ); + + phase[ me ] = THREE; + + lock_end[ me ] = FALSE; + } + + void + do_pass() + { + int i; + pthread_t t[ N_THREADS ]; + int err; + int done; + + /* Start N_THREADS threads, then join them so + * that they are terminated. + */ + for( i = 0; i < N_THREADS; i++ ) { + err = pthread_create( &t[i], NULL, spin, (void *)i ); + if( err != 0 ) { + printf( "== Start/stop, error in thread %d create\n", i ); + } + } + + /* Do phase 1. + */ + lock_one = FALSE; + + /* Do phase 2. + */ + lock_two = FALSE; + + /* Be done. + */ + done = 0; + while( !done ) { + + /* Be optimistic. + */ + done = 1; + for( i = 0; i < N_THREADS; i++ ) { + if( lock_end[i] ) { + /* Thread "i" is not ready yet. + */ + done = 0; + break; + } + } + } + + /* Finish up + */ + for( i = 0; i < N_THREADS; i++ ) { + err = pthread_join(t[i], NULL ); /* Line 105 */ + if( err != 0 ) { /* Line 106 */ + printf( "== Start/stop, error in thread %d join\n", i ); + } + } + + i = 10; /* Line 109. Null line for setting bpts on. */ + } + + main( argc, argv ) + int argc; + char **argv; + { + int i; + + /* Init + */ + lock_one = TRUE; + lock_two = TRUE; + for( i = 0; i < N_THREADS; i++ ) { + lock_end[i] = TRUE; + phase[i] = ZERO; + } + + do_pass(); + return(0); + } diff -r -c -N ../gdb-19990719/gdb/testsuite/gdb.threads/more-steps.exp gdb/testsuite/gdb.threads/more-steps.exp *** ../gdb-19990719/gdb/testsuite/gdb.threads/more-steps.exp Wed Dec 31 16:00:00 1969 --- gdb/testsuite/gdb.threads/more-steps.exp Thu Jul 22 17:50:38 1999 *************** *** 0 **** --- 1,131 ---- + # more-steps.exp -- Expect script to test gdb's ability to step threaded pgms + # Copyright (C) 1992 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@prep.ai.mit.edu + + if $tracelevel then { + strace $tracelevel + } + + if { ![istarget "hppa*-*-hpux11.*"] } { + verbose "HPUX thread test ignored for non-hppa or pre-HP/UX-10.30 targets." + return 0 + } + + set testfile more-steps + set srcfile ${srcdir}/${subdir}/${testfile}.c + set binfile ${objdir}/${subdir}/${testfile} + + if [get_compiler_info ${binfile}] { + return -1 + } + + # To build the executable we need to link against the thread library. + # + if { $hp_cc_compiler } { + set additional_flags "additional_flags=-Ae" + } else { + set additional_flags "" + } + + if { [gdb_compile "${srcdir}/${subdir}/${testfile}.c" "${binfile}" executable [list debug $additional_flags ldflags=-lpthread]] != "" } { + gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail." + } + + # Thread stuff is _slow_; prepare for long waits. + # + set oldtimeout $timeout + set timeout [expr "$timeout + 300"] + set oldverbose $verbose + #set verbose 40 + + # Further, this test has some "null" lines designed + # to consume output from gdb that was too late to be + # matched (sequence is "gdb_test" sends; timeout and + # on to next send; result finally comes in; mismatch). + # + # The null command is 'gdb_test "p \$pc" ".*" ""' + # + # NOTE: to pass a literal "$", "/" or "*" (etc.) to gdb_test, + # remember that the pattern will be escaped once and + # $-evaluated twice: + # + # "\\\*" matches "\*" + # "\$" matches "$" + # + proc fix_timeout {} { + gdb_test "p \$pc" ".*" "" + } + + #========================= + # + # Simple sanity test first. + # + gdb_exit + gdb_start + gdb_reinitialize_dir $srcdir/$subdir + gdb_load ${binfile} + + # First, step in the main thread. + # + gdb_test "b do_pass" ".*Breakpoint 1.*" "breakpoint at do_pass" + gdb_test "r" ".*Breakpoint 1.*do_pass.*" "run" + + # Breaks as well as nexts to make + # sure we can handle simultaneous hit + # of bpt and step, as well as stepping + # past bpts. + # + gdb_test "tb 87" ".*Breakpoint 2.*" "tbreak at line 87" + gdb_test "tb 91" ".*Breakpoint 3.*" "tbreak at line 91" + gdb_test "tb 96" ".*Breakpoint 4.*" "tbreak at line 96" + gdb_test "tb 113" ".*Breakpoint 5.*" "tbreak at line 113" + gdb_test "c" ".*do_pass.*87.*" "87" + gdb_test "n" ".*do_pass.*91.*" "n" + + # This only gets a number, as it doesn't + # hit a bpt. + # + gdb_test "n" ".*95.*" "n" + + gdb_test "n" ".*do_pass.*96.*" "n" + gdb_test "c" ".*do_pass.*113.*" "c" + gdb_test "c" ".*Program exited normally.*" "c" + + # Now step in a thread + # + gdb_test "r" ".*Breakpoint.*do_pass.*" "do_pass" + gdb_test "until 87" ".*do_pass.*87.*" "until" + gdb_test "thr 4" ".*Switching to thread 4.*spin.*56.*" "switch" + gdb_test "tb 60 thr 4" ".*Breakpoint.*" "tbreak at line 60 thread 4" + + # If we do "next" now, all the other threads + # can finish! + # + gdb_test "n" ".*58.*" "next line" + gdb_test "i th" ".*\\\* 4 sys.*spin.*1 sys.*do_pass.*" "still in 4" + + # Done! + # + gdb_exit + + set timeout $oldtimeout + set verbose $oldverbose + + return 0 + diff -r -c -N ../gdb-19990719/gdb/testsuite/gdb.threads/pthreads.exp gdb/testsuite/gdb.threads/pthreads.exp *** ../gdb-19990719/gdb/testsuite/gdb.threads/pthreads.exp Tue Feb 9 14:43:31 1999 --- gdb/testsuite/gdb.threads/pthreads.exp Thu Jul 22 17:50:37 1999 *************** *** 50,55 **** --- 50,56 ---- set options "debug" lappend options "incdir=${objdir}/${subdir}" lappend options "libs=$lib" + clone_output "Trying to link against $lib" set ccout [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable $options] switch -regexp -- $ccout { ".*no posix threads support.*" { *************** *** 65,73 **** --- 66,77 ---- {^$} { pass "successfully compiled posix threads test case" set built_binfile 1 + clone_output "Linking against $lib works." break } } + + clone_output "Failure ignored." } if {$built_binfile == "0"} { unsupported "Couldn't compile ${srcfile}, ${why_msg}" *************** *** 180,186 **** # We should be able to do an info threads before starting any others. send_gdb "info threads\n" gdb_expect { ! -re ".*Thread.*LWP.*main.*$gdb_prompt $" { pass "info threads" } -re "\r\n$gdb_prompt $" { --- 184,190 ---- # We should be able to do an info threads before starting any others. send_gdb "info threads\n" gdb_expect { ! -re ".*(Thread.*LWP| thread ).*main.*$gdb_prompt $" { pass "info threads" } -re "\r\n$gdb_prompt $" { *************** *** 193,223 **** # Extract the thread id number of main thread from "info threads" output. send_gdb "info threads\n" ! gdb_expect -re "(\[0-9\]+)(${horiz}Thread${horiz}main.*)($gdb_prompt $)" set main_id $expect_out(1,string) # Check that we can continue and create the first thread. gdb_test "break thread1" "Breakpoint .* file .*$srcdir.*" gdb_test "continue" \ ! "Continuing.*Breakpoint .*, thread1 \\(arg=0xfeedface\\).*at.*$srcfile.*" \ "Continue to creation of first thread" gdb_test "disable" "" # Extract the thread id number of thread 1 from "info threads" output. send_gdb "info threads\n" ! gdb_expect -re "(\[0-9\]+)(${horiz}Thread${horiz}thread1.*)($gdb_prompt $)" set thread1_id $expect_out(1,string) # Check that we can continue and create the second thread, # ignoring the first thread for the moment. gdb_test "break thread2" "Breakpoint .* file .*$srcdir.*" gdb_test "continue" \ ! "Continuing.*Breakpoint .*, thread2 \\(arg=0xdeadbeef\\).*at.*$srcfile.*" \ "Continue to creation of second thread" # Extract the thread id number of thread 2 from "info threads" output. send_gdb "info threads\n" ! gdb_expect -re "(\[0-9\]+)(${horiz}Thread${horiz}thread2.*)($gdb_prompt $)" set thread2_id $expect_out(1,string) return 1 --- 197,227 ---- # Extract the thread id number of main thread from "info threads" output. send_gdb "info threads\n" ! gdb_expect -re "(\[0-9\]+)${horiz}(Thread|thread)${horiz}main.*$gdb_prompt $" set main_id $expect_out(1,string) # Check that we can continue and create the first thread. gdb_test "break thread1" "Breakpoint .* file .*$srcdir.*" gdb_test "continue" \ ! "Continuing.*Breakpoint .*, thread1 \\(arg=0xfeedface.*\\).*at.*$srcfile.*" \ "Continue to creation of first thread" gdb_test "disable" "" # Extract the thread id number of thread 1 from "info threads" output. send_gdb "info threads\n" ! gdb_expect -re "(\[0-9\]+)${horiz}(Thread|thread)${horiz}thread1.*$gdb_prompt $" set thread1_id $expect_out(1,string) # Check that we can continue and create the second thread, # ignoring the first thread for the moment. gdb_test "break thread2" "Breakpoint .* file .*$srcdir.*" gdb_test "continue" \ ! "Continuing.*Breakpoint .*, thread2 \\(arg=0xdeadbeef.*\\).*at.*$srcfile.*" \ "Continue to creation of second thread" # Extract the thread id number of thread 2 from "info threads" output. send_gdb "info threads\n" ! gdb_expect -re "(\[0-9\]+)${horiz}(Thread|thread)${horiz}thread2.*$gdb_prompt $" set thread2_id $expect_out(1,string) return 1 *************** *** 232,240 **** } # Send a continue followed by ^C to the process to stop it. ! send_gdb "continue\n" set description "Stopped with a ^C" ! after 1000 [send_gdb "\003"] gdb_expect { -re "Program received signal SIGINT.*$gdb_prompt $" { pass $description --- 236,256 ---- } # Send a continue followed by ^C to the process to stop it. ! # ! # On fast systems the 'after 1000' part will have the threads ! # stopped by breakpoint SIGTRAP. ! # On HP-UX we'll just send ^C when we see that the threads are ! # running again. ! # - guo ! # set description "Stopped with a ^C" ! if [istarget "hppa*-hp-hpux*"] { ! send_gdb "continue\n" ! gdb_expect -re "Continuing" ! send_gdb "\003" ! } else { ! after 1000 [send_gdb "\003"] ! } gdb_expect { -re "Program received signal SIGINT.*$gdb_prompt $" { pass $description *************** *** 242,247 **** --- 258,266 ---- -re "Quit.*$gdb_prompt $" { pass $description } + -re "$gdb_prompt $" { + fail $description + } timeout { fail "$description (timeout)" } *************** *** 263,272 **** ".* in main \\(argc=.*, argv=.*\\).*" \ "check backtrace from main thread" gdb_test "thread apply $thread1_id backtrace" \ ! ".* in thread1 \\(arg=0xfeedface\\).*" \ "check backtrace from thread 1" gdb_test "thread apply $thread2_id backtrace" \ ! ".* in thread2 \\(arg=0xdeadbeef\\).*" \ "check backtrace from thread 2" # Check that we can apply the backtrace command to all --- 282,291 ---- ".* in main \\(argc=.*, argv=.*\\).*" \ "check backtrace from main thread" gdb_test "thread apply $thread1_id backtrace" \ ! ".* in thread1 \\(arg=0xfeedface.*\\).*" \ "check backtrace from thread 1" gdb_test "thread apply $thread2_id backtrace" \ ! ".* in thread2 \\(arg=0xdeadbeef.*\\).*" \ "check backtrace from thread 2" # Check that we can apply the backtrace command to all *************** *** 324,328 **** --- 343,355 ---- check_control_c check_backtraces } + + # let the program continue so we don't have the process hanging + # on the system + # - guo + send_gdb "disable\n" + gdb_expect -re "$gdb_prompt $" + send_gdb "continue\n" + gdb_expect -re "$gdb_prompt $" } clear_xfail "alpha-*-osf*" diff -r -c -N ../gdb-19990719/gdb/testsuite/gdb.threads/quicksort.c gdb/testsuite/gdb.threads/quicksort.c *** ../gdb-19990719/gdb/testsuite/gdb.threads/quicksort.c Wed Dec 31 16:00:00 1969 --- gdb/testsuite/gdb.threads/quicksort.c Thu Jul 22 17:50:38 1999 *************** *** 0 **** --- 1,284 ---- + /* BeginSourceFile quicksort.c + + This file is take from the DDE test system. It spawns six + threads to do a sort of an array of random numbers. + + The locations marked "quick N" are used in the test "quicksort.exp". + + The locations marked "att N" are used in the test "attach.exp". + + To compile: + + cc -Ae +DA1.0 -g -o quicksort -lpthread quicksort.c + + To run: + + quicksort --normal run + quicksort 1 --waits before starting to allow attach + */ + + #include + #include + #include + #include + #include + + #define TRUE 1 + #define FALSE 0 + #define SORTSET 100000 + + /* Uncomment to turn on debugging output */ + /* #define QUICK_DEBUG */ + + /* Uncomment to turn on wait on each thread create */ + /* #define THREAD_WAIT */ + + /* Fewer than SORT_DIRECT items are sorted with an insertion sort. */ + #define SORT_DIRECT 20 + + /* Work at this depth or less generates a separate work item. */ + #define DEFER_DEPTH 6 + + /* Workpile controller */ + typedef void (*work_proc_t)(void *); + + typedef struct workpile_struct { + pthread_mutex_t lock; /* mutex for this structure */ + pthread_cond_t work_wait; /* workers waiting for work */ + pthread_cond_t finish_wait; /* to wait for workers to finish */ + int max_pile; /* length of workpile array */ + work_proc_t worker_proc; /* work procedure */ + int n_working; /* number of workers working */ + int n_waiting; /* number of workers waiting for work */ + int n_pile; /* number of pointers in the workpile */ + int inp; /* FIFO input pointer */ + int outp; /* FIFO output pointer */ + void *pile[1]; /* array of pointers - the workpile */ + } *workpile_t; + + typedef struct { + float *data; /* Array to sort */ + int n; /* Number of elements in the array */ + int depth; /* Depth of recursion */ + workpile_t wp; /* Workpile to use */ + } quick_sort_args; + + /* True if waiting for attach. + */ + int wait_here = FALSE; + + static workpile_t quick_sort_workpile = NULL; + + void *worker(void * wptr); + + /* Allocates and initializes a workpile that holds max_pile entries. + * worker_proc is called to process each work item on the queue. + */ + workpile_t + work_init(int max_pile, work_proc_t worker_proc, int n_threads) + { + int err; + pthread_t t; + workpile_t *wpptr = (workpile_t *)malloc (sizeof(workpile_t)); + workpile_t wp = (workpile_t)malloc(sizeof (struct workpile_struct) + + (max_pile * sizeof (void *))); + if (wp != NULL) { + *wpptr = wp; + pthread_mutex_init(&wp->lock, NULL); + pthread_cond_init(&wp->work_wait, NULL); + pthread_cond_init(&wp->finish_wait, NULL); + wp->max_pile = max_pile; + wp->worker_proc = worker_proc; + wp->n_working = wp->n_waiting = wp->n_pile = 0; + wp->inp = wp->outp = 0; + while (n_threads--) { + err = pthread_create(&t, NULL, + worker, (void *)wpptr); + #ifdef QUICK_DEBUG + printf( "== Quicksort: created new thread\n" ); + #ifdef THREAD_WAIT + if( n_threads > 0 ) { + int i; + printf( "== Quicksort: waiting on user input of an integer\n" ); + scanf( "%d", &i ); + printf( "== Quicksort: continuing with quicksort\n" ); + } + #endif + #endif + + assert(err == 0); /* quick 1 */ + } + /* All the threads have now been created. + */ + assert( n_threads == -1 ); /* att 1 */ + if( wait_here ) { sleep(10); /* gdb.threads/attache.exp */ + #ifdef QUICK_DEBUG /* wants to hit 118 after c */ + printf( "== Quicksort: waiting for attach\n" ); + #endif + sleep( 25 ); + } + wait_here = 99; /* att 2, otherwise useless */ + } + return (wp); /* quick 2 */ + } + + /* + * Worker thread routine. Continuously looks for work, calls the + * worker_proc associated with the workpile to do work. + */ + void * + worker(void * wptr) + { + workpile_t wp; + void *ptr; + + wp = * (workpile_t *) wptr; + + pthread_mutex_lock(&wp->lock); + wp->n_working++; + for (;;) { + while (wp->n_pile == 0) { /* wait for new work */ + if (--wp->n_working == 0) + pthread_cond_signal(&wp->finish_wait); + wp->n_waiting++; + pthread_cond_wait(&wp->work_wait, &wp->lock); + wp->n_waiting--; /* quick 3 */ + wp->n_working++; + } + wp->n_pile--; + ptr = wp->pile[wp->outp]; + wp->outp = (wp->outp + 1) % wp->max_pile; + pthread_mutex_unlock(&wp->lock); + /* Call application worker routine. */ + (*wp->worker_proc)(ptr); + pthread_mutex_lock(&wp->lock); /* quick 4 */ + } + /* NOTREACHED */ + } + + /* Puts ptr in workpile. Called at the outset, or within a worker. */ + void + work_put(workpile_t wp, void *ptr) + { + pthread_mutex_lock(&wp->lock); + if (wp->n_waiting) { + /* idle workers to be awakened */ + pthread_cond_signal(&wp->work_wait); + } + assert(wp->n_pile != wp->max_pile); /* check for room */ + wp->n_pile++; + wp->pile[wp->inp] = ptr; + wp->inp = (wp->inp + 1) % wp->max_pile; + pthread_mutex_unlock(&wp->lock); + } + + + /* Wait until all work is done and workers quiesce. */ + void + work_wait(workpile_t wp) + { + pthread_mutex_lock(&wp->lock); + while(wp->n_pile !=0 || wp->n_working != 0) + pthread_cond_wait(&wp->finish_wait, &wp->lock); + pthread_mutex_unlock(&wp->lock); + } + + void + quick_sort_aux(float *data, int n, int depth, workpile_t wp, int deferrable) + { + int i,j; + + /* If array small, use insertion sort */ + if (n <= SORT_DIRECT) { + for (j = 1; j < n; j++) { + /* data[0..j-1] in sort; find a spot for data[j] */ + float key = data[j]; + for (i = j - 1; i >= 0 && key < data[i]; i--) + data[i+1] = data[i]; + data[i+1] = key; + } + return; + } + /* Defer this work to work queue if policy says so */ + if (deferrable && depth <= DEFER_DEPTH) { + quick_sort_args *q = (quick_sort_args *) + malloc(sizeof (quick_sort_args)); + assert(q != NULL); + q->data = data; q->n = n; q->depth = depth; q->wp = wp; + work_put(wp, (void *)q); + return; + } + /* Otherwise, partition data based on a median estimate */ + #define swap(i,j) {float t = data[i]; data[i] = data[j]; data[j] = t;} + i = 0; + j = n - 1; + for (;;) { + while (data[i] < data[j]) j--; + if (i >= j) break; + swap(i, j); i++; + while (data[i] < data[j]) i++; + if (i >= j) { i = j; break; } + swap(i, j); j--; + } + /* Median value is now at data[i] */ + /* Partitioned so that data[0..i-1] <= median <= data[i+1..n-1] */ + quick_sort_aux(data, i, depth+1, wp, TRUE); + quick_sort_aux(&data[i+1], n-i-1, depth+1, wp, TRUE); + } + /* Called from workpile controller with argument pointing to work. */ + void + quick_sort_worker(void *a) + { + quick_sort_args *q = (quick_sort_args *)a; + quick_sort_aux(q->data, q->n, q->depth, q->wp, FALSE); + free(q); + } + /* Main routine, called by client to do a sort. */ + void + quick_sort(float *data, int n) + { + if (quick_sort_workpile == NULL) { + int n_threads = 6; + quick_sort_workpile = work_init(2 << DEFER_DEPTH, + quick_sort_worker, n_threads); + assert(quick_sort_workpile != NULL); + } + + quick_sort_aux(data, n, 0, quick_sort_workpile, FALSE); + + /* Wait for all work to finish */ + work_wait(quick_sort_workpile); + + #ifdef QUICK_DEBUG + printf( "== Quicksort: done sorting\n" ); + #endif + } + + + main( argc, argv ) + int argc; + char **argv; + { + float data[SORTSET]; + int i; int debugging = 0; + + if((argc > 1) && (0 != argv )) { + if( 1 == atoi( argv[1] ) ) + wait_here = TRUE; + } + + for(i = 0; i < SORTSET; i++) + data[SORTSET -1 -i] = drand48(); + + for(i = 0; i < SORTSET; i++) + if (debugging) + printf("data[%d] = %f\n", i, data[i]); + + quick_sort(data, SORTSET); + for(i = 0; i < SORTSET; i++) + if (debugging) + printf("data[%d] = %f\n", i, data[i]); + + return(0); + } + /* EndSourceFile */ diff -r -c -N ../gdb-19990719/gdb/testsuite/gdb.threads/quicksort.exp gdb/testsuite/gdb.threads/quicksort.exp *** ../gdb-19990719/gdb/testsuite/gdb.threads/quicksort.exp Wed Dec 31 16:00:00 1969 --- gdb/testsuite/gdb.threads/quicksort.exp Thu Jul 22 18:50:01 1999 *************** *** 0 **** --- 1,839 ---- + # quicksort.exp -- Expect script to test gdb with quicksort.c + # Copyright (C) 1992 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@prep.ai.mit.edu + + if $tracelevel then { + strace $tracelevel + } + + if { ![istarget "hppa*-*-hpux11.*"] } { + verbose "HPUX thread test ignored for non-hppa or pre-HP/UX-10.30 targets." + return 0 + } + + set testfile quicksort + set srcfile ${srcdir}/${subdir}/${testfile}.c + set binfile ${objdir}/${subdir}/${testfile} + + if [get_compiler_info ${binfile}] { + return -1 + } + + # To build the executable we need to link against the thread library. + # + + if { $hp_cc_compiler } { + set additional_flags "additional_flags=-Ae" + } else { + set additional_flags "" + } + + if { [gdb_compile "${srcdir}/${subdir}/${testfile}.c" "${binfile}" executable [list debug $additional_flags ldflags=-lpthread]] != "" } { + gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail." + } + + # Thread stuff is _slow_; prepare for long waits. + # + set oldtimeout $timeout + set timeout [expr "$timeout + 600"] + + # Further, this test has some "null" lines designed + # to consume output from gdb that was too late to be + # matched (sequence is "gdb_test" sends; timeout and + # on to next send; result finally comes in; mismatch). + # + # The null command is 'gdb_test "p \$pc" ".*" ""' + # + # NOTE: to pass a literal "$", "/" or "*" (etc.) to gdb_test, + # remember that the pattern will be escaped once and + # $-evaluated twice: + # + # "\\\*" matches "\*" + # "\$" matches "$" + # + proc fix_timeout {} { + gdb_test "p \$pc" ".*" "" + } + + #========================= + # + # Simple sanity test first. + # + gdb_exit + gdb_start + gdb_reinitialize_dir $srcdir/$subdir + gdb_load ${binfile} + + gdb_test "tb 122" ".*Breakpoint.*" "tbreak at line 122" + gdb_test "r" ".*122.*" "run to line 122" + gdb_test "thr 99" ".*Thread ID 99 not known.*" "Check too-big thread number" + gdb_test "tb 145 thr 3" ".*Breakpoint.*" "set thread-specific bp 145" + gdb_test "tb 146 thr 4" ".*Breakpoint.*" "set thread-specific bp 146" + gdb_test "c" ".*Switched to thread.*14\[56\].*" "auto switch" + gdb_test "c" ".*Switched to thread.*14\[56\].*" "auto switch 2" + gdb_test "c" ".*Program exited normally.*" "continue" + + #========================= + # + # Test that you can't do a thread select after a program runs. + # + gdb_test "thread" ".*No stack.*" "No live thread after run" + gdb_test "thr 2" ".*No stack.*" "Can't set thread after run" + + #========================= + # + # Test thread command changes, look for frame level reset bug. + # + gdb_exit + gdb_start + gdb_reinitialize_dir $srcdir/$subdir + gdb_load ${binfile} + gdb_test "b 122" ".*" "break at line 122" + gdb_test "r" ".*122.*" "run to line 122" + + # Prep for frame level test--go up/info thread/check frame + # + gdb_test "up" ".*quick_sort.*" "up" + gdb_test "up" ".*main.*" "up" + + send_gdb "i th\n" + gdb_expect { + -re ".*7 thread.* in .* from .* in .* from .* 6 thread.*$gdb_prompt $" { + fail "old thread command, says things twice" + } + -re ".*7 system thread.*6 system th.*5 sys.*4.*3.*2.*1.*work_init.*$gdb_prompt $" { + pass "info threads" + } + -re ".*$gdb_prompt $" { fail "no info thread command" } + timeout { fail "timeout" } + } + + # We should have been restored two frames up--check. + # + send_gdb "up\n" + gdb_expect { + -re ".*Initial frame selected.*$gdb_prompt $" { + pass "Frame correctly reset after 'info threads'" + } + -re ".*quick_sort.*$gdb_prompt $" { + fail "Old gdb bug; should be fixed someday" + } + -re ".*$gdb_prompt $" { + fail "real bug--FIX!" + } + timeout { fail "timeout" } + } + + # Do it again, only just go to a middle frame, and use another thread. + # + gdb_test "thr 5" ".*" "switching to thread 5" + gdb_test "bt" ".*0.*__ksleep.*.*1.*libpthread.*.*2.*pthread_cond_wait.*.*3.*worker.*144.*.*4.*__pthread_create_system.*" "backtrace in thread 5" + send_gdb "up\n" + gdb_expect { + -re ".*1.*_lwp_cond_timedwait.*$gdb_prompt $" { pass "up 1 in thread 5 (1)" } + -re ".*1.*in .stub.*libpthread.*$gdb_prompt $" { pass "up 1 in thread 5 (2)" } + timeout { fail "(timeout) up 1 in thread 5" } + } + gdb_test "up" ".*2.*pthread_cond_wait.*" "up 2 in thread 5" + gdb_test "up" ".*3.*worker.*" "up 3 in thread 5" + gdb_test "i th" ".*7.*6.*work_init.*" "getting ids of the current threads" + gdb_test "f" ".*3.*worker.*" "Frame restored" + gdb_test "p wp->max_pile" ".*= 128.*" "can see vars in frame" + + # Thread command changes + # + gdb_test "thr" ".*Current thread is 5.*" "threads-no-num" + gdb_test "thr 6" ".*Switching to thread 6.*" "new switch" + gdb_test "thr" ".*Current thread is 6.*" "check switch" + gdb_test "thr 6" ".*Current thread is already 6.*" "dup, no switch" + gdb_test "thr app all p x" ".*No symbol.*" "thread app all" + gdb_test "thr" ".*Current thread is 6.*" "restore current thread" + + #========================= + # + # Test new stepping + # + + proc get_hit { } { + global hit2 + global hit3 + global hit4 + global hit5 + global hit6 + global hit7 + global gdb_prompt + + send_gdb "cont\n" + gdb_expect { + -re ".*Breakpoint.*145.*$gdb_prompt $" { + send_gdb "thr\n" + gdb_expect { + -re ".*is 7.*$gdb_prompt $" { + set hit7 [expr "$hit7 + 1"] + } + -re ".*is 6.*$gdb_prompt $" { + set hit6 [expr "$hit6 + 1"] + } + -re ".*is 5.*$gdb_prompt $" { + set hit5 [expr "$hit5 + 1"] + } + -re ".*is 4.*$gdb_prompt $" { + set hit4 [expr "$hit4 + 1"] + } + -re ".*is 3.*$gdb_prompt $" { + set hit3 [expr "$hit3 + 1"] + } + -re ".*is 2.*$gdb_prompt $" { + set hit2 [expr "$hit2 + 1"] + } + -re ".*$gdb_prompt $" { + fail "can't see which thread" + } + timeout { fail "timeout" } + } + } + -re ".*$gdb_prompt $" { + fail "thread command" + } + timeout { fail "timeout" } + } + } + + gdb_exit + gdb_start + gdb_reinitialize_dir $srcdir/$subdir + gdb_load ${binfile} + gdb_test "break 122" ".*" "break at line 122" + gdb_test "run" ".*122.*" "run to line 122" + + # Make sure we hit a bp on every thread. + # + # Try one, via thread-specific bps + # + gdb_test "break 145 thr 2" ".*" "set thread-specific bp thr 2" + gdb_test "break 145 thr 3" ".*" "set thread-specific bp thr 3" + gdb_test "break 145 thr 4" ".*" "set thread-specific bp thr 4" + gdb_test "break 145 thr 5" ".*" "set thread-specific bp thr 5" + gdb_test "break 145 thr 6" ".*" "set thread-specific bp thr 6" + gdb_test "break 145 thr 7" ".*" "set thread-specific bp thr 7" + + set hit2 0 + set hit3 0 + set hit4 0 + set hit5 0 + set hit6 0 + set hit7 0 + + get_hit + get_hit + get_hit + get_hit + get_hit + get_hit + + # Sometimes we hit one twice and don't hit another. + set total_hits [expr $hit2 + $hit3 + $hit4 + $hit5 + $hit6 + $hit7 ] + if $total_hits==6 { + pass "thread-specific bps 1" + } else { + fail "thread-specific bps 1" + } + + #==================== + # + # Now use generic bps + # + gdb_exit + gdb_start + gdb_reinitialize_dir $srcdir/$subdir + gdb_load ${binfile} + gdb_test "b 122" ".*" "break at line 122" + gdb_test "r" ".*122.*" "run to line 122" + + # Make sure we hit a bp on every thread. + # + # Try two, via non-thread-specific bp + # + gdb_test "b 145" ".*" "b 145" + + set hit2 0 + set hit3 0 + set hit4 0 + set hit5 0 + set hit6 0 + set hit7 0 + + get_hit + get_hit + get_hit + get_hit + get_hit + get_hit + + # Sometimes we hit one twice and don't hit another. + set hit_totals [expr "$hit2 + $hit3 + $hit4 + $hit5 + $hit6 + $hit7"] + if { [expr "$hit_totals == 6"] } { + pass "thread-specific bps 2" + } else { + fail "thread-specific bps 2" + } + + #==================== + # + # Complicated (original) test next. + # + gdb_exit + gdb_start + gdb_reinitialize_dir $srcdir/$subdir + gdb_load ${binfile} + + if ![runto_main] then { + fail "Can't run to main" + return 0 + } + + # OK, we're at "main", there should be one thread. + # + gdb_test "info thread" ".*\\\* 1 system thread .*main.*" "initial thread" + + # Try to see the threads being created: set a breakpoint + # after the creation and go around the loop a few times. + # + gdb_test "break 109" "Breakpoint.*109.*" "set bpt" + + gdb_test "c" ".*New thread.*Breakpoint.*109.*" "first continue" + fix_timeout + + # Make sure we don't wait (waiting is for attach test) + # + gdb_test "set wait_here = 0" ".*" "make sure we don't wait" + + send_gdb "info thr\n" + gdb_expect { + -re ".*2 system th.*1 sy.*109.*$gdb_prompt $" { pass "saw thread create" } + -re ".*1 system thread.*87.*$gdb_prompt $" { fail "didn't see thread create" } + -re ".*$gdb_prompt $" { fail "no info thread command" } + timeout { fail "timeout" } + } + + gdb_test "c" ".*New thread.*Breakpoint.*109.*" "continue" + fix_timeout + + send_gdb "info thr\n" + gdb_expect { + -re ".*3 system thread.*2 sys.*\\\* 1 system thread.*109.*$gdb_prompt $" { + pass "saw thread create" } + -re ".*2 system thread.*1 sys.*109.*$gdb_prompt $" { + fail "didn't see thread create" + } + -re ".*1 system thread.*109.*$gdb_prompt $" { + fail "didn't see thread create" + } + -re ".*$gdb_prompt $" { + fail "no info thread command" + } + timeout { fail "timeout" } + } + + fix_timeout + gdb_test "clear" ".*Deleted breakpoint.*" "clear" + + # Now go on to the end of thread creation. + # + gdb_test "b 122" ".*" "set bpt 122" + gdb_test "c" ".*New thread.*New thread.*New thread.*122.*" "continue" + gdb_test "p \$pc" ".*" "print pc" + gdb_test "clear" ".*Deleted breakpoint.*" "clear" + + send_gdb "info thr\n" + gdb_expect { + -re ".*7 system thread.*6 sys.*5.*1 system thread.*122.*$gdb_prompt $" + { pass "saw thread creates" } + -re ".*$gdb_prompt $" + { fail "no info thread command" } + timeout { fail "timeout" } + } + + # Try a thread-specific breakpoint; we expect the other threads to + # be waiting at this point. + # + gdb_test "thr 3" ".*Switching to thread.*ksleep.*" "thread switch" + gdb_test "i th" ".*\\\* 3 system thread.*" "show new current thread" + + send_gdb "up\n" + gdb_expect { + -re ".*lwp_cond_timedwait.*$gdb_prompt $" { pass "up to _lwp_cond_timedwait (1)"} + -re ".*stub.*$gdb_prompt $" { pass "up to _lwp_cond_timedwait (1)"} + timeout { fail "(timeout) up to _lwp_cond_timedwait" } + } + gdb_test "up" ".*pthread_cond_wait.*" "up to __pthread_cond_wait" + gdb_test "up" ".*worker.*144.*" "up to worker" + + gdb_test "b 145 th 3" ".*Breakpoint.*145.*" "set thread-specific bp" + gdb_test "i b" ".*breakpoint.*breakpoint.*145 thread 3.*" "show thread-specific bp" + + gdb_test "c" ".*Breakpoint.*145.*145.*" "hit thread-specific bp" + gdb_test "p \$pc" ".*" "print pc" + + # Test thread apply command on thread specific data. + # + gdb_test "thre app all p \$pc" ".*Thread 7.*Thread 6.*Thread 5.*Thread 4.*Thread 3.*Thread 2.*Thread 1.*" "thread apply all" + gdb_test "thr ap 1 3 5 p \$pc" ".*Thread 1.*Thread 3.*Thread 5.*" "thr app 1 3 5" + + # Switch again, and test that others continue on a "next" + # This test _could_ fail due to timing issues, but that's + # unlikely. + # + gdb_test "thr 7" ".*Switching to thread.*" "switch to thread 7" + + # Make sure that "up" stops at __pthread_exit, or + # __pthread_create, the pseudo-roots, and that we + # only see that pseudo-root once. + # + send_gdb "bt\n" + gdb_expect { + -re ".*Error accessing memory address.*$gdb_prompt $" { fail "bt" } + -re ".*pthread_create.*pthread_create.*$gdb_prompt $" { fail "bt" } + -re ".*worker.*pthread_create.*$gdb_prompt $" { pass "bt" } + -re ".*pthread_exit.*$gdb_prompt $" { pass "bt" } + -re ".*$gdb_prompt $" { fail "bt" } + timeout { fail "timeout on bt" } + } + + gdb_test "up" ".*" "up" + gdb_test "up" ".*" "up" + send_gdb "up\n" + # The ".*__pthread_cond_wait" pattern happens if we were stopped in + # __ksleep + gdb_expect { + -re ".*144.*$gdb_prompt $" { pass "Up 3" } + -re ".*pthread_cond_wait.*$gdb_prompt $" { pass "Up 3" } + -re ".*$gdb_prompt $" { fail "Up 3" } + timeout { fail "timeout on Up 3" } + } + + gdb_test "up" ".*pthread_.*" "Up 4" + send_gdb "up\n" + gdb_expect { + -re ".*Initial frame selected; you cannot go up.*$gdb_prompt $" { pass "catch end of thread stack" } + -re ".* in __pthread_create_system.*$gdb_prompt $" { + gdb_test "up" ".*Initial frame selected; you cannot go up.*" "catch end of thread stack" + } + -re ".*$gdb_prompt $" { fail "catch end of thread stack" } + timeout { fail "(timeout) catch end of thread stack" } + } + + #===================== + # + # Things get iffy here; when we step, sometimes the step + # completes, sometimes it doesn't. When it doesn't, we + # hit a bp somewhere else and the step never completes + # (wait_for_inferior just evaporates it). + # + # I think the right answer is that any failures here + # should stick around to trigger later fixing. + # + # Here's the plan: + # + # Bps at 148 (5) and 154 (6) on thread 7 (two bps so we + # see the difference between going around the loop and + # reporting the same bp hit twice). + # + # Bp at 144 on thread 3. + # + # Step out of a library routine. + # + # Either the step will finish or a bp will hit. Try to + # handle all the cases. + # + gdb_test "b 148 thr 7" ".*Breakpoint.*148.*" "set bpt 1" + gdb_test "b 154 thr 7" ".*Breakpoint.*154.*" "set bpt 2" + + set hit_154_bp 0 + set hit_148_bp 0 + set hit_145_bp 0 + set step_completed 0 + + # Expect zero hits + # + gdb_test "i b" ".*" "info break" + + # DTS 10080CLLbs - thread switch not reported + setup_xfail hppa*-*-*11* 10080CLLbs + send_gdb "n\n" + gdb_expect { + -re ".*Single stepping.*_lwp_cond_timedwait.*$gdb_prompt $" { + send_gdb "thr\n" + gdb_expect { + -re ".*is 7.*$gdb_prompt $" { + set step_completed 1 + pass "completed step in library code" + } + -re ".*$gdb_prompt $" { + fail "completed step in library code, but in wrong thread" + } + timeout { fail "timeout" } + } + } + -re ".*Single stepping.*Switched to thread 3.*Breakpoint.*$gdb_prompt $" { + pass "step cancelled; hit bp due to thread parallelism" + set hit_145_bp 1 + } + -re ".*Single stepping.*Switched to thread 7.*Breakpoint.*148.*$gdb_prompt $" { + pass "step cancelled; hit bp due to thread parallelism" + set hit_148_bp 1 + } + -re ".*Single stepping.*Switched to thread 7.*Breakpoint.*154.*$gdb_prompt $" { + pass "step cancelled; hit bp due to thread parallelism" + set hit_154_bp 1 + } + -re ".*$gdb_prompt $" { + send_gdb "thr\n" + gdb_expect { + -re ".*is 7.*$gdb_prompt $" { + fail "No event?" + } + -re ".*$gdb_prompt $" { + fail "No event" + } + timeout { fail "timeout" } + } + } + timeout { fail "timeout" } + } + + # Sometimes used to get SIGTRAP here; that should be fixed + # + + # Expect appropriate hits of bpt; too much work to parse + # result and check... + # + gdb_test "i b" ".*" "info break" + + send_gdb "c\n" + gdb_expect { + -re ".*SIGTRAP.*$gdb_prompt $" { + fail "got SIGTRAP" + } + -re ".*Switched to thread 7.*Breakpoint.*154.*$gdb_prompt $" { + if { $hit_154_bp == 1 } { + fail "re-hit old bp" + } else { + pass "continue; hit parallel event after continue" + } + set hit_154_bp 1 + } + -re ".*Switched to thread 7.*Breakpoint.*148.*$gdb_prompt $" { + if { $hit_148_bp == 1 } { + fail "re-hit old bp" + } else { + pass "continue; hit parallel event after continue" + } + set hit_148_bp 1 + } + -re ".*Breakpoint.*154.*$gdb_prompt $" { + if { $hit_154_bp == 1 } { + fail "re-hit old bp" + } else { + send_gdb "thr\n" + gdb_expect { + -re ".*is 7.*$gdb_prompt $" { + pass "continue; hit parallel event after continue" + } + -re ".*$gdb_prompt $" { + fail "hit bp in wrong thread" + } + timeout { fail "timeout" } + } + } + set hit_154_bp 1 + } + -re ".*Breakpoint.*148.*$gdb_prompt $" { + if { $hit_148_bp == 1 } { + fail "re-hit old bp" + } else { + send_gdb "thr\n" + gdb_expect { + -re ".*is 7.*$gdb_prompt $" { + pass "continue; hit parallel event after continue" + } + -re ".*$gdb_prompt $" { + fail "hit bp in wrong thread" + } + timeout { fail "timeout" } + } + } + set hit_148_bp 1 + } + -re ".*Breakpoint.*145.*$gdb_prompt $" { + if { $hit_145_bp == 1 } { + fail "re-hit old bp" + } else { + send_gdb "thr\n" + gdb_expect { + -re ".*is 3.*$gdb_prompt $" { + pass "continue; hit parallel event after continue" + } + -re ".*$gdb_prompt $" { + fail "hit bp in wrong thread" + } + timeout { fail "timeout" } + } + } + set hit_145_bp 1 + } + -re ".*_lwp_cond_timedwait.*$gdb_prompt $" { + pass "continue; hit step completion after continue" + } + -re ".*Program exited normally.*" { + fail "Program ended? HOW?" + } + -re ".*$gdb_prompt $" { + fail "Unexpected event" + } + timeout { fail "timeout" } + } + + # There are a number of places we _could_ be now; + # this is the price of really running in parallel. + # + send_gdb "n\n" + gdb_expect { + -re ".*Switched to thread 7.*pthread_cond_wait.*$gdb_prompt $" { + if { $step_completed } { + fail "step already completed" + } else { + pass "finish step" + } + } + -re ".*pthread_cond_wait.*$gdb_prompt $" { + # + # Unlikely, but we might finish the range step from inside + # ksleep, before anything else. + # + if { $step_completed } { + fail "step already completed" + } else { + send_gdb "thr\n" + gdb_expect { + -re ".*is 7.*$gdb_prompt $" { + pass "finish step" + } + -re ".*$gdb_prompt $" { + fail "step in wrong thread" + } + timeout { fail "timeout" } + } + } + } + -re ".*Switched to thread.*Breakpoint.*145.*$gdb_prompt $" { + pass "auto-switch thread" + } + -re ".*Breakpoint.*145.*$gdb_prompt $" { + pass "auto-switch not needed, ok" + } + -re "146.*wp->n_working.*" { + pass "auto-switch not needed, ok" + } + -re ".*140.*while.*n_pile.*$gdb_prompt $" { + # + # This is just going around the loop from the 154 bp. + # + send_gdb "thr\n" + gdb_expect { + -re ".*is 7.*$gdb_prompt $" { + pass "finish step" + } + -re ".*$gdb_prompt $" { + fail "step in wrong thread" + } + timeout { fail "timeout" } + } + } + -re ".*149.*ptr = wp.*pile.*$gdb_prompt $" { + # + # This is just going around the loop from the 148 bp. + # + if { $hit_154_bp } { + send_gdb "thr\n" + gdb_expect { + -re ".*is 7.*$gdb_prompt $" { + pass "finish step" + } + -re ".*$gdb_prompt $" { + fail "step in wrong thread" + } + timeout { fail "timeout" } + } + } else { + pass "step from 149 but didn't hit it first" + } + } + -re ".*Breakpoint 5.*154.*$gdb_prompt $" { + gdb_test "i b" ".*" + if { $hit_154_bp } { + fail "hit bp again?" + } else { + pass "hit bp" + } + } + -re ".*Breakpoint 5.*148.*$gdb_prompt $" { + gdb_test "i b" ".*" + if { $hit_148_bp } { + fail "hit bp again?" + } else { + pass "hit bp" + } + } + -re ".*$gdb_prompt $" { + fail "no step finished" + } + timeout { fail "timeout on 'next'" } + } + + # Let's get into some kind of known state again. + # + gdb_test "thr 7" ".*" "thread 7" + gdb_test "info thread" ".*" "info thread" + #gdb_test "i b" ".*" + + # Leave breakpoint "154 thr 7" as only live bp. + # + gdb_test "d 1" ".*" "del main bp" + gdb_test "d 4" ".*" "thread-specific bpt delete" + gdb_test "d 5" ".*" "other bp delete" + send_gdb "i b\n" + gdb_expect { + -re ".*breakpoint.*breakpoint.*$gdb_prompt $" { + fail "more than one bp left" + } + -re ".*breakpoint.*154.*thread.*7.*$gdb_prompt $" { + pass "Only one bp left" + } + -re ".*$gdb_prompt $" { + fail "Wrong or no bp left" + } + timeout { fail "timeout on info b" } + } + + send_gdb "c\n" + gdb_expect { + -re ".*SIGTRAP.*Switched to thread.*$gdb_prompt $" { + fail "SIGTRAP error; lost thread-specific bpt" + } + -re ".*SIGTRAP.*Switched to thread.*154.*$gdb_prompt $" { + fail "SIGTRAP, but hit right thread-specific bpt" + } + -re ".*Switched to thread.*Breakpoint.*154.*$gdb_prompt $" { + pass "auto-switch back" + } + -re ".*Breakpoint.*154.*$gdb_prompt $" { + pass "step to bp" + } + -re ".*$gdb_prompt $" { + fail "auto-switch back" + } + -re ".*Program exited normally.*$gdb_prompt $" { + fail "step lost" + } + timeout { + fail "timeout" + } + } + fix_timeout + + gdb_test "cle" ".*Deleted breakpoint.*" "delete last breakpoint" + + # Sometimes get SIGTRAP here. Continue sometimes gets another... + # + # DTS 10082CLLbs - Sometimes gdb gets a SIGTRAP on a deleted breakpoint + setup_xfail hppa*-*-*11* 10082CLLbs + send_gdb "c\n" + gdb_expect { + -re ".*SIGTRAP.*154.*154.*$gdb_prompt $" { + fail "SIGTRAP on deleted bp 154 " + gdb_test "n" ".*" + gdb_test "set confirm off" ".*" + gdb_test "delete" ".*" + gdb_test "c" ".*" + gdb_test "n" ".*" + gdb_test "c" ".*" + gdb_test "n" ".*" + gdb_test "c" ".*" + gdb_test "n" ".*" + gdb_test "c" ".*" + gdb_test "n" ".*" + gdb_test "c" ".*" + gdb_test "n" ".*" + gdb_test "c" ".*" + gdb_test "n" ".*" + send_gdb "c\n" + gdb_expect { + -re ".*$gdb_prompt $" { pass "fixup"} + timeout { fail "fixup" } + } + } + -re ".*SIGTRAP.*144.*145.*$gdb_prompt $" { + fail "SIGTRAP on deleted bp 145 " + send_gdb "c\n" + gdb_expect { + -re ".*$gdb_prompt $" { pass "fixup"} + timeout { fail "fixup" } + } + } + -re ".*SIGTRAP.*148.*148.*$gdb_prompt $" { + fail "SIGTRAP on deleted bp 148 " + send_gdb "c\n" + gdb_expect { + -re ".*$gdb_prompt $" { pass "fixup"} + timeout { fail "fixup" } + } + } + -re ".*SIGTRAP.*$gdb_prompt $" { + fail "unknown SIGTRAP" + send_gdb "c\n" + gdb_expect { + -re ".*$gdb_prompt $" { pass "fixup"} + timeout { fail "fixup" } + } + } + -re ".*Program exited.*$gdb_prompt $" { + pass "run to end" + } + -re ".*$gdb_prompt $" { + fail "run to end" + send_gdb "c\n" + gdb_expect { + -re ".*$gdb_prompt $" { pass "fixup"} + timeout { fail "fixup" } + } + } + timeout { fail "timeout" } + } + + gdb_test "p \$pc" ".*No registers.*" "program done" + + # Done! + # + gdb_exit + + set timeout $oldtimeout + + return 0 + diff -r -c -N ../gdb-19990719/gdb/testsuite/gdb.threads/start-stop.c gdb/testsuite/gdb.threads/start-stop.c *** ../gdb-19990719/gdb/testsuite/gdb.threads/start-stop.c Wed Dec 31 16:00:00 1969 --- gdb/testsuite/gdb.threads/start-stop.c Thu Jul 22 17:50:39 1999 *************** *** 0 **** --- 1,161 ---- + /* BeginSourceFile start_stop.c + + This file creates and deletes threads, so that wdb + can be tested on thread delete. + + To compile: + + cc -Ae +DA1.0 -g -o start_stop -lpthread start_stop.c + + To run: + + start_stop --normal run + start_stop 1 --waits in each thread to keep it alive. + */ + + #include + #include + #include + #include + #include + + #define TRUE 1 + #define FALSE 0 + #define OUTER_LOOP_COUNT 3 + #define N_THREADS 3 + #define MAX_LOCAL_VAL 40 + + /* Uncomment to turn on debugging output */ + /* #define START_DEBUG */ + + /* True if waiting for attach. + */ + int wait_here; + + /* Thing to check for debugging purposes. + */ + int a_global = 0; + + /* Thread-local storage. + */ + __thread int a_thread_local; + + /* Check the results of thread-local storage. + */ + int thread_local_val[ N_THREADS ]; + int val_debugger_saw[ N_THREADS ]; + + /* Routine for each thread to run, does nothing. + */ + void *spin( vp ) + void * vp; + { + int me = (int) vp; + int i; + + #ifdef START_DEBUG + printf( "== In thread %d\n", me ); + #endif + + a_global++; + + a_thread_local = 0; + for( i = 0; i < a_global; i++ ) { + a_thread_local += i; + } + + thread_local_val[ me ] = a_thread_local; /* Line 67 */ + + printf( "== Thread %d, a_thread_local is %d\n", + (int) vp, a_thread_local ); + + if( wait_here ) { + /* Extend life of thread to extend life of thread-local var. + * This makes life easier for human debugging (though you'd + * probably want to make the delay longer). + */ + /*sleep( 5 );*/ + } + } + + void + do_pass( pass ) + int pass; + { + int i; + pthread_t t[ N_THREADS ]; + int err; + + for( i = 0; i < N_THREADS; i++) { + thread_local_val[i] = 0; + val_debugger_saw[i] = 0; + } + + /* Start N_THREADS threads, then join them so + * that they are terminated. + */ + for( i = 0; i < N_THREADS; i++ ) { + err = pthread_create( &t[i], NULL, spin, (void *)i ); + if( err != 0 ) { + printf( "== Start/stop, error in thread %d create\n", i ); + } + } + + for( i = 0; i < N_THREADS; i++ ) { + err = pthread_join(t[i], NULL ); /* Line 105 */ + if( err != 0 ) { /* Line 106 */ + printf( "== Start/stop, error in thread %d join\n", i ); + } + } + + i = 10; /* Line 111. Null line for setting bpts on. */ + + /*#ifdef START_DEBUG*/ + for( i = 0; i < N_THREADS; i++) { + printf( " Local in thread %d was %d, debugger saw %d\n", + i, thread_local_val[i], val_debugger_saw[i] ); + } + printf( "== Pass %d done\n", pass ); + /*#endif*/ + + } + + void + do_it() + { + /* We want to start some threads and then + * end them, and then do it again and again + */ + int i; + int dummy; + + for( i = 0; i < OUTER_LOOP_COUNT; i++ ) { + do_pass( i ); + dummy = i; /* Line 134, null line for setting bps on */ + } + } + + main( argc, argv ) + int argc; + char **argv; + { + wait_here = FALSE; + if((argc > 1) && (0 != argv )) { + if( 1 == atoi( argv[1] ) ) + wait_here = TRUE; + } + + #ifdef START_DEBUG + printf( "== Test starting\n" ); + #endif + + do_it(); + + #ifdef START_DEBUG + printf( "== Test done\n" ); + #endif + + return(0); + } + + /* EndSourceFile */ diff -r -c -N ../gdb-19990719/gdb/testsuite/gdb.threads/start-stop.exp gdb/testsuite/gdb.threads/start-stop.exp *** ../gdb-19990719/gdb/testsuite/gdb.threads/start-stop.exp Wed Dec 31 16:00:00 1969 --- gdb/testsuite/gdb.threads/start-stop.exp Thu Jul 22 17:50:39 1999 *************** *** 0 **** --- 1,373 ---- + # start-stop.exp -- Expect script to test a threaded pgm which has terminating threads + # Copyright (C) 1992 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@prep.ai.mit.edu + + # Comment out for now, since this test is (sometimes?) hanging on 11.0 + # + # return 0 + + if $tracelevel then { + strace $tracelevel + } + + if { ![istarget "hppa*-*-hpux11.*"] } { + verbose "HPUX thread test ignored for non-hppa or pre-HP/UX-10.30 targets." + return 0 + } + + set testfile start-stop + set srcfile ${srcdir}/${subdir}/${testfile}.c + set binfile ${objdir}/${subdir}/${testfile} + + if [get_compiler_info ${binfile}] { + return -1 + } + + # To build the executable we need to link against the thread library. + # + if { $hp_cc_compiler } { + set additional_flags "additional_flags=-Ae" + } else { + set additional_flags "" + } + + if { [gdb_compile "${srcdir}/${subdir}/${testfile}.c" "${binfile}" executable [list debug $additional_flags ldflags=-lpthread]] != "" } { + gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail." + } + + # Thread stuff is _slow_; prepare for long waits. + # + # Further, this test has some "null" lines designed + # to consume output from gdb that was too late to be + # matched (sequence is "gdb_test" sends; timeout and + # on to next send; result finally comes in; mismatch). + # + # The null command is 'gdb_test "p \$pc" ".*" ""' + # NOTE: this command undoes any up/down stuff! + # + proc pre_timeout {} { + global timeout + + set timeout [expr "$timeout + 100"] + } + + proc post_timeout {} { + global timeout + global oldtimeout + + set timeout $oldtimeout + gdb_test "p \$pc" ".*" "" + } + + gdb_exit + gdb_start + gdb_reinitialize_dir $srcdir/$subdir + + gdb_load ${binfile} + if ![runto_main] then { + fail "Can't run to main" + return 0 + } + + set oldtimeout $timeout + #set timeout [expr "$timeout + 200"] + set oldverbose $verbose + #set verbose 40 + + gdb_test "b do_pass" ".*" "set do_pass bp" + gdb_test "c" ".*Breakpoint.*do_pass.*" "run to do_pass" + + # Should be only one thread. + # + pre_timeout + send_gdb "info thread\n" + gdb_expect { + -re ".*2 process.*$gdb_prompt $" { fail "Old code for 'thread.c'" } + -re ".*2 system thread.*1 sys.*$gdb_prompt $" { fail "Too many threads" } + -re ".*1 system thread.*$gdb_prompt $" { pass "Just one thread" } + -re ".*$gdb_prompt $" { fail "no thread info" } + timeout { fail "timeout on info thread 1" } + } + post_timeout + + # Run to a point after the thread creates (105 is just + # before the first join). + # + # The "== Thread" stuff is output from the computing threads. + # + gdb_test "b 105" ".*Breakpoint.*" "set 105 bp" + + pre_timeout + send_gdb "c\n" + gdb_expect { + -re ".*== Thread.*== Thread.*== Thread.*105.*$gdb_prompt $" { + set threads_exist 0 + pass "new threads created and ended - 1st case" + } + -re ".*== Thread.*== Thread.*105.*$gdb_prompt $" { + set threads_exist 1 + pass "new threads created and ended - 2nd case" + } + -re ".*== Thread.*.*105.*$gdb_prompt $" { + set threads_exist 2 + pass "new threads created and ended - 3rd case" + } + -re ".*New thread.*New th.*New th.*105.*$gdb_prompt $" { + set threads_exist 3 + pass "new threads created" + } + -re ".*Breakpoint.*105.*$gdb_prompt $" { + set threads_exist 0 + fail "didn't see any threads" + } + -re ".*$gdb_prompt $" { + set threads_exist 0 + fail "didn't even hit bp" + } + timeout { + set threads_exist -1 + fail "timeout on continue" + } + } + + gdb_test "cle" ".*Deleted.*" "del bp at 105" + + # Check that threads are being consumed at the join call. + # We expect to join three times. If we ever see the bp at + # 111, we've gone too far. + # + gdb_test "b 106" ".*Breakpoint.*106.*" "set bp at 106" + gdb_test "b 111" ".*Breakpoint.*111.*" "set bp at 111" + + # This one is sure: we're already in the loop. + # + #gdb_test "c" ".*Breakpoint.*106.*" "hit bp at 106 1st time, 2 left" + send_gdb "c\n" + gdb_expect { + -re ".*== Thread.*== Thread.*== Thread.*Breakpoint.*106.*$gdb_prompt $" { + set threads_exist [expr "$threads_exist - 3"] + pass "hit bp at 106 1st time, 2 left - 1st case" + } + -re ".*== Thread.*== Thread.*Breakpoint.*106.*$gdb_prompt $" { + set threads_exist [expr "$threads_exist - 2"] + pass "hit bp at 106 1st time, 2 left - 2nd case" + } + -re ".*== Thread.*.*Breakpoint.*106.*$gdb_prompt $" { + set threads_exist [expr "$threads_exist - 1"] + pass "hit bp at 106 1st time, 2 left - 3rd case" + } + -re ".*Breakpoint.*106.*$gdb_prompt $" { + pass "hit bp at 106 1st time, 2 left" + } + -re ".*$gdb_prompt $" { fail "hit bp at 106 1st time, 2 left" } + timeout { fail "timeout on hit bp at 106 1st time, 2 left" } + } + + # Look at the threads again. We expect that some of + # the threads may have already finished execution. + # + send_gdb "info thread\n" + gdb_expect { + -re ".*system.*system.*system.*system.*thread.*$gdb_prompt $" { set seen_threads 3 } + -re ".*system.*system.*system.*thread.*$gdb_prompt $" { set seen_threads 2 } + -re ".*system.*system.*thread.*$gdb_prompt $" { set seen_threads 1 } + -re ".*system.*thread.*$gdb_prompt $" { set seen_threads 0 } + -re ".*$gdb_prompt $" { set seen_threads 0 } + timeout { + set seen_threads -10 + fail "timeout on second info thread" + } + } + post_timeout + + if { $seen_threads == $threads_exist } { + pass "saw all threads that existed" + } else { + if { $seen_threads > $threads_exist } { + fail "may have seen threads ($threads_exist vs $seen_threads) that didn't finish exiting yet" + } else { + fail "didn't see live threads ($threads_exist vs $seen_threads)" + } + } + + # Did we go around the loop again? + # + send_gdb "c\n" + gdb_expect { + -re ".*Breakpoint.*111.*" { + fail "didn't join right 1" + gdb_test "cle" ".*" + } + -re ".*Breakpoint.*106.*" { + pass "hit bp at 106 2nd time, 1 left" + send_gdb "c\n" + gdb_expect { + -re ".*Breakpoint.*111.*" { + fail "didn't join right 2" + gdb_test "cle" ".*" + } + -re ".*Breakpoint.*106.*" { + pass "hit bp at 106 3rd time, 0 left" + gdb_test "cle" ".*" + gdb_test "c" ".*Breakpoint.*111.*" + gdb_test "cle" ".*" + } + timeout { fail "timeout going around the loop"} + } + } + timeout { fail "timeout getting to 106"} + } + + # Should only be one thread now. + # + pre_timeout + send_gdb "info thread\n" + gdb_expect { + -re ".*2 system thread.*1 sys.*$gdb_prompt $" { fail "Too many threads" } + -re ".*1 system th.*$gdb_prompt $" { pass "Just one thread" } + -re ".*$gdb_prompt $" { pass "One thread shown as no threads, ok" } + timeout { fail "timeout third info thread" } + } + post_timeout + + #============================= Begin pass 2 =========== + # + # Ok, go around again + # + gdb_test "c" ".*Breakpoint.*do_pass.*" "hit do_pass bp again 2" + gdb_test "b 105" ".*Breakpoint.*" "set 105 bp 2" + + pre_timeout + send_gdb "c\n" + gdb_expect { + -re ".*== Thread.*== Thread.*== Thread.*$gdb_prompt $" { + set threads_exist 0 + pass "new threads created and ended 2 - 1st case" + } + -re ".*== Thread.*== Thread.*== Thread.*" { + pass "new threads created and ended 2 - variant on 1st case" + } + -re ".*== Thread.*== Thread.*$gdb_prompt $" { + set threads_exist 1 + pass "new threads created and ended 2 - 2nd case" + } + -re ".*== Thread.*$gdb_prompt $" { + set threads_exist 2 + pass "new threads created and ended 2 - 3rd case" + } + -re ".*New system thread.*New sys.*New.*105.*$gdb_prompt $" { + set threads_exist 3 + pass "new threads created 2" + } + timeout { + set threads_exist -1 + fail "timeout on continue 2" + } + } + + # Look at the threads again. We expect that some of + # the threads may have already finished execution. + # + send_gdb "info thread\n" + gdb_expect { + -re ".*4 .*3 .*2 .* 1.*thread.*$gdb_prompt $" { set seen_threads 3 } + -re ".*3 .*2 .* 1.*thread.*$gdb_prompt $" { set seen_threads 2 } + -re ".*2 .* 1.*thread.*$gdb_prompt $" { set seen_threads 1 } + -re ".* 1.*thread.*$gdb_prompt $" { set seen_threads 0 } + -re ".*$gdb_prompt $" { set seen_threads 0 } + timeout { + set seen_threads -10 + fail "timeout on second info thread 2" + } + } + post_timeout + + if { $seen_threads == $threads_exist } { + pass "saw all threads that existed 2" + } else { + if { $seen_threads > $threads_exist } { + fail "may have seen threads ($threads_exist vs $seen_threads) that didn't finish exiting yet 2" + } else { + fail "didn't see live threads 2 ($threads_exist vs $seen_threads)" + } + } + + gdb_test "cle" ".*Deleted.*" "del bp at 105 2" + + # Check that threads are being consumed at the join call. + # We expect to join three times. If we ever see the bp at + # 111, we've gone too far. + # + gdb_test "b 106" ".*Breakpoint.*106.*" "set bp at 106 2" + gdb_test "b 111" ".*Breakpoint.*111.*" "set bp at 111 2" + + # This one is sure: we're already in the loop. + # + gdb_test "c" ".*Breakpoint.*106.*" "hit bp at 106 1st time, 2 left 2" + + # Did we go around the loop again? + # + send_gdb "c\n" + gdb_expect { + -re ".*Breakpoint.*111.*" { + fail "didn't join right 1, pass 2" + gdb_test "cle" ".*" + } + -re ".*Breakpoint.*106.*" { + pass "hit bp at 106 2nd time, 1 left, pass 2" + send_gdb "c\n" + gdb_expect { + -re ".*Breakpoint.*111.*" { + fail "didn't join right 2, pass 2" + gdb_test "cle" ".*" + } + -re ".*Breakpoint.*106.*" { + pass "hit bp at 106 3rd time, 0 left, pass 2" + gdb_test "cle" ".*" + gdb_test "c" ".*Breakpoint.*111.*" + gdb_test "cle" ".*" + } + timeout { fail "timeout going around loop, pass 2"} + } + } + timeout { fail "timeout continue to 106, pass 2"} + } + + # Should only be one thread now. + # + pre_timeout + send_gdb "info thread\n" + gdb_expect { + -re ".*2 system thread.*1 sys.*$gdb_prompt $" { fail "Too many threads, pass 2" } + -re ".*1 system thread.*$gdb_prompt $" { pass "Just one thread, pass 2" } + -re ".*$gdb_prompt $" { pass "One thread shown as no threads, ok, pass 2" } + timeout { fail "timeout last info thread, pass 2" } + } + post_timeout + + # Done! + # + gdb_exit + + set timeout $oldtimeout + set verbose $oldverbose + + # execute_anywhere "rm -f ${binfile}" + # + return 0 diff -r -c -N ../gdb-19990719/gdb/testsuite/gdb.threads/thr-lib.c gdb/testsuite/gdb.threads/thr-lib.c *** ../gdb-19990719/gdb/testsuite/gdb.threads/thr-lib.c Wed Dec 31 16:00:00 1969 --- gdb/testsuite/gdb.threads/thr-lib.c Thu Jul 22 17:50:39 1999 *************** *** 0 **** --- 1,79 ---- + /* Thread local in a library. + */ + #include "thr-lib.h" + /* + * #define NTHREADS 4 + * #define NUM_ELEMS 12 + */ + + extern void* adder( void * ); + + pthread_mutex_t mutex; /* mutex for protecting global data total */ + + int numbers[NUM_ELEMS] = {5, 4, 3, 2, 1, 6, 7, 8, 9, 10, 12, 11}; + int total = 0; + + int debugger_saw[NTHREADS][ELEMS_PER_THREAD]; /* [4][3] */ + int the_code_saw[NTHREADS][ELEMS_PER_THREAD]; + + int get_number(i) + int i; + { + /* sleep to force context switch to another thread in non-MP system + * so that TLS symbols are used by multiple threads concurrently + * in some way. + */ + sleep(1); + return numbers[i]; + } + + main() + { + pthread_t thread[NTHREADS]; + void *status; + int i, j, ret; + + printf("== Thread: Test started\n"); + + for( i = 0; i < NTHREADS; i++ ) { + for( j = 0; j < ELEMS_PER_THREAD; j++ ) { + debugger_saw[i][j] = 0; + the_code_saw[i][j] = 0; + } + } + + ret = pthread_mutex_init(&mutex, NULL); + if (ret != 0) { + printf("== Thread: pthread_mutex_init() error: %d\n", ret); + exit(1); + } + + for (i=0; i < NTHREADS; i++) { + ret = pthread_create( &thread[i], + NULL, + adder, + (void *) i); + if (ret != 0) { + printf("== Thread: pthread_create() error: %d\n", ret); + exit(1); + } + printf("== Thread: thread %d created\n", i); + } + + for (i=0; i < NTHREADS; i++) { + pthread_join( thread[i], &status); + } + + printf("== Thread: total = %d\n", total); /* Expect "78" */ + + for( i = 0; i < NTHREADS; i++ ) { + for( j = 0; j < ELEMS_PER_THREAD; j++ ) { + printf( "== Thread: the debugger saw %d, the program saw %d\n", + debugger_saw[i][j], + the_code_saw[i][j] ); + } + } + + printf("== Thread: Test ended\n"); + exit(0); + } diff -r -c -N ../gdb-19990719/gdb/testsuite/gdb.threads/thr-lib.exp gdb/testsuite/gdb.threads/thr-lib.exp *** ../gdb-19990719/gdb/testsuite/gdb.threads/thr-lib.exp Wed Dec 31 16:00:00 1969 --- gdb/testsuite/gdb.threads/thr-lib.exp Thu Jul 22 17:50:39 1999 *************** *** 0 **** --- 1,253 ---- + # thr-lib.exp -- Expect script to test thread-local storage in lib + # Copyright (C) 1992 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@prep.ai.mit.edu + + if $tracelevel then { + strace $tracelevel + } + + if { ![istarget "hppa*-*-hpux11.*"] } { + verbose "HPUX thread test ignored for non-hppa or pre-HP/UX-10.30 targets." + return 0 + } + + set testfile thr-lib + set srcfile ${srcdir}/${subdir}/${testfile}.c + set libsrc ${srcdir}/${subdir}/${testfile}lib.c + set mainobj ${objdir}/${testfile}.o + set libobj ${objdir}/${testfile}lib.o + set libsl ${objdir}/${subdir}/${testfile}lib.sl + set binfile ${objdir}/${subdir}/${testfile} + + # To build the executable we need to do this: + # + # cc -c -Aa -g -D_HPUX_SOURCE -D_REENTRANT +DA1.0 ./gdb.hp/thr-lib.c + # cc -c -Aa -g -D_HPUX_SOURCE -D_REENTRANT +DA1.0 +z ./gdb.hp/thr-liblib.c + # ld -o thread_local_in_lib.lib.sl -b ./gdb.hp/thr-liblib.o + # ld -a archive /opt/langtools/lib/crt0.o /opt/langtools/lib/end.o \ + # thr-lib.o ./gdb.hp/thr-liblib.sl \ + # -o thr-lib -lpthread -lc + # + if { [gdb_compile "${srcfile}" "${mainobj}" object {debug}] != "" } { + gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail." + } + if { [gdb_compile "${libsrc}" "${libobj}" object {debug additional_flags=+z}] != "" } { + gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail." + } + + remote_exec build "ld -o ${libsl} -b ${libobj}" + if [istarget "hppa2.0w-*-*"] { + remote_exec build "ld -a archive /opt/langtools/lib/pa20_64/crt0.o /opt/langtools/lib/pa20_64/end.o ${mainobj} ${libsl} -lpthread -lc -o ${binfile}" + } else { + remote_exec build "ld -a archive /opt/langtools/lib/crt0.o /opt/langtools/lib/end.o ${mainobj} ${libsl} -lpthread -lc -o ${binfile}" + } + + # Thread stuff is _slow_; prepare for long waits. + # + # Further, this test has some "null" lines designed + # to consume output from gdb that was too late to be + # matched (sequence is "gdb_test" sends; timeout and + # on to next send; result finally comes in; mismatch). + # + # The null command is 'gdb_test "p \$pc" ".*" ""' + # NOTE: this command undoes any up/down stuff! + # + proc pre_timeout {} { + global timeout + + set timeout [expr "$timeout + 100"] + } + + proc post_timeout {} { + global timeout + global oldtimeout + + set timeout $oldtimeout + gdb_test "p \$pc" ".*" "" + } + + gdb_exit + gdb_start + gdb_reinitialize_dir $srcdir/$subdir + + set oldtimeout $timeout + # RM: Set timeout to a lower value so this test doesn't run forever + set timeout [expr "30"] + set oldverbose $verbose + + gdb_load ${binfile} + + # Here we go: test various things. + # + gdb_test "b adder" ".*Breakpoint.*deferred.*adder.*Breakpoint deferred until a shared library containing.*" "shared loc, needs to run" + gdb_test "b main" ".*" + gdb_test "run" ".*Breakpoint 2, main.*" + + # Set a bp to inspect the results + # + gdb_test "b 67" ".*Breakpoint 3.*" + + # get to a point where we can set the collection breakpoint. + # + gdb_test "tb adder" ".*Breakpoint 4.*line 47.*" "set bp in shared lib" + gdb_test "c" ".*Switched to.*adder.*" "run to shared lib rtn" + + # Check locations of things + # + gdb_test "i ad sum" ".*Symbol \"sum\" is a thread-local variable.*offset.*from the thread base register mpsfu_high.*" "find sum" + gdb_test "i add x" ".*Symbol \"x\" is a thread-local variable.*" "find x" + + # Set a breakpoint later on in "adder" and + # collect the thread local's value. + # + gdb_test "b 61" ".*Breakpoint 5.*61.*" "Set collection bp" + + # extra check for grins, expect to hit "adder" in thread 2 first + # but could be wrong... + # + gdb_test "info thread" ".*\\\* 2.*thread.*thread.*" "two threads" + + # Can't use "gdb_test", as it uses "$gdb_prompt $" in + # testing the result. Our new prompt is ">", with + # no trailing space, so we can't do this just by + # changing "prompt". + # + # Anyway, I couldn't get expect to see the ">" prompt, + # during the command addition, so I just punted. + # _You_ are welcome to try, if you want! + # + send_gdb "commands 5\n" + gdb_expect { + -re "(.*Type commands.*\"end\"\.\r\n\>)" { + pass "start commands" + } + -re ".*$gdb_prompt $" { + fail "start commands" + } + } + + # Assume we're in commands-input mode. (Self-debug stuff turned off) + # + send_gdb "silent\n" + #send_gdb "p id\n" + #send_gdb "p j\n" + #send_gdb "p x\[j\]\n" + send_gdb "set debugger_saw\[id\]\[j\] = x\[j\]\n" + send_gdb "continue\n" + send_gdb "end\n" + + gdb_expect { + -re ".*set.*cont.*$gdb_prompt $" { + pass "add commands" + } + -re ".*$gdb_prompt $" { + fail "add commands" + } + } + + # Check out of paranoia. + # + send_gdb "info break 5\n" + gdb_expect { + -re ".*breakpoint.*set debugger_saw.*continue.*$gdb_prompt $" { + pass "Commands added" + } + -re ".*$gdb_prompt $" { + fail "Commands not added." + } + } + + # When we hit the breakpoint for which we have commands set, + # gdb is going to dump core because there is a continue command embedded + # in the commands set and this is due to DTS 10120CLLbs. When this + # DTS is fixed, we should be able to continue with the rest of the test. + + setup_xfail "hppa*-*-*" 10120CLLbs + send_gdb " \n" + gdb_expect { + -re ".*$gdb_prompt $" { fail "About to dump core -- returning"; return } + } + + # We now expect to run through the whole application + # Since this'll run for while, set a generous timeout. + # + #RM: Keep low timeout here too + #set timeout [expr "$timeout + 30"] + send_gdb "c\n" + gdb_expect { + -re ".*Program exited normally.*$gdb_prompt $" { + fail "program runaway" + } + -re ".*Breakpoint 2.*67.*$gdb_prompt $" { + pass "get to end" + } + -re ".*$gdb_prompt $" { + fail "No progress?" + } + timeout { fail "timeout" } + } + #RM: Still want a low timeout + #set timeout $oldtimeout + + gdb_test "p debugger_saw" ".*5, 1, 9.*4, 6, 10.*3, 7, 12.*2, 8, 11.*" "check results" + + # Often only one misses; let's get detailed! + # + gdb_test "p debugger_saw\[0\]\[0\]" ".*= 5.*" "1" + gdb_test "p debugger_saw\[0\]\[1\]" ".*= 1.*" "2" + gdb_test "p debugger_saw\[0\]\[2\]" ".*= 9.*" "3" + gdb_test "p debugger_saw\[1\]\[0\]" ".*= 4.*" "4" + gdb_test "p debugger_saw\[1\]\[1\]" ".*= 6.*" "5" + gdb_test "p debugger_saw\[1\]\[2\]" ".*= 10.*" "6" + gdb_test "p debugger_saw\[2\]\[0\]" ".*= 3.*" "7" + gdb_test "p debugger_saw\[2\]\[1\]" ".*= 7.*" "8" + gdb_test "p debugger_saw\[2\]\[2\]" ".*= 12.*" "9" + gdb_test "p debugger_saw\[3\]\[0\]" ".*= 2.*" "10" + gdb_test "p debugger_saw\[3\]\[1\]" ".*= 8.*" "11" + gdb_test "p debugger_saw\[3\]\[2\]" ".*= 11.*" "12" + + send_gdb "i th\n" + gdb_expect { + -re ".* 1.*system thread.* 2.*system thread.*$gdb_prompt $" { + fail "Too many threads left" + } + -re ".*\\\* 1.*system thread.*main.*$gdb_prompt $" { + pass "Expect only base thread" + } + -re ".*No stack.*$gdb_prompt $" { + fail "runaway" + } + -re ".*$gdb_prompt $" { + fail "Hunh?" + } + timeout { fail "timeout" } + } + + gdb_test "c" ".*exited normally.*" "run to completion" + + # Done! + # + gdb_exit + + set timeout $oldtimeout + set verbose $oldverbose + + # execute_anywhere "rm -f ${binfile}" + # + return 0 diff -r -c -N ../gdb-19990719/gdb/testsuite/gdb.threads/thr-lib.h gdb/testsuite/gdb.threads/thr-lib.h *** ../gdb-19990719/gdb/testsuite/gdb.threads/thr-lib.h Wed Dec 31 16:00:00 1969 --- gdb/testsuite/gdb.threads/thr-lib.h Thu Jul 22 17:50:40 1999 *************** *** 0 **** --- 1,7 ---- + #include + #include + + #define NTHREADS 4 + #define NUM_ELEMS 12 + + #define ELEMS_PER_THREAD (NUM_ELEMS/NTHREADS) diff -r -c -N ../gdb-19990719/gdb/testsuite/gdb.threads/thr-liblib.c gdb/testsuite/gdb.threads/thr-liblib.c *** ../gdb-19990719/gdb/testsuite/gdb.threads/thr-liblib.c Wed Dec 31 16:00:00 1969 --- gdb/testsuite/gdb.threads/thr-liblib.c Thu Jul 22 17:50:40 1999 *************** *** 0 **** --- 1,92 ---- + #include + + /* Library code for thread local in lib test. + */ + #include "thr-lib.h" + + extern pthread_mutex_t mutex; + extern int get_number(); + extern int total; + extern int the_code_saw[NTHREADS][ELEMS_PER_THREAD]; + + /* The debugger should see this without a declaration. + * + * extern int debugger_saw[NTHREADS][ELEMS_PER_THREAD]; + */ + + /* The actual thread locals. + */ + __thread int sum; + __thread int x[ ELEMS_PER_THREAD ]; /* [3] */ + + void sumup() + { + int j; + + sum = 0; + for (j = 0; j < ELEMS_PER_THREAD; j++) { + sum += x[j]; + } + + if( sum == x[0] ) + /* It won't be "==", but this lets us set a breakpoint + * and look at the thread-local storage. + */ + sum++; + + x[0] = x[2]; /* Another no-op for debugger use */ + } + + void *adder( vid ) + void * vid; + { + int id; + int i, j; + int ret; + + id = (int) vid; + + /* printf( "== Thread: Welcome to adder %d\n", id ); */ + + for (j = 0; j < ELEMS_PER_THREAD; j++) { + x[j] = 0; + } + + for (i = id, j = 0; i < NUM_ELEMS; i += NTHREADS, j++ ) { + + /* printf( "== Thread: id %d, i %d, j %d\n", id, i, j ); + fflush( stdout ); */ + + x[j] = get_number(i); /* {0,1,2,3} +0, +4, +8 */ + + /* Record for posterity; the debugger will gather + * the same data here, using "x[j]". + */ + the_code_saw[ id ][ j ] = x[j]; + + /* printf( "== Thread %d, sample %d, val %d, i %d\n", id, j, x[j],i ); + fflush( stdout ); */ + } + + sumup(); + /* printf("== Thread: adder %d contributes total %d\n", id, sum); */ + + /* protect global data */ + ret = pthread_mutex_lock(&mutex); + if (ret != 0) { + printf("== Thread: pthread_mutex_lock() error: %d\n", ret); + exit(1); + } + + total += sum; + + ret = pthread_mutex_unlock(&mutex); + if (ret != 0) { + printf("== Thread: pthread_mutex_unlock() error: %d\n", ret); + exit(1); + } + + if( NTHREADS != 4 || ELEMS_PER_THREAD != 3 || NUM_ELEMS != 12 ) { + printf( "** ERROR in test code **\n" ); + } + } diff -r -c -N ../gdb-19990719/gdb/testsuite/gdb.threads/thr-stg.exp gdb/testsuite/gdb.threads/thr-stg.exp *** ../gdb-19990719/gdb/testsuite/gdb.threads/thr-stg.exp Wed Dec 31 16:00:00 1969 --- gdb/testsuite/gdb.threads/thr-stg.exp Thu Jul 22 17:50:40 1999 *************** *** 0 **** --- 1,245 ---- + # thread_local_stg.exp -- Expect script to test thread-local storage + # Copyright (C) 1992 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@prep.ai.mit.edu + + if $tracelevel then { + strace $tracelevel + } + + if { ![istarget "hppa*-*-hpux11.*"] } { + verbose "HPUX thread test ignored for non-hppa or pre-HP/UX-10.30 targets." + return 0 + } + + set testfile start-stop + set srcfile ${srcdir}/${subdir}/${testfile}.c + set binfile ${objdir}/${subdir}/${testfile} + + if [get_compiler_info ${binfile}] { + return -1 + } + + # To build the executable we need to link against the thread library. + # + if { $hp_cc_compiler } { + set additional_flags "additional_flags=-Ae" + } else { + set additional_flags "" + } + if { [gdb_compile "${srcdir}/${subdir}/${testfile}.c" "${binfile}" executable [list debug $additional_flags ldflags=-lpthread]] != "" } { + gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail." + } + + # Thread stuff is _slow_; prepare for long waits. + # + # Further, this test has some "null" lines designed + # to consume output from gdb that was too late to be + # matched (sequence is "gdb_test" sends; timeout and + # on to next send; result finally comes in; mismatch). + # + # The null command is 'gdb_test "p \$pc" ".*" ""' + # NOTE: this command undoes any up/down stuff! + # + proc pre_timeout {} { + global timeout + + set timeout [expr "$timeout + 100"] + } + + proc post_timeout {} { + global timeout + global oldtimeout + + set timeout $oldtimeout + gdb_test "p \$pc" ".*" "" + } + + gdb_exit + gdb_start + gdb_reinitialize_dir $srcdir/$subdir + + gdb_load ${binfile} + if ![runto_main] then { + fail "Can't run to main" + return 0 + } + + set oldtimeout $timeout + #set timeout [expr "$timeout + 200"] + set oldverbose $verbose + #set verbose 40 + + gdb_test "b do_pass" ".*" "set do_pass bp" + gdb_test "c" ".*do_pass.*" "run to do_pass" + gdb_test "cle" ".*" + + # Set a breakpoint at the "spin" routine and + # collect the thread local's value. + # + gdb_test "b 67" ".*Breakpoint 3.*67.*" "Set bp" + + # Can't use "gdb_test", as it uses "$gdb_prompt $" in + # testing the result. Our new prompt is ">", with + # no trailing space, so we can't do this just by + # changing "prompt". + # + # Anyway, I couldn't get expect to see the ">" prompt, + # during the command addition, so I just punted. + # _You_ are welcome to try, if you want! + # + send_gdb "commands 3\n" + gdb_expect { + -re "(.*Type commands.*\"end\"\.\r\n\>)" { + pass "start commands" + } + -re ".*$gdb_prompt $" { + fail "start commands" + } + } + + # Assume we're in commands-input mode. + # + send_gdb "silent\n" + send_gdb "set val_debugger_saw\[me\] = a_thread_local\n" + send_gdb "continue\n" + send_gdb "end\n" + + gdb_expect { + -re ".*set.*cont.*$gdb_prompt $" { + pass "add commands" + } + -re ".*$gdb_prompt $" { + fail "add commands" + } + } + + # Check out of paranoia. + # + send_gdb "info break 3\n" + gdb_expect { + -re ".*breakpoint.*set val_debugger.*continue.*$gdb_prompt $" { + pass "Commands added" + } + -re ".*$gdb_prompt $" { + fail "Commands not added." + } + } + + # Set a bp to inspect the results + # + gdb_test "b 134" ".*Breakpoint 4.*" + + # We now expect to run through a whole pass, seeing + # specific results as noted below (actual gotten by + # running application with debugging print statements + # turned on. + # + # Since this'll run for while, set a generous timeout. + # + set timeout [expr "$timeout + 30"] + send_gdb "c\n" + gdb_expect { + -re ".*Program exited normally.*$gdb_prompt $" { + fail "program runaway" + } + -re ".*Pass 0 done.*Pass 1 done.*$gdb_prompt $" { + fail "program runaway 2" + } + -re ".*Pass 0 done.*Breakpoint 4.*134.*$gdb_prompt $" { + pass "get to end of first pass" + } + -re ".*$gdb_prompt $" { + fail "No progress?" + } + timeout { fail "timeout" } + } + + gdb_test "p val_debugger_saw" ".*0, 1, 3.*" "first pass" + + send_gdb "i th\n" + gdb_expect { + -re ".* 1.*system thread.* 2.*system thread.*$gdb_prompt $" { + fail "Too many threads left" + } + -re ".*\\\* 1 system thread.*$gdb_prompt $" { + pass "Expect only base thread" + } + -re ".*No stack.*$gdb_prompt $" { + fail "runaway" + } + -re ".*$gdb_prompt $" { + fail "Hunh?" + } + timeout { fail "timeout" } + } + + gdb_test "i b" ".*4.*breakpoint.*134.*hit.*1 time.*" "Expect 134 bp to exist" + + gdb_test "c" ".*Breakpoint 4.*134.*" "get to end of second pass" + gdb_test "p val_debugger_saw" ".*6, 10, 15.*" "second pass" + + gdb_test "c" ".*Breakpoint 4.*134.*" "get to end of third pass" + gdb_test "p val_debugger_saw" ".*21, 28, 36.*" "third pass" + + gdb_test "info bre 3" ".*already hit 9 times.*" "count of silent bp hits" + + # Start over and do some "info address" stuff + # + send_gdb "d\n" + gdb_expect { + -re ".*Delete all breakpoints.*$" { + send_gdb "y\n" + gdb_expect { + -re ".*$gdb_prompt $" { + pass "del bps" + } + } + } + -re ".*$gdb_prompt $" { fail "no question" } + } + + gdb_test "b spin" ".*Breakpoint 5.*" + + send_gdb "r\n" + gdb_expect { + -re ".*Start it from the beginning.*$" { + send_gdb "y\n" + gdb_expect { + -re ".*$gdb_prompt $" { pass "restart" } + } + } + -re ".*Starting program.*$gdb_prompt $" { + pass "restart after previous fails" + } + -re ".*$gdb_prompt $" { fail "Can't restart" } + } + gdb_test "i ad a_global" ".*a_global.*static storage at address.*" "i ad a_global" + gdb_test "i add me" ".*me.*local variable at frame offset.*" "i ad me" + gdb_test "i ad a_thread_local" ".*a_thread_local.*a thread-local variable at offset.*" "i ad a_thread_local" + + # Done! + # + gdb_exit + + set timeout $oldtimeout + set verbose $oldverbose + + # execute_anywhere "rm -f ${binfile}" + # + return 0