OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /openrisc/trunk/gnu-old/gdb-7.1/gdb/testsuite/gdb.threads
    from Rev 227 to Rev 816
    Reverse comparison

Rev 227 → Rev 816

/print-threads.exp
0,0 → 1,126
# Copyright (C) 1996, 1997, 2002, 2003, 2007, 2008, 2009, 2010
# 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 3 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, see <http://www.gnu.org/licenses/>.
 
# This file was written by Daniel Jacobowitz <drow@mvista.com>
# (parts based on pthreads.exp by Fred Fish (fnf@cygnus.com).
#
# It tests miscellaneous actions with multiple threads, including
# handling for thread exit.
 
if $tracelevel then {
strace $tracelevel
}
 
set prms_id 0
set bug_id 0
 
set testfile "print-threads"
set srcfile ${testfile}.c
set binfile ${objdir}/${subdir}/${testfile}
 
# regexp for "horizontal" text (i.e. doesn't include newline or
# carriage return)
set horiz "\[^\n\r\]*"
 
if {[gdb_compile_pthreads "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable [list debug "incdir=${objdir}"]] != "" } {
return -1
}
 
# Now we can proceed with the real testing.
 
# Start with a fresh gdb.
 
gdb_exit
gdb_start
gdb_reinitialize_dir $srcdir/$subdir
gdb_load ${binfile}
 
gdb_test "set print sevenbit-strings" ""
#gdb_test "set print address off" ""
gdb_test "set width 0" ""
 
# We'll need this when we send_gdb a ^C to GDB. Need to do it before we
# run the program and gdb starts saving and restoring tty states.
# On Ultrix, we don't need it and it is really slow (because shell_escape
# doesn't use vfork).
if ![istarget "*-*-ultrix*"] then {
gdb_test "shell stty intr '^C'" ""
}
 
proc test_all_threads { name kill } {
global gdb_prompt
 
set i 0
set j 0
send_gdb "continue\n"
gdb_expect {
-re "Breakpoint \[0-9\]+, thread_function \\(arg=.*\\) at .*print-threads.c:\[0-9\]+.*$gdb_prompt" {
set i [expr $i + 1]
pass "Hit thread_function breakpoint, $i ($name)"
send_gdb "continue\n"
exp_continue
}
-re "Breakpoint \[0-9\]+, .* kill \\(.*\\) .*$gdb_prompt" {
set j [expr $j + 1]
if { $kill == 1 } {
pass "Hit kill breakpoint, $j ($name)"
} else {
fail "Hit kill breakpoint, $j ($name) (unexpected)"
}
send_gdb "continue\n"
exp_continue
}
-re "Program exited normally\\.\[\r\n\]+$gdb_prompt" {
pass "program exited normally"
if {$i == 5} {
pass "all threads ran once ($name)"
} else {
fail "all threads ran once ($name) (total $i threads ran)"
}
}
-re "Program received signal SIGTRAP.*(Thread \[-0-9a-fx\]* \\(zombie\\)|0x00000000 in ).*$gdb_prompt $" {
if { $kill == 1 } {
kfail "gdb/1265" "Running threads ($name) (zombie thread)"
} else {
fail "Running threads ($name) (unknown output)"
}
}
-re "$gdb_prompt" {
fail "Running threads ($name) (unknown output)"
}
timeout {
fail "Running threads ($name) (timeout)"
}
}
}
 
runto_main
gdb_test "break thread_function" "Breakpoint \[0-9\]+ at 0x\[0-9a-f\]+: file .*print-threads.c, line \[0-9\]*\\."
gdb_test "set var slow = 0" ""
test_all_threads "fast" 0
 
runto_main
gdb_test "break thread_function" "Breakpoint \[0-9\]+ at 0x\[0-9a-f\]+: file .*print-threads.c, line \[0-9\]*\\." "break thread_function (2)"
gdb_test "set var slow = 1" ""
test_all_threads "slow" 0
 
runto_main
gdb_test "break thread_function" "Breakpoint \[0-9\]+ at 0x\[0-9a-f\]+: file .*print-threads.c, line \[0-9\]*\\." "break thread_function (3)"
gdb_test "set var slow = 1" "" "set var slow = 1 (2)"
gdb_breakpoint "kill"
test_all_threads "slow with kill breakpoint" 1
 
return 0
/threxit-hop-specific.c
0,0 → 1,48
/* This testcase is part of GDB, the GNU debugger.
 
Copyright 2009, 2010 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 3 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, see <http://www.gnu.org/licenses/>. */
 
#include <pthread.h>
#include <unistd.h>
#include <stdlib.h>
 
void *
thread_function (void *arg)
{
/* We'll next over this, with scheduler-locking off. */
pthread_exit (NULL);
}
 
void
hop_me (void)
{
}
 
int
main (int argc, char **argv)
{
pthread_t thread;
 
pthread_create (&thread, NULL, thread_function, NULL);
pthread_join (thread, NULL); /* wait for exit */
 
/* The main thread should be able to hop over the breakpoint set
here... */
hop_me (); /* set thread specific breakpoint here */
 
/* ... and reach here. */
exit (0); /* set exit breakpoint here */
}
threxit-hop-specific.c Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +Id \ No newline at end of property Index: linux-dp.c =================================================================== --- linux-dp.c (nonexistent) +++ linux-dp.c (revision 816) @@ -0,0 +1,207 @@ +/* linux-dp.c --- dining philosophers, on LinuxThreads + Jim Blandy --- March 1999 */ + +/* It's okay to edit this file and shift line numbers around. The + tests use gdb_get_line_number to find source locations, so they + don't depend on having certain line numbers in certain places. */ + +#include +#include +#include +#include +#include +#include + +/* The number of philosophers at the table. */ +int num_philosophers; + +/* Mutex ordering - + If you want to lock a mutex M, all the mutexes you have locked + already must appear before M on this list. + + fork_mutex[0] + fork_mutex[1] + ... + fork_mutex[num_philosophers - 1] + stdout_mutex + random_mutex +*/ + +/* You must hold this mutex while writing to stdout. */ +pthread_mutex_t stdout_mutex; + +/* You must hold this mutex while calling any of the random number + generation routines. */ +pthread_mutex_t random_mutex; + +/* array of mutexes, one for each fork; fork_mutex[i] is to the left + of philosopher i. A philosopher is holding fork i iff his/her + thread has locked fork_mutex[i]. */ +pthread_mutex_t *fork_mutex; + +/* array of threads, one representing each philosopher. */ +pthread_t *philosophers; + +void * +xmalloc (size_t n) +{ + void *p = malloc (n); + + if (! p) + { + fprintf (stderr, "out of memory\n"); + exit (2); + } + + return p; +} + +void +shared_printf (char *format, ...) +{ + va_list ap; + + va_start (ap, format); + pthread_mutex_lock (&stdout_mutex); + vprintf (format, ap); + pthread_mutex_unlock (&stdout_mutex); + va_end (ap); +} + +int +shared_random () +{ + static unsigned int seed; + int result; + + pthread_mutex_lock (&random_mutex); + result = rand_r (&seed); + pthread_mutex_unlock (&random_mutex); + return result; +} + +void +my_usleep (long usecs) +{ + struct timeval timeout; + + timeout.tv_sec = usecs / 1000000; + timeout.tv_usec = usecs % 1000000; + + select (0, 0, 0, 0, &timeout); +} + +void +random_delay () +{ + my_usleep ((shared_random () % 2000) * 100); +} + +void +print_philosopher (int n, char left, char right) +{ + int i; + + shared_printf ("%*s%c %d %c\n", (n * 4) + 2, "", left, n, right); +} + +void * +philosopher (void *data) +{ + int n = * (int *) data; + + print_philosopher (n, '_', '_'); + +#if 1 + if (n == num_philosophers - 1) + for (;;) + { + /* The last philosopher is different. He goes for his right + fork first, so there is no cycle in the mutex graph. */ + + /* Grab the right fork. */ + pthread_mutex_lock (&fork_mutex[(n + 1) % num_philosophers]); + print_philosopher (n, '_', '!'); + random_delay (); + + /* Then grab the left fork. */ + pthread_mutex_lock (&fork_mutex[n]); + print_philosopher (n, '!', '!'); + random_delay (); + + print_philosopher (n, '_', '_'); + pthread_mutex_unlock (&fork_mutex[n]); + pthread_mutex_unlock (&fork_mutex[(n + 1) % num_philosophers]); + random_delay (); + } + else +#endif + for (;;) + { + /* Grab the left fork. */ + pthread_mutex_lock (&fork_mutex[n]); + print_philosopher (n, '!', '_'); + random_delay (); + + /* Then grab the right fork. */ + pthread_mutex_lock (&fork_mutex[(n + 1) % num_philosophers]); + print_philosopher (n, '!', '!'); + random_delay (); + + print_philosopher (n, '_', '_'); + pthread_mutex_unlock (&fork_mutex[n]); + pthread_mutex_unlock (&fork_mutex[(n + 1) % num_philosophers]); + random_delay (); + } + + return (void *) 0; +} + +int +main (int argc, char **argv) +{ + num_philosophers = 5; + + /* Set up the mutexes. */ + { + pthread_mutexattr_t ma; + int i; + + pthread_mutexattr_init (&ma); + pthread_mutex_init (&stdout_mutex, &ma); + pthread_mutex_init (&random_mutex, &ma); + fork_mutex = xmalloc (num_philosophers * sizeof (fork_mutex[0])); + for (i = 0; i < num_philosophers; i++) + pthread_mutex_init (&fork_mutex[i], &ma); + pthread_mutexattr_destroy (&ma); + } + + /* Set off the threads. */ + { + int i; + int *numbers = xmalloc (num_philosophers * sizeof (*numbers)); + pthread_attr_t ta; + + philosophers = xmalloc (num_philosophers * sizeof (*philosophers)); + + pthread_attr_init (&ta); + + for (i = 0; i < num_philosophers; i++) + { + numbers[i] = i; + /* linuxthreads.exp: create philosopher */ + pthread_create (&philosophers[i], &ta, philosopher, &numbers[i]); + } + + pthread_attr_destroy (&ta); + } + + /* linuxthreads.exp: info threads 2 */ + sleep (1000000); + + /* Drink yourself into oblivion. */ + for (;;) + sleep (1000000); + + return 0; +}
linux-dp.c Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +Id \ No newline at end of property Index: Makefile.in =================================================================== --- Makefile.in (nonexistent) +++ Makefile.in (revision 816) @@ -0,0 +1,13 @@ +VPATH = @srcdir@ +srcdir = @srcdir@ + +EXECUTABLES = pthreads + +all info install-info dvi install uninstall installcheck check: + @echo "Nothing to be done for $@..." + +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 Index: attachstop-mt.exp =================================================================== --- attachstop-mt.exp (nonexistent) +++ attachstop-mt.exp (revision 816) @@ -0,0 +1,267 @@ +# Copyright 2008, 2009, 2010 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 3 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, see . + +# This test is based on gdb.base/attach.exp with modifications by Jeff Johnston +# and Jan Kratochvil . + +# This test only works on Linux +if { ![isnative] || [is_remote host] || ![istarget *-linux*] } { + continue +} + +set testfile "attachstop-mt" +set srcfile ${testfile}.c +set binfile ${objdir}/${subdir}/${testfile} +set escapedbinfile [string_to_regexp ${objdir}/${subdir}/${testfile}] + +#execute_anywhere "rm -f ${binfile}" +remote_exec build "rm -f ${binfile}" +# For debugging this test +# +#log_user 1 + +# build the test case +# +if { [gdb_compile_pthreads "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug}] != "" } { + untested attachstop-mt.exp + return -1 +} + +if [get_compiler_info ${binfile}] { + return -1 +} + +# Start the program running and then wait for a bit, to be sure +# that it can be attached to. + +set testpid [eval exec $binfile &] + +# No race +sleep 2 + +# The testcase has three threads, find some other thread TID for $testpid2. +set tids [exec sh -c "echo /proc/$testpid/task/*"] +regsub -all /proc/$testpid/task/ $tids {} tids +if {$tids == "*"} { + unresolved "/proc/PID/task is not supported (kernel-2.4?)" + remote_exec build "kill -9 ${testpid}" + return -1 +} +set tids [lsort -integer [split $tids]] +if {[llength $tids] != 3 || [lindex $tids 0] != $testpid} { + verbose -log "Invalid TIDs <$tids> for PID $testpid" + fail "Invalid TIDs found" + remote_exec build "kill -9 ${testpid}" + return -1 +} +set testpid2 [lindex $tids 2] + +# Initial sanity test it is normally sleeping +set status2 /proc/${testpid}/task/${testpid2}/status +set fileid0 [open $status2 r]; +gets $fileid0 line1; +gets $fileid0 line2; +close $fileid0; + +set test "attach0, initial sanity check of the sleeping state" +if {[string match "*(sleeping)*" $line2]} { + pass $test +} else { + fail $test +} + +# Sttach and detach to test it will not become stopped +gdb_start +gdb_reinitialize_dir $srcdir/$subdir +gdb_load ${binfile} + +set test "attach0 to sleeping" +gdb_test_multiple "attach $testpid" "$test" { + -re "Attaching to program.*`?$escapedbinfile'?, process $testpid.*$gdb_prompt $" { + pass "$test" + } +} + +gdb_test "gcore /dev/null" ".*aved corefile.*" "attach0 to sleeping gcore invocation" + +gdb_test "thread 2" ".*witching to thread 2 .*" "attach0 to sleeping switch thread" + +gdb_test "bt" ".*sleep.*func.*" "attach0 to sleeping bt" + +# Exit and detach the process. + +gdb_exit + +# No race +sleep 2 + +# Check it did not get stopped by our gdb +set fileid1 [open $status2 r]; +gets $fileid1 line1; +gets $fileid1 line2; +close $fileid1; + +set test "attach1, post-gdb sanity check of the sleeping state - Red Hat BZ 197584" +if {[string match "*(sleeping)*" $line2]} { + pass $test +} else { + fail $test +} + +# Stop the program +remote_exec build "kill -s STOP ${testpid}" + +# No race +sleep 2 + +# Check it really got stopped by kill(1) +set fileid2 [open $status2 r]; +gets $fileid2 line1; +gets $fileid2 line2; +close $fileid2; + +set test "attach2, initial sanity check of the stopped state" +if {[string match "*(stopped)*" $line2]} { + pass $test +} else { + fail $test +} + +# Start with clean gdb +gdb_start +gdb_reinitialize_dir $srcdir/$subdir +gdb_load ${binfile} + +# Verify that we can attach to the process by first giving its +# executable name via the file command, and using attach with the +# process ID. + +set test "set file, before attach3 to stopped process" +gdb_test_multiple "file $binfile" "$test" { + -re "Load new symbol table from.*y or n. $" { + gdb_test "y" "Reading symbols from $escapedbinfile\.\.\.*done." \ + "$test (re-read)" + } + -re "Reading symbols from $escapedbinfile\.\.\.*done.*$gdb_prompt $" { + pass "$test" + } +} + +set test "attach3 to stopped, after setting file" +gdb_test_multiple "attach $testpid" "$test" { + -re "Attaching to program.*`?$escapedbinfile'?, process $testpid.*$gdb_prompt $" { + pass "$test" + } +} + +# We may be already after the threads phase. +# `thread 2' command is important for the test to switch the current thread to +# a non-primary one for the detach process. + +gdb_test "thread 2" ".*(witching to thread 2 |hread ID 2 not known).*" "attach3 to stopped switch thread" +gdb_test "bt" ".*sleep.*(func|main).*" "attach3 to stopped bt" + +# Exit and detach the process. +gdb_exit + +# Stop the program +remote_exec build "kill -s STOP ${testpid}" + +# No race +sleep 2 + +# Continue the test as we would hit another expected bug regarding +# Program received signal SIGSTOP, Stopped (signal). +# across NPTL threads. + +gdb_start +gdb_reinitialize_dir $srcdir/$subdir +gdb_load ${binfile} + +# Verify that we can attach to the process just by giving the +# process ID. + +set test "attach4 to stopped, after setting file" +gdb_test_multiple "attach $testpid" "$test" { + -re "Attaching to program.*`?$escapedbinfile'?, process $testpid.*$gdb_prompt $" { + pass "$test" + } +} + +# We may be already after the threads phase. +# `thread 2' command is important for the test to switch the current thread to +# a non-primary one for the detach process. + +gdb_test "thread 2" ".*(witching to thread 2 |hread ID 2 not known).*" "attach4 to stopped switch thread" +gdb_test "bt" ".*sleep.*(func|main).*" "attach4 to stopped bt" + +# RHEL3U8 kernel-2.4.21-47.EL will not return SIGINT but only shorten the sleep. +gdb_breakpoint [gdb_get_line_number "Ridiculous time"] +gdb_breakpoint [gdb_get_line_number "cut the sleep time"] +set test "attach4 continue" +send_gdb "continue\n" +gdb_expect { + -re "Continuing" + { pass "continue ($test)" } + timeout + { fail "continue ($test) (timeout)" } +} + +# For this to work we must be sure to consume the "Continuing." +# message first, or GDB's signal handler may not be in place. +after 1000 {send_gdb "\003"} +set test "attach4 stop by interrupt" +gdb_expect { + -re "Program received signal SIGINT.*$gdb_prompt $" + { + pass $test + } + -re "Breakpoint \[0-9\].*$srcfile.*$gdb_prompt $" + { + pass $test + } + timeout + { + fail "$test (timeout)" + } +} + +gdb_exit + +# No race +sleep 2 + +# At this point, the process should be sleeping + +set fileid4 [open $status2 r]; +gets $fileid4 line1; +gets $fileid4 line2; +close $fileid4; + +set test "attach4, exit leaves process sleeping" +if {[string match "*(sleeping)*" $line2]} { + pass $test +} else { + fail $test +} + +# Make sure we don't leave a process around to confuse +# the next test run (and prevent the compile by keeping +# the text file busy), in case the "set should_exit" didn't +# work. + +remote_exec build "kill -9 ${testpid}" + +return 0 Index: staticthreads.c =================================================================== --- staticthreads.c (nonexistent) +++ staticthreads.c (revision 816) @@ -0,0 +1,71 @@ +/* This test program is part of GDB, The GNU debugger. + + Copyright 2004, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. + + Originally written by Jeff Johnston , + contributed by Red Hat + + This file is part of GDB. + + 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 3 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, see . */ + +#include +#include +#include +#include +#include + +sem_t semaphore; + +void * +thread_function (void *arg) +{ + printf ("Thread executing\n"); + while (sem_wait (&semaphore) != 0) + { + if (errno != EINTR) + { + perror ("thread_function"); + return; + } + } + return NULL; +} + +int +main (int argc, char **argv) +{ + pthread_attr_t attr; + + pthread_attr_init (&attr); + pthread_attr_setstacksize (&attr, PTHREAD_STACK_MIN); + + if (sem_init (&semaphore, 0, 0) == -1) + { + perror ("semaphore"); + return -1; + } + + + /* Create a thread, wait for it to complete. */ + { + pthread_t thread; + pthread_create (&thread, &attr, thread_function, NULL); + sem_post (&semaphore); + pthread_join (thread, NULL); + } + + pthread_attr_destroy (&attr); + return 0; +}
staticthreads.c Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +Id \ No newline at end of property Index: killed.c =================================================================== --- killed.c (nonexistent) +++ killed.c (revision 816) @@ -0,0 +1,42 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2002, 2004, 2007, 2008, 2009, 2010 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 3 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, see . */ + +#include +#include +#include +#include +#include + +int pid; + +void * +child_func (void *dummy) +{ + kill (pid, SIGKILL); + exit (1); +} + +int +main () +{ + pthread_t child; + + pid = getpid (); + pthread_create (&child, 0, child_func, 0); + for (;;) + sleep (10000); +}
killed.c Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +Id \ No newline at end of property Index: thread_check.c =================================================================== --- thread_check.c (nonexistent) +++ thread_check.c (revision 816) @@ -0,0 +1,73 @@ +/* Copyright (C) 2004, 2007, 2008, 2009, 2010 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 3 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, see . + + This file was written by Steve Munroe (sjmunroe@us.ibm.com). */ + +/* Test break points and single step on thread functions. */ + +#include +#include +#include +#include +#include +#include + +#define N 2 + +static void * +tf (void *arg) +{ + int n = (int) (long int) arg; + char number[160]; + int unslept = 10; + + sprintf(number, "tf(%ld): begin", (long)arg); + puts (number); + + while (unslept > 0) + unslept = sleep(unslept); + + sprintf(number, "tf(%ld): end", (long)arg); + puts (number); + return NULL; +} + +int main (int argc, char *argv[]) +{ + int n; + int unslept = 2; + pthread_t th[N]; + + for (n = 0; n < N; ++n) + if (pthread_create (&th[n], NULL, tf, (void *) (long int) n) != 0) + { + while (unslept > 0) + unslept = sleep(2); + puts ("create failed"); + exit (1); + } + + puts("after create"); + + for (n = 0; n < N; ++n) + if (pthread_join (th[n], NULL) != 0) + { + puts ("join failed"); + exit (1); + } + + puts("after join"); + return 0; +}
thread_check.c Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +Id \ No newline at end of property Index: multi-create.exp =================================================================== --- multi-create.exp (nonexistent) +++ multi-create.exp (revision 816) @@ -0,0 +1,40 @@ +# multi-create.exp -- Test creating many threads in parallel +# Copyright (C) 2007, 2008, 2009, 2010 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 3 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, see . + +set testfile "multi-create" +set srcfile ${testfile}.c +set binfile ${objdir}/${subdir}/${testfile} + +if {[gdb_compile_pthreads "${srcdir}/${subdir}/${srcfile}" "${binfile}" \ + executable {debug}] != "" } { + return -1 +} + +gdb_start +gdb_reinitialize_dir $srcdir/$subdir +gdb_load ${binfile} +runto_main + +# Run to the beginning of create_function several times. Make sure +# we always stop there, and not somewhere else in the guts of the +# thread library. + +set bp_location1 [gdb_get_line_number "set breakpoint 1 here"] +gdb_breakpoint $srcfile:$bp_location1 +for {set i 0} {$i < 32} {incr i} { + gdb_test "continue" ".*Breakpoint $decimal,.*$srcfile:$bp_location1.*" \ + "continue to breakpoint $i" +} Index: schedlock.exp =================================================================== --- schedlock.exp (nonexistent) +++ schedlock.exp (revision 816) @@ -0,0 +1,346 @@ +# Copyright (C) 1996, 1997, 2002, 2003, 2007, 2008, 2009, 2010 +# 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 3 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, see . + +# This file was written by Daniel Jacobowitz +# (parts based on pthreads.exp by Fred Fish (fnf@cygnus.com). +# +# This test covers the various forms of "set scheduler-locking". + +if $tracelevel then { + strace $tracelevel +} + +set prms_id 0 +set bug_id 0 + +set testfile "schedlock" +set srcfile ${testfile}.c +set binfile ${objdir}/${subdir}/${testfile} + +# The number of threads, including the main thread. +set NUM 2 + +if {[gdb_compile_pthreads "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable [list debug "incdir=${objdir}"]] != "" } { + return -1 +} + +# Now we can proceed with the real testing. + +proc get_args { } { + global list_count + global gdb_prompt + global NUM + + set pattern "(\[0-9\]+)" + for {set i 1} {[expr $i < $NUM]} {incr i} { + append pattern ", (\[0-9\]+)" + } + + send_gdb "print args\n" + gdb_expect { + -re "\\\$\[0-9\]+ = {$pattern}.*$gdb_prompt" + { + set list_count [expr $list_count + 1] + pass "listed args ($list_count)" + + set result "" + for {set i 1} {[expr $i <= $NUM]} {incr i} { + lappend result $expect_out($i,string) + } + return $result + } + -re "$gdb_prompt" + { + fail "listed args ($list_count) (unknown output)" + } + timeout + { + fail "listed args ($list_count) (timeout)" + } + } +} + +proc stop_process { description } { + global gdb_prompt + + # For this to work we must be sure to consume the "Continuing." + # message first, or GDB's signal handler may not be in place. + after 1000 {send_gdb "\003"} + gdb_expect { + -re "Program received signal SIGINT.*$gdb_prompt $" + { + pass $description + } + timeout + { + fail "$description (timeout)" + } + } +} + +proc get_current_thread { description } { + global gdb_prompt + + send_gdb "bt\n" + gdb_expect { + -re "thread_function \\(arg=0x(\[0-9\])\\).*$gdb_prompt $" + { + pass $description + return $expect_out(1,string) + } + -re "$gdb_prompt $" + { + fail "$description (unknown output)" + } + timeout + { + fail "$description (timeout)" + } + } +} + +proc my_continue { msg } { + send_gdb "continue\n" + gdb_expect { + -re "Continuing" + { pass "continue ($msg)" } + timeout + { fail "continue ($msg) (timeout)" } + } + + stop_process "stop all threads ($msg)" + + # Make sure we're in one of the non-main looping threads. + gdb_breakpoint [concat [gdb_get_line_number "schedlock.exp: main loop"] " if arg != 0"] + gdb_continue_to_breakpoint "return to loop ($msg)" + delete_breakpoints +} + +proc step_ten_loops { msg } { + global gdb_prompt + + for {set i 0} {[expr $i < 10]} {set i [expr $i + 1]} { + send_gdb "step\n" + set other_step 0 + gdb_expect { + -re ".*myp\\) \\+\\+;\[\r\n\]+$gdb_prompt $" { + pass "step to increment ($msg $i)" + } + -re "$gdb_prompt $" { + if {$other_step == 0} { + set other_step 1 + send_gdb "step\n" + exp_continue + } else { + fail "step to increment ($msg $i)" + # FIXME cascade? + } + } + timeout { + fail "step to increment ($msg $i) (timeout)" + } + } + } +} + +# Start with a fresh gdb. + +gdb_exit +gdb_start +gdb_reinitialize_dir $srcdir/$subdir + +# We'll need this when we send_gdb a ^C to GDB. Need to do it before we +# run the program and gdb starts saving and restoring tty states. +# On Ultrix, we don't need it and it is really slow (because shell_escape +# doesn't use vfork). +if ![istarget "*-*-ultrix*"] then { + gdb_test "shell stty intr '^C'" "" +} + +gdb_load ${binfile} + +gdb_test "set print sevenbit-strings" "" +gdb_test "set width 0" "" + +runto_main + +# See if scheduler locking is available on this target. +send_gdb "set scheduler-locking off\n" +global gdb_prompt +gdb_expect { + -re "Target .* cannot support this command" + { + unsupported "target does not support scheduler locking" + return + } + -re "$gdb_prompt $" + { + pass "scheduler locking set to none" + } + timeout + { + unsupported "target does not support scheduler locking (timeout)" + return + } +} + +gdb_breakpoint [gdb_get_line_number "schedlock.exp: last thread start"] +gdb_continue_to_breakpoint "all threads started" + +global list_count +set list_count 0 + +set start_args [get_args] + +# First make sure that all threads are alive. +my_continue "initial" + +set cont_args [get_args] + +set bad 0 +for {set i 0} {[expr $i < $NUM]} {set i [expr $i + 1]} { + if {[lindex $start_args $i] == [lindex $cont_args $i]} { + incr bad + } +} +if { $bad == 0 } { + pass "all threads alive" +} else { + fail "all threads alive ($bad/$NUM did not run)" +} + +# We can't change threads, unfortunately, in current GDB. Use +# whichever we stopped in. +set curthread [get_current_thread "find current thread (1)"] + + + + +# Test stepping without scheduler locking. +gdb_test "set scheduler-locking off" "" + +step_ten_loops "unlocked" + +# Make sure we're still in the same thread. +set newthread [get_current_thread "find current thread (2)"] +if {$curthread == $newthread} { + pass "step without lock does not change thread" +} else { + fail "step without lock does not change thread (switched to thread $newthread)" +} + +set start_args $cont_args +set cont_args [get_args] + +set num_other_threads 0 +for {set i 0} {[expr $i < $NUM]} {set i [expr $i + 1]} { + if {[lindex $start_args $i] == [lindex $cont_args $i]} { + if {$i == $curthread} { + fail "current thread stepped (didn't run)" + } + } else { + if {$i == $curthread} { + if {[lindex $start_args $i] == [expr [lindex $cont_args $i] - 10]} { + pass "current thread stepped" + } else { + fail "current thread stepped (wrong amount)" + } + } else { + set num_other_threads [expr $num_other_threads + 1] + } + } +} +if {$num_other_threads > 0} { + pass "other threads ran - unlocked" +} else { + fail "other threads ran - unlocked" +} + +# Test continue with scheduler locking +gdb_test "set scheduler-locking on" "" + +my_continue "with lock" + +# Make sure we're still in the same thread. +set newthread [get_current_thread "find current thread (3)"] +if {$curthread == $newthread} { + pass "continue with lock does not change thread" +} else { + fail "continue with lock does not change thread (switched to thread $newthread)" +} + +set start_args $cont_args +set cont_args [get_args] + +set num_other_threads 0 +for {set i 0} {[expr $i < $NUM]} {set i [expr $i + 1]} { + if {[lindex $start_args $i] == [lindex $cont_args $i]} { + if {$i == $curthread} { + fail "current thread ran (didn't run)" + } + } else { + if {$i == $curthread} { + pass "current thread ran" + } else { + incr num_other_threads + } + } +} +if {$num_other_threads > 0} { + fail "other threads didn't run - locked" +} else { + pass "other threads didn't run - locked" +} + +# Test stepping with scheduler locking +step_ten_loops "locked" + +# Make sure we're still in the same thread. +set newthread [get_current_thread "find current thread (2)"] +if {$curthread == $newthread} { + pass "step with lock does not change thread" +} else { + fail "step with lock does not change thread (switched to thread $newthread)" +} + +set start_args $cont_args +set cont_args [get_args] + +set num_other_threads 0 +for {set i 0} {[expr $i < $NUM]} {set i [expr $i + 1]} { + if {[lindex $start_args $i] == [lindex $cont_args $i]} { + if {$i == $curthread} { + fail "current thread stepped locked (didn't run)" + } + } else { + if {$i == $curthread} { + if {[lindex $start_args $i] == [expr [lindex $cont_args $i] - 10]} { + pass "current thread stepped locked" + } else { + fail "current thread stepped locked (wrong amount)" + } + } else { + incr num_other_threads + } + } +} +if {$num_other_threads > 0} { + fail "other threads didn't run - step locked" +} else { + pass "other threads didn't run - step locked" +} + +return 0 Index: pthreads.c =================================================================== --- pthreads.c (nonexistent) +++ pthreads.c (revision 816) @@ -0,0 +1,171 @@ +/* Pthreads test program. + Copyright 1996, 2002, 2003, 2004, 2007, 2008, 2009, 2010 + Free Software Foundation, Inc. + + Written by Fred Fish of Cygnus Support + Contributed by Cygnus Support + + This file is part of GDB. + + 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 3 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, see . */ + +#include +#include +#include + +/* Under OSF 2.0 & 3.0 and HPUX 10, the second arg of pthread_create + is prototyped to be just a "pthread_attr_t", while under Solaris it + is a "pthread_attr_t *". Arg! */ + +#if defined (__osf__) || defined (__hpux__) +#define PTHREAD_CREATE_ARG2(arg) arg +#define PTHREAD_CREATE_NULL_ARG2 null_attr +static pthread_attr_t null_attr; +#else +#define PTHREAD_CREATE_ARG2(arg) &arg +#define PTHREAD_CREATE_NULL_ARG2 NULL +#endif + +static int verbose = 0; + +static void +common_routine (arg) + int arg; +{ + static int from_thread1; + static int from_thread2; + static int from_main; + static int hits; + static int full_coverage; + + if (verbose) printf("common_routine (%d)\n", arg); + hits++; + switch (arg) + { + case 0: + from_main++; + break; + case 1: + from_thread1++; + break; + case 2: + from_thread2++; + break; + } + if (from_main && from_thread1 && from_thread2) + full_coverage = 1; +} + +static void * +thread1 (void *arg) +{ + int i; + int z = 0; + + if (verbose) printf ("thread1 (%0x) ; pid = %d\n", arg, getpid ()); + for (i=1; i <= 10000000; i++) + { + if (verbose) printf("thread1 %d\n", pthread_self ()); + z += i; + common_routine (1); + sleep(1); + } + return (void *) 0; +} + +static void * +thread2 (void * arg) +{ + int i; + int k = 0; + + if (verbose) printf ("thread2 (%0x) ; pid = %d\n", arg, getpid ()); + for (i=1; i <= 10000000; i++) + { + if (verbose) printf("thread2 %d\n", pthread_self ()); + k += i; + common_routine (2); + sleep(1); + } + sleep(100); + return (void *) 0; +} + +void +foo (a, b, c) + int a, b, c; +{ + int d, e, f; + + if (verbose) printf("a=%d\n", a); +} + +main(argc, argv) + int argc; + char **argv; +{ + pthread_t tid1, tid2; + int j; + int t = 0; + void (*xxx) (); + pthread_attr_t attr; + + if (verbose) printf ("pid = %d\n", getpid()); + + foo (1, 2, 3); + +#ifndef __osf__ + if (pthread_attr_init (&attr)) + { + perror ("pthread_attr_init 1"); + exit (1); + } +#endif + +#ifdef PTHREAD_SCOPE_SYSTEM + if (pthread_attr_setscope (&attr, PTHREAD_SCOPE_SYSTEM)) + { + perror ("pthread_attr_setscope 1"); + exit (1); + } +#endif + + if (pthread_create (&tid1, PTHREAD_CREATE_ARG2(attr), thread1, (void *) 0xfeedface)) + { + perror ("pthread_create 1"); + exit (1); + } + if (verbose) printf ("Made thread %d\n", tid1); + sleep (1); + + if (pthread_create (&tid2, PTHREAD_CREATE_NULL_ARG2, thread2, (void *) 0xdeadbeef)) + { + perror ("pthread_create 2"); + exit (1); + } + if (verbose) printf("Made thread %d\n", tid2); + + sleep (1); + + for (j = 1; j <= 10000000; j++) + { + if (verbose) printf("top %d\n", pthread_self ()); + common_routine (0); + sleep(1); + t += j; + } + + exit(0); +} +
pthreads.c Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +Id \ No newline at end of property Index: sigthread.c =================================================================== --- sigthread.c (nonexistent) +++ sigthread.c (revision 816) @@ -0,0 +1,77 @@ +/* Test case for C-c sent to threads with pending signals. Before I + even get there, creating a thread and sending it a signal before it + has a chance to run leads to an internal error in GDB. We need to + record that there's a pending SIGSTOP, so that we'll ignore it + later, and pass the current signal back to the thread. + + The fork/vfork case has similar trouble but that's even harder + to get around. We may need to send a SIGCONT to cancel out the + SIGSTOP. Different kernels may do different things if the thread + is stopped by ptrace and sent a SIGSTOP. */ + +#include +#include +#include +#include +#include + +/* Loop long enough for GDB to send a few signals of its own, but + don't hang around eating CPU forever if something goes wrong during + testing. */ +#define NSIGS 10000000 + +pthread_barrier_t barrier; + +void +handler (int sig) +{ + ; +} + +pthread_t main_thread; +pthread_t child_thread, child_thread_two; + +void * +child_two (void *arg) +{ + int i; + + pthread_barrier_wait (&barrier); + + for (i = 0; i < NSIGS; i++) + pthread_kill (child_thread, SIGUSR1); +} + +void * +thread_function (void *arg) +{ + int i; + + pthread_barrier_wait (&barrier); + + for (i = 0; i < NSIGS; i++) + pthread_kill (child_thread_two, SIGUSR2); +} + +int main() +{ + int i; + + signal (SIGUSR1, handler); + signal (SIGUSR2, handler); + + pthread_barrier_init (&barrier, NULL, 3); + + main_thread = pthread_self (); + pthread_create (&child_thread, NULL, thread_function, NULL); + pthread_create (&child_thread_two, NULL, child_two, NULL); + + pthread_barrier_wait (&barrier); + + for (i = 0; i < NSIGS; i++) + pthread_kill (child_thread_two, SIGUSR1); + + pthread_join (child_thread, NULL); + + exit (0); +}
sigthread.c Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +Id \ No newline at end of property Index: threadapply.c =================================================================== --- threadapply.c (nonexistent) +++ threadapply.c (revision 816) @@ -0,0 +1,81 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2002, 2003, 2004, 2007, 2008, 2009, 2010 + 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 3 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, see . + + This file is copied from schedlock.c. */ + +#include +#include +#include +#include + +void *thread_function(void *arg); /* Pointer to function executed by each thread */ + +#define NUM 5 + +unsigned int args[NUM+1]; + +int main() { + int res; + int all_started; + pthread_t threads[NUM]; + void *thread_result; + long i; + + for (i = 0; i < NUM; i++) + { + args[i] = 1; /* Init value. */ + res = pthread_create(&threads[i], + NULL, + thread_function, + (void *) i); + } + + all_started = 0; + while (!all_started) + { + all_started = 1; + for (i = 0; i < NUM; i++) + { + if (args[i] == 1) + { + all_started = 0; + break; + } + } + } + + args[i] = 1; + /* Break here */ + thread_function ((void *) i); + + exit(EXIT_SUCCESS); +} + +void *thread_function(void *arg) { + int my_number = (long) arg; + int *myp = (int *) &args[my_number]; + + /* Don't run forever. Run just short of it :) */ + while (*myp > 0) + { + (*myp) ++; /* Loop increment. */ + } + + pthread_exit(NULL); +} +
threadapply.c Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +Id \ No newline at end of property Index: thread-execl.exp =================================================================== --- thread-execl.exp (nonexistent) +++ thread-execl.exp (revision 816) @@ -0,0 +1,53 @@ +# Copyright (C) 2009, 2010 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 3 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, see . + +# Test that GDB doesn't get stuck when stepping over an exec call done +# by a thread other than the main thread. + +# There's no support for exec events in the remote protocol. +if { [is_remote target] } { + return 0 +} + +set testfile "thread-execl" +set srcfile ${testfile}.c +set binfile ${objdir}/${subdir}/${testfile} + +if {[gdb_compile_pthreads "${srcdir}/${subdir}/${srcfile}" "${binfile}" \ + executable [list debug "incdir=${objdir}"]] != "" } { + return -1 +} + +# Start with a fresh gdb. + +gdb_exit +gdb_start +gdb_reinitialize_dir $srcdir/$subdir +gdb_load ${binfile} + +runto_main + +# Get ourselves to the thread that execs +gdb_breakpoint "thread_execler" +gdb_test "continue" ".*thread_execler.*" "continue to thread start" + +# Now set a breakpoint at `main', and step over the execl call. The +# breakpoint at main should be reached. GDB should not try to revert +# back to the old thread from the old image and resume stepping it +# (since it is gone). +gdb_breakpoint "main" +gdb_test "next" ".*main.*" "get to main in new image" + +return 0 Index: fork-child-threads.exp =================================================================== --- fork-child-threads.exp (nonexistent) +++ fork-child-threads.exp (revision 816) @@ -0,0 +1,53 @@ +# Copyright (C) 2008, 2009, 2010 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 3 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, see . + +# Only GNU/Linux is known to support `set follow-fork-mode child'. +if { ! [istarget "*-*-linux*"] } { + return 0 +} + +set testfile fork-child-threads +set srcfile ${testfile}.c +set binfile ${objdir}/${subdir}/${testfile} + +if {[gdb_compile_pthreads "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug}] != "" } { + return -1 +} + +gdb_exit +gdb_start +gdb_reinitialize_dir $srcdir/$subdir + +gdb_load ${binfile} +if ![runto_main] then { + fail "Can't run to main" + return 0 +} + +gdb_test "set follow-fork-mode child" +gdb_breakpoint "start" + +# Make sure we can step over fork without losing our breakpoint. +gdb_test "next" ".*pthread_create \\(&thread, NULL, start, NULL\\);.*" "next over fork" + +gdb_test "continue" "Breakpoint 2, start.*" "get to the spawned thread" + +# Wrong: +# * 2 LWP 4466 start (arg=0x0) at fork-child-threads.c:28 +# Correct: +# * 3 Thread 0x40a00950 (LWP 5553) start (arg=0x0) at ../.././gdb/testsuite/gdb.threads/fork-child-threads.c:28 +# 2 Thread 0x2aaaaaac3000 (LWP 5552) 0x00000031674076dd in pthread_join (threadid=, thread_return=) at pthread_join.c:89 + +gdb_test "info threads" " Thread .* Thread .*" "two threads found" Index: print-threads.c =================================================================== --- print-threads.c (nonexistent) +++ print-threads.c (revision 816) @@ -0,0 +1,58 @@ +#include +#include +#include +#include + +void *thread_function(void *arg); /* Pointer to function executed by each thread */ + +int slow = 0; + +#define NUM 5 + +int main() { + int res; + pthread_t threads[NUM]; + void *thread_result; + int args[NUM]; + int i; + + for (i = 0; i < NUM; i++) + { + args[i] = i; + res = pthread_create(&threads[i], NULL, thread_function, (void *)&args[i]); + } + + for (i = 0; i < NUM; i++) + res = pthread_join(threads[i], &thread_result); + + printf ("Done\n"); + + if (slow) + sleep (4); + + exit(EXIT_SUCCESS); +} + +void *thread_function(void *arg) { + int my_number = *(int *)arg; + int rand_num; + + printf ("Print 1, thread %d\n", my_number); + sleep (1); + + if (slow) + { + printf ("Print 2, thread %d\n", my_number); + sleep (1); + printf ("Print 3, thread %d\n", my_number); + sleep (1); + printf ("Print 4, thread %d\n", my_number); + sleep (1); + printf ("Print 5, thread %d\n", my_number); + sleep (1); + } + + printf("Bye from %d\n", my_number); + pthread_exit(NULL); +} +
print-threads.c Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +Id \ No newline at end of property Index: pthread_cond_wait.exp =================================================================== --- pthread_cond_wait.exp (nonexistent) +++ pthread_cond_wait.exp (revision 816) @@ -0,0 +1,73 @@ +# Copyright (C) 2004, 2007, 2008, 2009, 2010 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 3 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, see . + +# Please email any bugs, comments, and/or additions to this file to: +# bug-gdb@gnu.org + +# This file verifies that GDB is able to compute a backtrace for a thread +# being blocked on a call to pthread_cond_wait(). + +if $tracelevel then { + strace $tracelevel +} + +set testfile "pthread_cond_wait" +set srcfile ${testfile}.c +set binfile ${objdir}/${subdir}/${testfile} + +if {[gdb_compile_pthreads "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable [list debug "incdir=${objdir}"]] != "" } { + return -1 +} + +gdb_exit +gdb_start +gdb_reinitialize_dir $srcdir/$subdir +gdb_load ${binfile} +runto_main + +gdb_test "break break_me" \ + "Breakpoint 2 at .*: file .*${srcfile}, line .*" \ + "breakpoint on break_me" + +gdb_test "continue" \ + ".*Breakpoint 2, break_me ().*" \ + "run to break_me" + +# +# Backtrace all threads, find the one running noreturn, and +# verify that we are able to get a sensible backtrace, including +# the frame for the pthread_cond_wait() call. +# +# The string below will only match if the functions named +# occur in a single thread's backtrace, in the given order. +# + +global hex +global decimal + +# +# This is a "backtrace break" ("btb"): +# +set btb "\[^\r\n\]+\[\r\n\]+\#${decimal}\[ \t\]+${hex} in " + +# One of the threads is blocked on a call to pthread_cond_wait, and +# we want to verify that we are able to get a sensible backtrace for +# that thread. Because we don't know its thread ID, we can't switch +# to it before doing the backtrace. So we get a backtrace for all +# threads, and verify that one them returns the expected backtrace. +gdb_test "thread apply all backtrace" \ + "pthread_cond_wait${btb}cond_wait${btb}noreturn${btb}forever_pthread.*" \ + "backtrace in blocked thread" + Index: bp_in_thread.exp =================================================================== --- bp_in_thread.exp (nonexistent) +++ bp_in_thread.exp (revision 816) @@ -0,0 +1,49 @@ +# Copyright (C) 2004, 2007, 2008, 2009, 2010 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 3 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, see . + +# gdb 6.1.1 on AIX had a bug where the aix-threads code called +# getthrds() incorrectly so that gdb lost track of breakpoints. +# GDB reported a SIGTRAP signal in a random thread when hitting +# a breakpoint. + +if $tracelevel then { + strace $tracelevel +} + +set testfile "bp_in_thread" +set srcfile ${testfile}.c +set binfile ${objdir}/${subdir}/${testfile} + +if {[gdb_compile_pthreads "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable [list debug "incdir=${objdir}"]] != "" } { + return -1 +} + +gdb_exit +gdb_start +gdb_reinitialize_dir $srcdir/$subdir +gdb_load ${binfile} +runto_main + +gdb_test "break noreturn" \ + "Breakpoint 2 at .*: file .*${srcfile}, line .*" \ + "breakpoint on noreturn" + +# Run the program and make sure GDB reports that we stopped after +# hitting breakpoint 1 in noreturn(). + +gdb_test "continue" \ + ".*Breakpoint 2, noreturn ().*" \ + "run to noreturn" + Index: attachstop-mt.c =================================================================== --- attachstop-mt.c (nonexistent) +++ attachstop-mt.c (revision 816) @@ -0,0 +1,56 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2008, 2009, 2010 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 3 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, see . */ + +/* This program is intended to be started outside of gdb, then + manually stopped via a signal. */ + +#include +#include +#include +#include + +/* Red Hat BZ PR 197584.c */ + +void *func (void *arg) +{ + sleep (10000); /* Ridiculous time, but we will eventually kill it. */ + sleep (10000); /* RHEL3U8 kernel-2.4.21-47.EL will cut the sleep time. */ + + return NULL; /* thread-sleep */ +} + +int main () +{ + pthread_t t1,t2; + int ret; + + ret = pthread_create (&t1, NULL, func, NULL); + if (ret) + fprintf(stderr, "pthread_create(): %s", strerror (ret)); + ret = pthread_create (&t2, NULL, func, NULL); + if (ret) + fprintf(stderr, "pthread_create(): %s", strerror (ret)); + + ret = pthread_join (t1, NULL); + if (ret) /* first-join */ + fprintf(stderr, "pthread_join(): %s", strerror (ret)); + ret = pthread_join (t2, NULL); + if (ret) + fprintf(stderr, "pthread_join(): %s", strerror (ret)); + + return 0; +}
attachstop-mt.c Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +Id \ No newline at end of property Index: switch-threads.c =================================================================== --- switch-threads.c (nonexistent) +++ switch-threads.c (revision 816) @@ -0,0 +1,44 @@ +/* A minimal multi-threaded test case. + + Copyright 2003, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. + + This file is part of GDB. + + 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 3 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, see . */ + +#include + +void foo (void) +{ +} + +void *thread_func (void *arg) +{ + int x; + for (x = 0; x < 10; x++) + foo (); + return 0; +} + +int main() +{ + pthread_t thr; + void *ret; + int x; + + pthread_create (&thr, NULL, thread_func, NULL); + pthread_join (thr, &ret); + for (x = 0; x < 10; x++) + foo (); +}
switch-threads.c Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +Id \ No newline at end of property Index: hand-call-in-threads.exp =================================================================== --- hand-call-in-threads.exp (nonexistent) +++ hand-call-in-threads.exp (revision 816) @@ -0,0 +1,160 @@ +# Copyright (C) 2004, 2007, 2008, 2010 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 3 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, see . + +# Test making hand function calls in multiple threads. + +set NR_THREADS 4 + +if $tracelevel then { + strace $tracelevel +} + +set testfile "hand-call-in-threads" +set srcfile ${testfile}.c +set binfile ${objdir}/${subdir}/${testfile} + +if {[gdb_compile_pthreads "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable [list debug "incdir=${objdir}" "additional_flags=-DNR_THREADS=$NR_THREADS"]] != "" } { + return -1 +} + +# Some targets can't do function calls, so don't even bother with this +# test. +if [target_info exists gdb,cannot_call_functions] { + setup_xfail "*-*-*" 2416 + fail "This target can not call functions" + continue +} + +proc get_dummy_frame_number { } { + global gdb_prompt + + send_gdb "bt\n" + gdb_expect { + -re "#(\[0-9\]*) *.*$gdb_prompt $" + { + return $expect_out(1,string) + } + -re "$gdb_prompt $" + { + return "" + } + timeout + { + return "" + } + } + return "" +} + +gdb_exit +gdb_start +gdb_reinitialize_dir $srcdir/$subdir +gdb_load ${binfile} + +if { ![runto_main] } { + fail "Can't run to main" + return 0 +} + +gdb_test "break all_threads_running" \ + "Breakpoint 2 at .*: file .*${srcfile}, line .*" \ + "breakpoint on all_threads_running" + +gdb_test "break hand_call" \ + "Breakpoint 3 at .*: file .*${srcfile}, line .*" \ + "breakpoint on hand_call" + +# Run the program and make sure GDB reports that we stopped after +# hitting breakpoint 2 in all_threads_running(). + +gdb_test "continue" \ + ".*Breakpoint 2, all_threads_running ().*" \ + "run to all_threads_running" + +# Before we start making hand function calls, turn on scheduler locking. + +gdb_test "set scheduler-locking on" "" "enable scheduler locking" +gdb_test "show scheduler-locking" ".* locking scheduler .* is \"on\"." "show scheduler locking on" + +# Now hand-call a function in each thread, having the function +# stop without returning. + +# Add one for the main thread. +set total_nr_threads [expr $NR_THREADS + 1] + +# Thread numbering in gdb is origin-1, so begin numbering at 1. +for { set i 1 } { $i <= $total_nr_threads } { incr i } { + set thread_nr $i + gdb_test "thread $thread_nr" "" "prepare to make hand call, thread $thread_nr" + gdb_test "call hand_call()" "Breakpoint 3, .*" "hand call, thread $thread_nr" +} + +# Now have each hand-called function return. + +# Turn confirmation off for the "return" command. +gdb_test "set confirm off" "" + +clear_xfail "*-*-*" + +for { set i 1 } { $i <= $total_nr_threads } { incr i } { + set thread_nr $i + gdb_test "thread $thread_nr" "" "prepare to discard hand call, thread $thread_nr" + set frame_number [get_dummy_frame_number] + if { "$frame_number" == "" } { + fail "dummy stack frame number, thread $thread_nr" + # Need something. + set frame_number 0 + } else { + pass "dummy stack frame number, thread $thread_nr" + } + # Pop the dummy frame. + gdb_test "frame $frame_number" "" "setting frame, thread $thread_nr" + gdb_test "return" "" "discard hand call, thread $thread_nr" + # In case getting the dummy frame number failed, re-enable for next iter. + clear_xfail "*-*-*" +} + +# Make sure all dummy frames got popped. + +gdb_test_multiple "maint print dummy-frames" "all dummies popped" { + -re ".*stack=.*$gdb_prompt $" { + fail "all dummies popped" + } + -re ".*$gdb_prompt $" { + pass "all dummies popped" + } +} + +# Before we resume the full program, turn of scheduler locking. +gdb_test "set scheduler-locking off" "" "disable scheduler locking" +gdb_test "show scheduler-locking" ".* locking scheduler .* is \"off\"." "show scheduler locking off" + +# Continue one last time, the program should exit normally. +# +# ??? This currently doesn't work because gdb doesn't know how to singlestep +# over reported breakpoints that weren't in the last thread to run. +# Commented out until then. +# +# For reference sake ... +# An alternative is to manually work around the issue by manually setting +# the thread back to the first thread: the program is still at the +# all_threads_running breakpoint, which wasn't the last thread to run, +# and gdb doesn't know how to singlestep over reported breakpoints that +# weren't in the last thread to run. +#gdb_test "thread 1" "" "set thread to 1, prepare to resume" +# +#gdb_continue_to_end "hand-call-in-threads" + +return 0 Index: attach-stopped.exp =================================================================== --- attach-stopped.exp (nonexistent) +++ attach-stopped.exp (revision 816) @@ -0,0 +1,158 @@ +# Copyright 2008, 2009, 2010 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 3 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, see . + +# This test was created by modifying attach.exp. +# This file was created by Jeff Johnston . +# This file was updated by Jan Kratochvil . + +# This test only works on Linux +if { ![isnative] || [is_remote host] || ![istarget *-linux*] } { + continue +} + +set testfile "attach-stopped" +set srcfile ${testfile}.c +set binfile ${objdir}/${subdir}/${testfile} +set escapedbinfile [string_to_regexp ${objdir}/${subdir}/${testfile}] + +#execute_anywhere "rm -f ${binfile}" +remote_exec build "rm -f ${binfile}" +# For debugging this test +# +#log_user 1 + +proc corefunc { threadtype } { + global srcfile + global binfile + global escapedbinfile + global srcdir + global subdir + global gdb_prompt + + if [get_compiler_info ${binfile}] { + return -1 + } + + # Start the program running and then wait for a bit, to be sure + # that it can be attached to. + + set testpid [eval exec $binfile &] + + # Avoid some race: + sleep 2 + + # Stop the program + remote_exec build "kill -s STOP ${testpid}" + + # Start with clean gdb + gdb_exit + gdb_start + gdb_reinitialize_dir $srcdir/$subdir + gdb_load ${binfile} + + # Verify that we can attach to the stopped process. + + set test "$threadtype: attach2 to stopped, after setting file" + gdb_test_multiple "attach $testpid" "$test" { + -re "Attaching to program.*`?$escapedbinfile'?, process $testpid.*$gdb_prompt $" { + pass "$test" + } + } + + # ".*sleep.*clone.*" would fail on s390x as bt stops at START_THREAD there. + if {[string equal $threadtype threaded]} { + gdb_test "thread apply all bt" ".*sleep.*start_thread.*" "$threadtype: attach2 to stopped bt" + } else { + gdb_test "bt" ".*sleep.*main.*" "$threadtype: attach2 to stopped bt" + } + # This breakpoint is there for old/non-x86 kernels not restarting syscalls. + gdb_breakpoint [gdb_get_line_number "Second sleep"] + set test "$threadtype: attach2 continue" + send_gdb "continue\n" + gdb_expect { + -re "Continuing" + { pass "continue ($test)" } + timeout + { fail "continue ($test) (timeout)" } + } + + # For this to work we must be sure to consume the "Continuing." + # message first, or GDB's signal handler may not be in place. + after 1000 {send_gdb "\003"} + set test "$threadtype: attach2 stop interrupt" + gdb_expect 10 { + -re "Program received signal SIGINT.*$gdb_prompt $" + { + pass $test + } + -re "Breakpoint \[0-9\].*$srcfile.*$gdb_prompt $" + { + pass $test + } + timeout + { + fail $test + } + } + + gdb_exit + + # Avoid some race: + sleep 2 + + # At this point, the process should be sleeping + + if [catch {open /proc/${testpid}/status r} fileid2] { + set line2 "NOTFOUND" + } else { + gets $fileid2 line1; + gets $fileid2 line2; + close $fileid2; + } + + set test "$threadtype: attach2, exit leaves process sleeping" + if {[string match "*(sleeping)*" $line2]} { + pass $test + } else { + fail $test + } + + # Make sure we don't leave a process around to confuse + # the next test run (and prevent the compile by keeping + # the text file busy), in case the "set should_exit" didn't + # work. + + remote_exec build "kill -9 ${testpid}" +} + +# build the test case first without threads +# +if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug}] != "" } { + untested "attach-stopped.exp (unthreaded)" + return -1 +} + +corefunc nonthreaded + +# build the test case first without threads +# +if { [gdb_compile_pthreads "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug additional_flags=-DUSE_THREADS}] != "" } { + untested "attach-stopped.exp (threaded)" + return -1 +} + +corefunc threaded + +return 0 Index: thread_events.c =================================================================== --- thread_events.c (nonexistent) +++ thread_events.c (revision 816) @@ -0,0 +1,55 @@ +/* Copyright (C) 2007, 2009, 2010 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 3 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, see . + + This file was written by Chris Demetriou (cgd@google.com). */ + +/* Simple test to trigger thread events (thread start, thread exit). */ + +#include +#include +#include + +static void * +threadfunc (void *arg) +{ + printf ("in threadfunc\n"); + return NULL; +} + +static void +after_join_func (void) +{ + printf ("finished\n"); +} + +int main (int argc, char *argv[]) +{ + pthread_t thread; + + if (pthread_create (&thread, NULL, threadfunc, NULL) != 0) + { + printf ("pthread_create failed\n"); + exit (1); + } + + if (pthread_join (thread, NULL) != 0) + { + printf ("pthread_join failed\n"); + exit (1); + } + + after_join_func (); + return 0; +}
thread_events.c Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +Id \ No newline at end of property Index: pending-step.c =================================================================== --- pending-step.c (nonexistent) +++ pending-step.c (revision 816) @@ -0,0 +1,62 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2002, 2003, 2004, 2007, 2008, 2009, 2010 + 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 3 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, see . */ + +#include +#include +#include + +void *thread_function(void *arg); /* Pointer to function executed by each thread */ + +#define NUM 1 + +unsigned int args[NUM+1]; + +int main() { + int res; + pthread_t threads[NUM]; + void *thread_result; + long i; + + for (i = 1; i <= NUM; i++) + { + args[i] = 1; + res = pthread_create(&threads[i - 1], + NULL, + thread_function, + (void *) i); + } + + /* schedlock.exp: last thread start. */ + args[0] = 1; + thread_function ((void *) 0); + + exit(EXIT_SUCCESS); +} + +void *thread_function(void *arg) { + int my_number = (long) arg; + int *myp = (int *) &args[my_number]; + + /* Don't run forever. Run just short of it :) */ + while (*myp > 0) + { + (*myp) ++; /* insert breakpoint here */ + } + + pthread_exit(NULL); +}
pending-step.c Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +Id \ No newline at end of property Index: local-watch-wrong-thread.c =================================================================== --- local-watch-wrong-thread.c (nonexistent) +++ local-watch-wrong-thread.c (revision 816) @@ -0,0 +1,89 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2002, 2003, 2004, 2007, 2008, 2009, 2010 + 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 3 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, see . + +*/ + +#include +#include +#include + +unsigned int args[2]; +int trigger = 0; + +void * +thread_function0 (void *arg) +{ + int my_number = (long) arg; + volatile int *myp = (volatile int *) &args[my_number]; + + while (*myp > 0) + { + (*myp) ++; + usleep (1); /* Loop increment 1. */ + } + + return NULL; +} + +void * +thread_function0_1 (void *arg) +{ + void *ret = thread_function0 (arg); + + return ret; /* set breakpoint here */ +} + +void * +thread_function1 (void *arg) +{ + int my_number = (long) arg; + + volatile int *myp = (volatile int *) &args[my_number]; + + while (*myp > 0) + { + (*myp) ++; + usleep (1); /* Loop increment 2. */ + } + + return NULL; +} + +int +main () +{ + int res; + pthread_t threads[2]; + void *thread_result; + long i = 0; + + args[i] = 1; /* Init value. */ + res = pthread_create (&threads[i], NULL, + thread_function0_1, + (void *) i); + + i++; + args[i] = 1; /* Init value. */ + res = pthread_create(&threads[i], NULL, + thread_function1, + (void *) i); + + pthread_join (threads[0], &thread_result); + pthread_join (threads[1], &thread_result); + exit(EXIT_SUCCESS); +}
local-watch-wrong-thread.c Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +Id \ No newline at end of property Index: tls-nodebug.exp =================================================================== --- tls-nodebug.exp (nonexistent) +++ tls-nodebug.exp (revision 816) @@ -0,0 +1,48 @@ +# tls.exp -- Expect script to test thread-local storage without debuginfo +# Copyright (C) 2006, 2007, 2008, 2009, 2010 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 3 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, see . */ + +set testfile tls-nodebug +set srcfile ${testfile}.c +set binfile ${objdir}/${subdir}/${testfile} + +if [istarget "*-*-linux"] then { + set target_cflags "-D_MIT_POSIX_THREADS" +} else { + set target_cflags "" +} + +if {[gdb_compile_pthreads "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable []] != "" } { + return -1 +} + +gdb_exit +gdb_start +gdb_reinitialize_dir $srcdir/$subdir + +gdb_load ${binfile} +if ![runto_main] then { + fail "Can't run to main" + return 0 +} + +# Formerly: Cannot access memory at address 0x0 +gdb_test "p thread_local" "= 42" "thread local storage" + +# Done! +# +gdb_exit + +return 0 Index: attach-into-signal.exp =================================================================== --- attach-into-signal.exp (nonexistent) +++ attach-into-signal.exp (revision 816) @@ -0,0 +1,169 @@ +# Copyright 2008, 2009, 2010 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 3 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, see . + +# This test was created by modifying attach-stopped.exp. +# This file was created by Jan Kratochvil . + +# This test only works on Linux +if { ![isnative] || [is_remote host] || ![istarget *-linux*] } { + continue +} + +set testfile "attach-into-signal" +set srcfile ${testfile}.c +set binfile ${objdir}/${subdir}/${testfile} +set escapedbinfile [string_to_regexp ${objdir}/${subdir}/${testfile}] + +remote_exec build "rm -f ${binfile}" +# For debugging this test +# +#log_user 1 + +proc corefunc { threadtype } { + global srcfile + global binfile + global escapedbinfile + global srcdir + global subdir + global gdb_prompt + + if [get_compiler_info ${binfile}] { + return -1 + } + + # Start the program running and then wait for a bit, to be sure + # that it can be attached to. + # Statistically there is a better chance without giving process a nice. + + set testpid [eval exec $binfile &] + exec sleep 2 + + # Run 2 passes of the test. + # The C file inferior stops pending its signals if a single one is lost, + # we test successful redelivery of the caught signal by the 2nd pass. + + # linux-2.6.20.4.x86_64 had maximal attempt # 20 in 4 test runs. + set attempts 100 + set attempt 1 + set passes 1 + while { $passes < 3 && $attempt <= $attempts } { + set stoppedtry 0 + while { $stoppedtry < 10 } { + if [catch {open /proc/${testpid}/status r} fileid] { + set stoppedtry 10 + break + } + gets $fileid line1; + gets $fileid line2; + close $fileid; + + if {![string match "*(stopped)*" $line2]} { + # No PASS message as we may be looping in multiple attempts. + break + } + sleep 1 + set stoppedtry [expr $stoppedtry + 1] + } + if { $stoppedtry >= 10 } { + verbose -log $line2 + set test "$threadtype: process is still running on the attempt # $attempt of $attempts" + break + } + + # Main test: + set test "$threadtype: attach (pass $passes), pending signal catch" + if {[gdb_test_multiple "attach $testpid" $test { + -re "Attaching to program.*`?$escapedbinfile'?, process $testpid.*Received Alarm clock.*$gdb_prompt $" { + # nonthreaded: + pass $test + verbose -log "$test succeeded on the attempt # $attempt of $attempts" + set passes [expr $passes + 1] + } + -re "Attaching to program.*`?$escapedbinfile'?, process $testpid.*$gdb_prompt $" { + # nonthreaded: + # We just lack the luck, we should try it again. + set attempt [expr $attempt + 1] + } + -re "Attaching to process $testpid.*Received Alarm clock.*$gdb_prompt $" { + # threaded: + pass $test + verbose -log "$test succeeded on the attempt # $attempt of $attempts" + set passes [expr $passes + 1] + } + -re "Attaching to process $testpid.*$gdb_prompt $" { + # threaded: + # We just lack the luck, we should try it again. + set attempt [expr $attempt - 1] + } + }] != 0 } { + break + } + + gdb_test "detach" "Detaching from.*" "" + } + if {$passes < 3} { + if {$attempt > $attempts} { + unresolved $test + } else { + fail $test + } + } + + # Exit and detach the process. + + gdb_exit + + # Make sure we don't leave a process around to confuse + # the next test run (and prevent the compile by keeping + # the text file busy), in case the "set should_exit" didn't + # work. + + # Continue the program - some Linux kernels need it before -9 if the + # process is stopped. + remote_exec build "kill -s CONT ${testpid}" + + remote_exec build "kill -9 ${testpid}" +} + +# Start with clean gdb +gdb_exit + +# build the test case first without threads +# +if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug}] != "" } { + untested "attach-into-signal.exp (unthreaded)" + return -1 +} + +gdb_start +gdb_reinitialize_dir $srcdir/$subdir +gdb_load ${binfile} +gdb_test "set debug lin-lwp 1" "" "" + +corefunc nonthreaded + +# build the test case also with threads +# +if { [gdb_compile_pthreads "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug additional_flags=-DUSE_THREADS}] != "" } { + untested "attach-into-signal.exp (threaded)" + return -1 +} + +gdb_start +gdb_reinitialize_dir $srcdir/$subdir +gdb_load ${binfile} +gdb_test "set debug lin-lwp 1" "" "" + +corefunc threaded Index: step2.exp =================================================================== --- step2.exp (nonexistent) +++ step2.exp (revision 816) @@ -0,0 +1,147 @@ +# step2.exp -- Expect script to test gdb step.c +# Copyright (C) 1992, 1997, 2007, 2008, 2009, 2010 +# 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 3 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, see . + +# This file was written by Jeff Law. (law@cygnus.com) +# + + +if $tracelevel then { + strace $tracelevel +} + +set program_exited 0 + +# A simple and crude test to see that we can step two threads independently +proc test_multi_threaded_stepping {} { + global gdb_prompt + global hex + global srcfile + global decimal + + # Set breakpoints in code that we know is executed in only + # thread of control. + gdb_test "break thread1" \ + "Break.* at $hex: file .*$srcfile, line $decimal\\." + gdb_test "break thread2" \ + "Break.* at $hex: file .*$srcfile, line $decimal\\." + + # the order in which things happen is indeterminate. So we basically + # look for a set of events and note that each one happens and that + # all of the required events have happened when we're done. + # + # Right now we only verify that both threads start and that they + # both call pthread_cond_wait twice. + set thread1started 0 + set thread1condwait 0 + set thread2started 0 + set thread2condwait 0 + + send_gdb "run\n" + gdb_expect { + -re "The program .* has been started already.*y or n. $" { + send_gdb "y\n" + exp_continue + } + -re ".*Breakpoint \[0-9\]+,.*thread1.* at .*$srcfile:.*\[\t \].*$gdb_prompt $" { + if { $thread1started != 0 } then { + fail "thread1 started" + return + } else { + set thread1started 1 + pass "thread1 started" + } + send_gdb "step\n" + exp_continue + } + -re ".*Breakpoint \[0-9\]+,.*thread2.* at .*$srcfile:.*\[\t \].*$gdb_prompt $" { + if { $thread2started != 0 } then { + fail "thread2 started" + return + } else { + set thread2started 1 + pass "thread2 started" + } + send_gdb "step\n" + exp_continue + } + -re ".*pthread_cond_wait.*cv_a.*$gdb_prompt" { + if { $thread1started == 0 } then { + fail "thread1 condwait" + return + } + if { $thread1condwait < 2 } then { + pass "thread1 condwait" + incr thread1condwait + } + if { $thread2condwait == 2 } then { + pass "multi threaded stepping" + return + } + send_gdb "step\n" + exp_continue + } + + -re ".*pthread_cond_wait.*cv_b.*$gdb_prompt" { + if { $thread2started == 0 } then { + fail "thread2 condwait" + return + } + if { $thread2condwait < 2 } then { + pass "thread2 condwait" + incr thread2condwait + } + if { $thread1condwait == 2 } then { + pass "multi threaded stepping" + return + } + send_gdb "step\n" + exp_continue + } + + -re "$gdb_prompt" { + send_gdb "step\n" + exp_continue + } + default { fail "multi threaded stepping" } + } +} + +# Check to see if we have an executable to test. If not, then either we +# haven't tried to compile one, or the compilation failed for some reason. +# In either case, just notify the user and skip the tests in this file. + +set binfile "step" +set srcfile "step.c" + +if ![file exists $objdir/$subdir/$binfile] then { + if $all_flag then { + warning "$binfile does not exist; tests suppressed." + } + return +} + +set prms_id 0 +set bug_id 0 + +# Start with a fresh gdb. + +gdb_exit +gdb_start +gdb_reinitialize_dir $srcdir/$subdir +gdb_load $objdir/$subdir/$binfile + +test_multi_threaded_stepping Index: fork-child-threads.c =================================================================== --- fork-child-threads.c (nonexistent) +++ fork-child-threads.c (revision 816) @@ -0,0 +1,50 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2008, 2009, 2010 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 3 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, see . */ + +#include +#include +#include + +static void * +start (void *arg) +{ + assert (0); + return arg; +} + +int main(void) +{ + pthread_t thread; + int i; + + switch (fork ()) + { + case -1: + assert (0); + default: + break; + case 0: + i = pthread_create (&thread, NULL, start, NULL); + assert (i == 0); + i = pthread_join (thread, NULL); + assert (i == 0); + + assert (0); + } + + return 0; +}
fork-child-threads.c Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +Id \ No newline at end of property Index: execl.exp =================================================================== --- execl.exp (nonexistent) +++ execl.exp (revision 816) @@ -0,0 +1,75 @@ +# Copyright (C) 2008, 2009, 2010 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 3 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, see . + +# Test handling of threads across an execl. + + +# Original image, loads a thread library. +set testfile "execl" +set srcfile ${testfile}.c +set binfile ${objdir}/${subdir}/${testfile} + +if {[gdb_compile_pthreads "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug}] != "" } { + return -1 +} + +# New image, that does not load a thread library. +set testfile1 "execl1" +set srcfile1 ${testfile1}.c +set binfile1 ${objdir}/${subdir}/${testfile1} + +if {[gdb_compile "${srcdir}/${subdir}/${srcfile1}" "${binfile1}" executable {debug}] != "" } { + return -1 +} + +gdb_exit +gdb_start +gdb_reinitialize_dir $srcdir/$subdir +gdb_load ${binfile} + +runto_main + +gdb_test "b [gdb_get_line_number "breakpoint here"]" \ + ".*Breakpoint .*execl.*" "set breakpoint at execl" + +gdb_test "continue" ".*breakpoint here.*" "continue to exec" + +gdb_test "info threads" ".*3 Thread.*2 Thread.*1 Thread.*" "info threads before exec" + +# When continuing from this point we'll hit the breakpoint in main() +# again, this time in the exec'd process. +gdb_test "continue" ".*Breakpoint 1, main.*" \ + "continue across exec" + +gdb_test "info threads" ".*" "info threads after exec" + +set test "info threads after exec" +gdb_test_multiple "info threads" "$test" { + -re "2 Thread .*$gdb_prompt $" { + # Old threads left behind. + fail "$test" + } + -re "4 Thread .*$gdb_prompt $" { + # New threads registered. + fail "$test" + } + -re "$gdb_prompt $" { + # Target doesn't register the main thread, pass for now. + pass "$test" + } +} + +gdb_test "continue" ".*Program exited normally\\." \ + "continue to end" Index: current-lwp-dead.c =================================================================== --- current-lwp-dead.c (nonexistent) +++ current-lwp-dead.c (revision 816) @@ -0,0 +1,88 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2009, 2010 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 3 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, see . + + Do not use threads as we need to exploit a bug in LWP code masked by the + threads code otherwise. + + INFERIOR_PTID must point to exited LWP. Here we use the initial LWP as it + is automatically INFERIOR_PTID for GDB. + + Finally we need to call target_resume (RESUME_ALL, ...) which we invoke by + NEW_THREAD_EVENT (called from the new LWP as initial LWP is exited now). */ + +#define _GNU_SOURCE +#include +#include +#include +#include + +#include +#ifdef __UCLIBC__ +#if !(defined(__UCLIBC_HAS_MMU__) || defined(__ARCH_HAS_MMU__)) +#define HAS_NOMMU +#endif +#endif + +#define STACK_SIZE 0x1000 + +static int +fn_return (void *unused) +{ + return 0; /* at-fn_return */ +} + +static int +fn (void *unused) +{ + int i; + unsigned char *stack; + int new_pid; + + i = sleep (1); + assert (i == 0); + + stack = malloc (STACK_SIZE); + assert (stack != NULL); + + new_pid = clone (fn_return, stack + STACK_SIZE, CLONE_FILES +#if defined(__UCLIBC__) && defined(HAS_NOMMU) + | CLONE_VM +#endif /* defined(__UCLIBC__) && defined(HAS_NOMMU) */ + , NULL, NULL, NULL, NULL); + assert (new_pid > 0); + + return 0; +} + +int +main (int argc, char **argv) +{ + unsigned char *stack; + int new_pid; + + stack = malloc (STACK_SIZE); + assert (stack != NULL); + + new_pid = clone (fn, stack + STACK_SIZE, CLONE_FILES +#if defined(__UCLIBC__) && defined(HAS_NOMMU) + | CLONE_VM +#endif /* defined(__UCLIBC__) && defined(HAS_NOMMU) */ + , NULL, NULL, NULL, NULL); + assert (new_pid > 0); + + return 0; +}
current-lwp-dead.c Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +Id \ No newline at end of property Index: gcore-thread.exp =================================================================== --- gcore-thread.exp (nonexistent) +++ gcore-thread.exp (revision 816) @@ -0,0 +1,178 @@ +# Copyright 2002, 2003, 2004, 2007, 2008, 2009, 2010 +# 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 3 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, see . + +# This file was written by Michael Snyder (msnyder@redhat.com) +# This is a test for the gdb command "generate-core-file". + +if $tracelevel then { + strace $tracelevel +} + +set prms_id 0 +set bug_id 0 + +# Single-threaded test case +set testfile "pthreads" +set srcfile ${testfile}.c +set binfile ${objdir}/${subdir}/gcore-${testfile} + +if [istarget "*-*-linux"] then { + set target_cflags "-D_MIT_POSIX_THREADS" +} else { + set target_cflags "" +} + +if {[gdb_compile_pthreads "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable [list debug "incdir=${objdir}"]] != "" } { + return -1 +} + +# Now we can proceed with the real testing. + +# Start with a fresh gdb. + +gdb_exit +gdb_start +gdb_reinitialize_dir $srcdir/$subdir +gdb_load ${binfile} + +# regexp for "horizontal" text (i.e. doesn't include newline or +# carriage return) +set horiz "\[^\n\r\]*" + +# regexp for newline +set nl "\[\r\n\]+" + +set prev_timeout $timeout +set timeout 30 + +send_gdb "help gcore\n" +gdb_expect { + -re "Undefined command: .gcore.*$gdb_prompt $" { + # gcore command not supported -- nothing to test here. + unsupported "gdb does not support gcore on this target" + return -1; + } + -re "Save a core file .*$gdb_prompt $" { + pass "help gcore" + } + -re ".*$gdb_prompt $" { + fail "help gcore" + } + timeout { + fail "help gcore (timeout)" + } +} + +if { ! [ runto_main ] } then { + untested gcore-thread.exp + return -1 +} + +send_gdb "info threads\n" +gdb_expect { + -re ".* main .*$gdb_prompt $" { + # OK, threads are supported. + } + -re "${nl}$gdb_prompt $" { + unsupported "gdb does not support threads on this target" + return -1; + } +} + +# Make sure thread 1 is running +delete_breakpoints +gdb_breakpoint "thread1" +gdb_test "continue" "Continuing.*Breakpoint.* thread1 .*" "thread 1 is running" + +# Make sure thread 2 is running +delete_breakpoints +gdb_breakpoint "thread2" +gdb_test "continue" "Continuing.*Breakpoint.* thread2 .*" "thread 2 is running" + +set escapedfilename [string_to_regexp ${objdir}/${subdir}/gcore.test] +# Drop corefile +gdb_test_multiple "gcore ${objdir}/${subdir}/gcore.test" \ + "save a corefile" \ +{ + -re "Saved corefile ${escapedfilename}\[\r\n\]+$gdb_prompt $" { + pass "save a corefile" + global core_supported + set core_supported 1 + } + -re "Can't create a corefile\[\r\n\]+$gdb_prompt $" { + unsupported "save a corefile" + global core_supported + set core_supported 0 + } +} + +global core_supported +if {!$core_supported} { + return -1 +} + +# Now restart gdb and load the corefile. +gdb_exit +gdb_start +gdb_reinitialize_dir $srcdir/$subdir +gdb_load ${binfile} + +send_gdb "core ${objdir}/${subdir}/gcore.test\n" +gdb_expect { + -re ".* is not a core dump:.*$gdb_prompt $" { + fail "re-load generated corefile (bad file format)" + # No use proceeding from here. + return; + } + -re ".*: No such file or directory.*$gdb_prompt $" { + fail "re-load generated corefile (file not found)" + # No use proceeding from here. + return; + } + -re ".*Couldn't find .* registers in core file.*$gdb_prompt $" { + fail "re-load generated corefile (incomplete note section)" + } + -re "Core was generated by .*$gdb_prompt $" { + pass "re-load generated corefile" + } + -re ".*$gdb_prompt $" { + fail "re-load generated corefile" + } + timeout { + fail "re-load generated corefile (timeout)" + } +} + +# FIXME: now what can we test about the thread state? +# We do not know for certain that there should be at least +# three threads, because who knows what kind of many-to-one +# mapping various OS's may do? Let's assume that there must +# be at least two threads: + +gdb_test "info threads" ".*${nl} 2 ${horiz}${nl}\\* 1 .*" \ + "corefile contains at least two threads" + +# One thread in the corefile should be in the "thread2" function. + +gdb_test "info threads" ".* thread2 .*" \ + "a corefile thread is executing thread2" + +# The thread2 thread should be marked as the current thread. + +gdb_test "info threads" ".*${nl}\\* ${horiz} thread2 .*" \ + "thread2 is current thread in corefile" + +set timeout $prev_timeout Index: bp_in_thread.c =================================================================== --- bp_in_thread.c (nonexistent) +++ bp_in_thread.c (revision 816) @@ -0,0 +1,73 @@ +/* A small multi-threaded test case. + + Copyright 2004, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. + + This file is part of GDB. + + 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 3 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, see . */ + +#include +#include +#include + +void +cond_wait (pthread_cond_t *cond, pthread_mutex_t *mut) +{ + pthread_mutex_lock(mut); + pthread_cond_wait (cond, mut); + pthread_mutex_unlock (mut); +} + +void +noreturn (void) +{ + pthread_mutex_t mut; + pthread_cond_t cond; + + pthread_mutex_init (&mut, NULL); + pthread_cond_init (&cond, NULL); + + /* Wait for a condition that will never be signaled, so we effectively + block the thread here. */ + cond_wait (&cond, &mut); +} + +void * +forever_pthread (void *unused) +{ + noreturn (); +} + +void +break_me (void) +{ + /* Just an anchor to help putting a breakpoint. */ +} + +int +main (void) +{ + pthread_t forever; + const struct timespec ts = { 0, 10000000 }; /* 0.01 sec */ + + pthread_create (&forever, NULL, forever_pthread, NULL); + for (;;) + { + nanosleep (&ts, NULL); + break_me(); + } + + return 0; +} +
bp_in_thread.c Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +Id \ No newline at end of property Index: pthread_cond_wait.c =================================================================== --- pthread_cond_wait.c (nonexistent) +++ pthread_cond_wait.c (revision 816) @@ -0,0 +1,73 @@ +/* A small multi-threaded test case. + + Copyright 2004, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. + + This file is part of GDB. + + 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 3 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, see . */ + +#include +#include +#include + +void +cond_wait (pthread_cond_t *cond, pthread_mutex_t *mut) +{ + pthread_mutex_lock(mut); + pthread_cond_wait (cond, mut); + pthread_mutex_unlock (mut); +} + +void +noreturn (void) +{ + pthread_mutex_t mut; + pthread_cond_t cond; + + pthread_mutex_init (&mut, NULL); + pthread_cond_init (&cond, NULL); + + /* Wait for a condition that will never be signaled, so we effectively + block the thread here. */ + cond_wait (&cond, &mut); +} + +void * +forever_pthread (void *unused) +{ + noreturn (); +} + +void +break_me (void) +{ + /* Just an anchor to help putting a breakpoint. */ +} + +int +main (void) +{ + pthread_t forever; + const struct timespec ts = { 0, 10000000 }; /* 0.01 sec */ + + pthread_create (&forever, NULL, forever_pthread, NULL); + for (;;) + { + nanosleep (&ts, NULL); + break_me(); + } + + return 0; +} +
pthread_cond_wait.c Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +Id \ No newline at end of property Index: tls-shared.exp =================================================================== --- tls-shared.exp (nonexistent) +++ tls-shared.exp (revision 816) @@ -0,0 +1,111 @@ +# Copyright 2003, 2007, 2008, 2009, 2010 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 3 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, see . */ + +# tls-shared.exp -- Expect script to test thread local storage in gdb, with +# shared libraries. + +if $tracelevel then { + strace $tracelevel +} + +set testfile tls-main +set libfile tls-shared +set srcfile ${testfile}.c +set binfile ${objdir}/${subdir}/${testfile} + +remote_exec build "rm -f ${binfile}" + +# get the value of gcc_compiled +if [get_compiler_info ${binfile}] { + return -1 +} + +if { [gdb_compile_pthreads "${srcdir}/${subdir}/${srcfile}" "${binfile}.o" object {debug}] != "" } { + return -1 +} + +# Build the shared libraries this test case needs. +# + +if {$gcc_compiled == 0} { + if [istarget "hppa*-hp-hpux*"] then { + set additional_flags "additional_flags=+z" + } elseif { [istarget "mips-sgi-irix*"] } { + # Disable SGI compiler's implicit -Dsgi + set additional_flags "additional_flags=-Usgi" + } else { + # don't know what the compiler is... + set additional_flags "" + } +} else { + if { ([istarget "powerpc*-*-aix*"] + || [istarget "rs6000*-*-aix*"]) } { + set additional_flags "" + } else { + set additional_flags "additional_flags=-fpic" + } +} + +set additional_flags "$additional_flags -shared" +if {[gdb_compile_pthreads "${srcdir}/${subdir}/${libfile}.c" "${objdir}/${subdir}/${libfile}.so" executable [list debug $additional_flags "incdir=${objdir}"]] != ""} { + return -1 +} + +if { ($gcc_compiled +&& ([istarget "powerpc*-*-aix*"] +|| [istarget "rs6000*-*-aix*"] )) } { + set additional_flags "additional_flags=-L${objdir}/${subdir}" +} elseif { [istarget "mips-sgi-irix*"] } { + set additional_flags "additional_flags=-rpath ${objdir}/${subdir}" +} else { + set additional_flags "" +} + +if {[gdb_compile_pthreads "${objdir}/${subdir}/${testfile}.o ${objdir}/${subdir}/${libfile}.so" "${binfile}" executable [list debug $additional_flags]] != ""} { + return -1 +} + + +gdb_exit +gdb_start +gdb_reinitialize_dir $srcdir/$subdir +gdb_load ${binfile} + +if ![runto_main] then { + fail "Can't run to main" + return 0 +} + +gdb_test "print i_tls" "2" "print thread local storage variable" + +gdb_test "ptype i_tls" "int" "ptype of thread local storage variable" + +gdb_test "info address i_tls" \ + "Symbol \\\"i_tls\\\" is a thread-local variable at offset 0x0 in the thread-local storage for .*tls-main.." \ + "print storage info for thread local storage variable" + +set line_number [gdb_get_line_number "break here to check result"] + +gdb_test "break $line_number" \ + "Breakpoint.*at.*file.*tls-main.c.*line ${line_number}." \ + "break at and of main" +gdb_test "continue" \ + "main .* at .*:.*return 0.*break here to check result.*" \ + "continue to break" +# This is more of a gcc/glibc test, really. +# +gdb_test "print result" "3" "print result" + + Index: attach-stopped.c =================================================================== --- attach-stopped.c (nonexistent) +++ attach-stopped.c (revision 816) @@ -0,0 +1,50 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2008, 2009, 2010 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 3 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, see . */ + +/* This program is intended to be started outside of gdb, then + manually stopped via a signal. */ + +#include +#include +#ifdef USE_THREADS +#include +#endif + +static void *func (void *arg) +{ + sleep (10000); /* Ridiculous time, but we will eventually kill it. */ + sleep (10000); /* Second sleep. */ + return NULL; +} + +int main () +{ + +#ifndef USE_THREADS + + func (NULL); + +#else + + pthread_t th; + pthread_create (&th, NULL, func, NULL); + pthread_join (th, NULL); + +#endif + + return 0; +}
attach-stopped.c Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +Id \ No newline at end of property Index: attach-into-signal.c =================================================================== --- attach-into-signal.c (nonexistent) +++ attach-into-signal.c (revision 816) @@ -0,0 +1,67 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2008, 2009, 2010 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 3 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, see . */ + +#include +#include +#include +#include +#include +#ifdef USE_THREADS +#include +#endif + +void action(int sig, siginfo_t * info, void *uc) +{ + raise (SIGALRM); +} + +static void *func (void *arg) +{ + struct sigaction act; + + memset (&act, 0, sizeof(struct sigaction)); + act.sa_sigaction = action; + act.sa_flags = SA_RESTART; + sigaction (SIGALRM, &act, 0); + + raise (SIGALRM); + + /* We must not get past this point, either in a free standing or debugged + state. */ + + abort (); + /* NOTREACHED */ + return NULL; +} + +int main () +{ + +#ifndef USE_THREADS + + func (NULL); + +#else + + pthread_t th; + pthread_create (&th, NULL, func, NULL); + pthread_join (th, NULL); + +#endif + + return 0; +}
attach-into-signal.c Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +Id \ No newline at end of property Index: threadapply.exp =================================================================== --- threadapply.exp (nonexistent) +++ threadapply.exp (revision 816) @@ -0,0 +1,76 @@ +# This testcase is part of GDB, the GNU debugger. + +# Copyright 2004, 2007, 2008, 2009, 2010 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 3 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, see . + +if $tracelevel { + strace $tracelevel +} + +set prms_id 0 +set bug_id 0 + +# This test verifies that a macro using backtrace can be applied to all threads +# and will continue for each thread even though an error may occur in +# backtracing one of the threads. + +set testfile "threadapply" +set srcfile ${testfile}.c +set binfile ${objdir}/${subdir}/${testfile} +if {[gdb_compile_pthreads "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable [list debug "incdir=${objdir}"]] != "" } { + return -1 +} + +gdb_exit +gdb_start +gdb_reinitialize_dir $srcdir/$subdir +gdb_load ${binfile} + +# +# Run to `main' where we begin our tests. +# + +if ![runto_main] then { + gdb_suppress_tests +} + +# Break after all threads have been started. +set break_line [gdb_get_line_number "Break here"] +gdb_test "b $break_line" "" +gdb_test "continue" + +gdb_test_multiple "define backthread" "defining macro" { + -re "Type commands for definition of \"backthread\".\r\nEnd with a line saying just \"end\".\r\n>$" { + gdb_test_multiple "bt\np/x 20\nend" "macro details" { + -re "$gdb_prompt $" { + pass "macro details" + } + } + pass "defining macro" + } +} + +# Cause backtraces to fail by setting a limit. This allows us to +# verify that the macro can get past the backtrace error and perform +# subsequent commands. +gdb_test "set backtrace limit 3" "" +gdb_test "thread apply all backthread" "Thread ..*\\\$\[0-9]+ = 0x14.*Thread ..*\\\$\[0-9]+ = 0x14.*Thread ..*\\\$\[0-9]+ = 0x14.*Thread ..*\\\$\[0-9]+ = 0x14.*Thread ..*\\\$\[0-9]+ = 0x14.*Thread ..*\\\$\[0-9]+ = 0x14" + +# Go into the thread_function to check that a simple "thread apply" +# does not change the selected frame. +gdb_test "step" "thread_function.*" "step to the thread_function" +gdb_test "up" ".*in main.*" "go up in the stack frame" +gdb_test "thread apply all print 1" "Thread ..*\\\$\[0-9]+ = 1.*Thread ..*\\\$\[0-9]+ = 1.*Thread ..*\\\$\[0-9]+ = 1.*Thread ..*\\\$\[0-9]+ = 1.*Thread ..*\\\$\[0-9]+ = 1.*Thread ..*\\\$\[0-9]+ = 1" "run a simple print command on all threads" +gdb_test "down" "#0.*thread_function.*" "go down and check selected frame" Index: execl.c =================================================================== --- execl.c (nonexistent) +++ execl.c (revision 816) @@ -0,0 +1,56 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2008, 2009, 2010 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 3 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, see . +*/ + +/* Test handling thread control across an execl. */ + +/* The original image loads a thread library and has several threads, + while the new image does not load a thread library. */ + +#include +#include +#include +#include +#include + +void * +thread_function (void *arg) +{ + while (1) + sleep (100); + return NULL; +} + +int +main (int argc, char* argv[]) +{ + pthread_t thread1; + pthread_t thread2; + char *new_image; + + pthread_create (&thread1, NULL, thread_function, NULL); + pthread_create (&thread2, NULL, thread_function, NULL); + + new_image = malloc (strlen (argv[0]) + 2); + strcpy (new_image, argv[0]); + strcat (new_image, "1"); + + if (execl (new_image, new_image, NULL) == -1) /* set breakpoint here */ + return 1; + + return 0; +}
execl.c Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +Id \ No newline at end of property Index: fork-thread-pending.exp =================================================================== --- fork-thread-pending.exp (nonexistent) +++ fork-thread-pending.exp (revision 816) @@ -0,0 +1,128 @@ +# Copyright (C) 2009, 2010 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 3 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, see . + +# There's no support for `set follow-fork-mode' in the remote +# protocol. +if { [is_remote target] } { + return 0 +} + +# Only GNU/Linux is known to support `set follow-fork-mode child'. +# +if { ! [istarget "*-*-linux*"] } { + return 0 +} + +set testfile fork-thread-pending +set srcfile ${testfile}.c +set binfile ${objdir}/${subdir}/${testfile} + +if {[gdb_compile_pthreads "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug}] != "" } { + return -1 +} + +gdb_exit +gdb_start +gdb_reinitialize_dir $srcdir/$subdir + +gdb_load ${binfile} +if ![runto_main] then { + fail "Can't run to main" + return 0 +} + +gdb_test "set follow-fork-mode child" "" "1, set follow-fork-mode child" +gdb_test "catch fork" "Catchpoint \[0-9\]* \\(fork\\)" "1, insert fork catchpoint" +gdb_breakpoint "start" "" "1, set breakpoint at start" + +gdb_test "continue" "Catchpoint.*" "1, get to the fork event" + +gdb_test "info threads" " Thread .* Thread .* Thread .* Thread .*" "1, multiple threads found" + +gdb_test "thread 2" "" "1, switched away from event thread" + +gdb_test "continue" "Not resuming.*" "1, refused to resume" + +set test "1, followed to the child, found one thread" +gdb_test_multiple "info threads" "metest" { + -re " Thread .* Thread .*$gdb_prompt $" { + fail "$test" + } + -re " Thread .*$gdb_prompt $" { + pass "$test" + } + -re "$gdb_prompt $" { + fail "$test (unknown output)" + } + timeout { + fail "$test (timeout)" + } +} + +gdb_test "continue" "Breakpoint 3, start.*" "1, get to the spawned thread in fork child" + +set test "1, followed to the child, found two threads" +gdb_test_multiple "info threads" "$test" { + -re " Thread .* Thread .* Thread .*$gdb_prompt $" { + fail "$test" + } + -re " Thread .* Thread .*$gdb_prompt $" { + pass "$test" + } + -re "$gdb_prompt $" { + fail "$test (unknown output)" + } + timeout { + fail "$test (timeout)" + } +} + +# Start over, but this time, don't switch away from the fork event thread. + +gdb_exit +gdb_start +gdb_reinitialize_dir $srcdir/$subdir + +gdb_load ${binfile} +if ![runto_main] then { + fail "Can't run to main" + return 0 +} + +gdb_test "set follow-fork-mode child" "" "2, set follow-fork-mode child" +gdb_test "catch fork" "Catchpoint \[0-9\]* \\(fork\\)" "2, insert fork catchpoint" +gdb_breakpoint "start" + +gdb_test "continue" "Catchpoint.*" "2, get to the fork event" + +gdb_test "info threads" " Thread .* Thread .* Thread .* Thread .*" "2, multiple threads found" + +gdb_test "continue" "Breakpoint 3, start.*" "2, get to the spawned thread in fork child" + +set test "2, followed to the child, found two threads" +gdb_test_multiple "info threads" "$test" { + -re " Thread .* Thread .* Thread .*$gdb_prompt $" { + fail "$test" + } + -re " Thread .* Thread .*$gdb_prompt $" { + pass "$test" + } + -re "$gdb_prompt $" { + fail "$test (unknown output)" + } + timeout { + fail "$test (timeout)" + } +} Index: watchthreads2.c =================================================================== --- watchthreads2.c (nonexistent) +++ watchthreads2.c (revision 816) @@ -0,0 +1,115 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2009, 2010 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 3 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, see . + + Check that watchpoints get propagated to all existing threads when the + watchpoint is created. +*/ + +#include +#include +#include +#include +#include + +#ifndef NR_THREADS +#define NR_THREADS 4 +#endif + +#ifndef X_INCR_COUNT +#define X_INCR_COUNT 10 +#endif + +void *thread_function (void *arg); /* Function executed by each thread. */ + +pthread_mutex_t x_mutex; +int x; + +/* Used to hold threads back until watchthreads2.exp is ready. */ +int test_ready = 0; + +int +main () +{ + int res; + pthread_t threads[NR_THREADS]; + int i; + + pthread_mutex_init (&x_mutex, NULL); + + for (i = 0; i < NR_THREADS; ++i) + { + res = pthread_create (&threads[i], + NULL, + thread_function, + (void *) (intptr_t) i); + if (res != 0) + { + fprintf (stderr, "error in thread %d create\n", i); + abort (); + } + } + + for (i = 0; i < NR_THREADS; ++i) + { + res = pthread_join (threads[i], NULL); + if (res != 0) + { + fprintf (stderr, "error in thread %d join\n", i); + abort (); + } + } + + exit (EXIT_SUCCESS); +} + +/* Easy place for a breakpoint. + watchthreads2.exp uses this to track when all threads are running + instead of, for example, the program keeping track + because we don't need the program to know when all threads are running, + instead we need gdb to know when all threads are running. + There is a delay between when a thread has started and when the thread + has been registered with gdb. */ + +void +thread_started () +{ +} + +void * +thread_function (void *arg) +{ + int i; + + thread_started (); + + /* Don't start incrementing X until watchthreads2.exp is ready. */ + while (! test_ready) + usleep (1); + + for (i = 0; i < X_INCR_COUNT; ++i) + { + pthread_mutex_lock (&x_mutex); + /* For debugging. */ + printf ("Thread %ld changing x %d -> %d\n", (long) arg, x, x + 1); + /* The call to usleep is so that when the watchpoint triggers, + the pc is still on the same line. */ + ++x; usleep (1); /* X increment. */ + pthread_mutex_unlock (&x_mutex); + } + + pthread_exit (NULL); +}
watchthreads2.c Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +Id \ No newline at end of property Index: switch-threads.exp =================================================================== --- switch-threads.exp (nonexistent) +++ switch-threads.exp (revision 816) @@ -0,0 +1,48 @@ +# Copyright (C) 2003, 2007, 2008, 2009, 2010 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 3 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, see . + +# This file was written by Daniel Jacobowitz . +# +# It tests that the correct thread is single-stepped. Prior to the +# introduction of vCont, we didn't pass enough information to remote +# multi-threaded stubs to reliably get this correct; gdbserver defaulted +# to the first thread. + +# TODO: we should also test explicitly changing threads with the "thread" +# command. + +if $tracelevel then { + strace $tracelevel +} + +set testfile "switch-threads" +set srcfile ${testfile}.c +set binfile ${objdir}/${subdir}/${testfile} + +if {[gdb_compile_pthreads "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable [list debug "incdir=${objdir}"]] != "" } { + return -1 +} + +gdb_exit +gdb_start +gdb_reinitialize_dir $srcdir/$subdir +gdb_load ${binfile} + +runto_main + +gdb_breakpoint thread_func +gdb_continue_to_breakpoint "continue to thread_func" +gdb_test "next" ".*foo \\(\\);" + Index: thread-specific.exp =================================================================== --- thread-specific.exp (nonexistent) +++ thread-specific.exp (revision 816) @@ -0,0 +1,114 @@ +# Copyright 2004, 2007, 2008, 2009, 2010 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 3 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, see . + +# This file was written by Daniel Jacobowitz . +# It tests that the correct breakpoint is reported when we hit a +# thread-specific breakpoint inserted for several threads. + +if $tracelevel then { + strace $tracelevel +} + +set prms_id 0 +set bug_id 0 + +set testfile "thread-specific" +set srcfile ${testfile}.c +set binfile ${objdir}/${subdir}/${testfile} + +if {[gdb_compile_pthreads "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable [list debug "incdir=${objdir}"]] != "" } { + return -1 +} + +# Return a list of the valid thread IDs, with the initial thread first. +proc get_thread_list { } { + global gdb_prompt + global expect_out + + set thr_list "" + + gdb_test_multiple "info threads" "get threads list" { + -re "info threads\r\n" { + exp_continue + } + -re "New Thread \[^\n\]*\n" { + exp_continue + } + -re "^\\* *(\[0-9\]*) Thread \[^\n\]*main\[^\n\]*\n" { + set thr_list "$expect_out(1,string) $thr_list" + exp_continue + } + -re "^ *(\[0-9\]*) Thread \[^\n\]*\n" { + lappend thr_list $expect_out(1,string) + exp_continue + } + -re ".*$gdb_prompt $" { + if { [llength $thr_list] != 0 } { + pass "get threads list" + } else { + fail "get threads list (no threads)" + } + } + } + + return $thr_list +} + +# Start with a fresh gdb. + +gdb_exit +gdb_start +gdb_reinitialize_dir $srcdir/$subdir + +gdb_load ${binfile} + +gdb_test "set print sevenbit-strings" "" +gdb_test "set width 0" "" + +runto_main + +gdb_breakpoint [gdb_get_line_number "thread-specific.exp: last thread start"] +gdb_continue_to_breakpoint "all threads started" + +set line [gdb_get_line_number "thread-specific.exp: thread loop"] +set threads [get_thread_list] + +if {[llength $threads] == 0} { + # We have already issued a FAIL above. + return 1 +} + +gdb_test_multiple "break $line thread [lindex $threads 0]" \ + "breakpoint $line main thread" { + -re "Breakpoint (\[0-9\]*) at.* file .*$srcfile, line.*$gdb_prompt $" { + set main_breakpoint $expect_out(1,string) + pass "breakpoint $line main thread" + } +} + +foreach thread [lrange $threads 1 end] { + gdb_breakpoint "$line thread $thread" +} + +gdb_test_multiple "continue" "continue to thread-specific breakpoint" { + -re "Breakpoint $main_breakpoint, .* at .*\r\n$gdb_prompt $" { + fail "continue to thread-specific breakpoint (wrong breakpoint)" + } + -re "Breakpoint .* at .*\r\n$gdb_prompt $" { + pass "continue to thread-specific breakpoint" + } +} + +return 0 Index: thread_events.exp =================================================================== --- thread_events.exp (nonexistent) +++ thread_events.exp (revision 816) @@ -0,0 +1,152 @@ +# Copyright (C) 2007, 2009, 2010 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 3 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, see . + +# This file was written by Chris Demetriou (cgd@google.com). +# It tests printing of thread event (start, exit) information, and +# disabling of those messages. +# +# Note: the format of thread event messages (and also whether or not +# messages are printed and can be disabled) is dependent on the target +# thread support code. + +# This test has only been verified with Linux targets, and would need +# to be generalized to support other targets +if ![istarget *-*-linux*] then { + return +} + +# When using gdbserver, even on Linux, we don't get notifications +# about new threads. This is expected, so don't test for that. +if [is_remote target] then { + return +} + +if $tracelevel then { + strace $tracelevel +} + +set prms_id 0 +set bug_id 0 + +set testfile "thread_events" +set srcfile ${testfile}.c +set binfile ${objdir}/${subdir}/${testfile} + +if {[gdb_compile_pthreads "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable [list debug "incdir=${objdir}"]] != "" } { + return -1 +} + +proc gdb_test_thread_start {messages_enabled command pattern message} { + global gdb_prompt + + if { $messages_enabled } { + set events_expected 1 + } else { + set events_expected 0 + } + set events_seen 0 + + return [gdb_test_multiple $command $message { + -re "\\\[New Thread \[^\]\]*\\\]\r\n" { + incr events_seen; + exp_continue; + } + -re "\[\r\n\]*($pattern)\[\r\n\]+$gdb_prompt $" { + if { $events_seen != $events_expected } { + fail "$message (saw $events_seen, expected $events_expected)" + } else { + pass "$message" + } + } + }] +} + +proc gdb_test_thread_exit {messages_enabled command pattern message} { + global gdb_prompt + + if { $messages_enabled } { + set events_expected 1 + } else { + set events_expected 0 + } + set events_seen 0 + + return [gdb_test_multiple $command $message { + -re "\\\[Thread \[^\]\]* exited\\\]\r\n" { + incr events_seen + exp_continue; + } + -re "\[\r\n\]*($pattern)\[\r\n\]+$gdb_prompt $" { + if { $events_seen != $events_expected } { + fail "$message (saw $events_seen, expected $events_expected)" + } else { + pass "$message" + } + } + }] +} + +proc test_thread_messages {enabled} { + global srcdir subdir binfile srcfile + + if { $enabled } { + set enabled_string "with messages enabled" + } else { + set enabled_string "with messages disabled" + } + + gdb_start + gdb_reinitialize_dir $srcdir/$subdir + gdb_load ${binfile} + + if { $enabled } { + gdb_test "set print thread-events on" + } else { + gdb_test "set print thread-events off" + } + + # The initial thread may log a 'New Thread' message, but we don't + # check for it. + if ![runto_main] then { + fail "Can't run to main $enabled_string" + return 1 + } + + gdb_test "break threadfunc" \ + "Breakpoint.*at.* file .*$srcfile, line.*" \ + "breakpoint at threadfunc $enabled_string" + gdb_test "break after_join_func" \ + "Breakpoint.*at.* file .*$srcfile, line.*" \ + "breakpoint at after_join_func $enabled_string" + + # continue to threadfunc breakpoint. A thread will start. + # Expect to see a thread start message, if messages are enabled. + gdb_test_thread_start $enabled "continue" \ + ".*Breakpoint .*,.*threadfunc.*at.*$srcfile:.*" \ + "continue to threadfunc $enabled_string" + + # continue to after_join_func breakpoint. A thread will exit. + # Expect to see a thread exit message, if messages are enabled. + gdb_test_thread_exit $enabled "continue" \ + ".*Breakpoint .*,.*after_join_func.*at.*$srcfile:.*" \ + "continue to after_join_func $enabled_string" + + delete_breakpoints + + gdb_exit +} + +test_thread_messages 0 +test_thread_messages 1 Index: tls-shared.c =================================================================== --- tls-shared.c (nonexistent) +++ tls-shared.c (revision 816) @@ -0,0 +1,6 @@ +__thread int i_tls = 1; +int foo () +{ + return i_tls; +} +
tls-shared.c Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +Id \ No newline at end of property Index: local-watch-wrong-thread.exp =================================================================== --- local-watch-wrong-thread.exp (nonexistent) +++ local-watch-wrong-thread.exp (revision 816) @@ -0,0 +1,122 @@ +# This testcase is part of GDB, the GNU debugger. + +# Copyright 2009, 2010 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 3 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, see . + +# This test verifies that a local watchpoint isn't deleted when a +# thread other than the thread the local watchpoint was set in stops +# for a breakpoint. + +if [target_info exists gdb,no_hardware_watchpoints] { + return 0; +} + +set testfile "local-watch-wrong-thread" +set srcfile ${testfile}.c +set binfile ${objdir}/${subdir}/${testfile} +if {[gdb_compile_pthreads \ + "${srcdir}/${subdir}/${srcfile}" \ + "${binfile}" executable {debug} ] != "" } { + return -1 +} + +gdb_exit +gdb_start +gdb_reinitialize_dir $srcdir/$subdir +gdb_load ${binfile} + +gdb_test "set can-use-hw-watchpoints 1" "" "" + +if ![runto_main] then { + fail "Can't run to main" + return +} + +set inc_line_1 [gdb_get_line_number "Loop increment 1"] +set inc_line_2 [gdb_get_line_number "Loop increment 2"] +set bkpt_here [gdb_get_line_number "set breakpoint here"] + +# Run to the loop within thread_function0, so we can set our local +# watchpoint. +gdb_test "break ${srcfile}:${inc_line_1}" \ + "Breakpoint 2 at .*: file .*${srcfile}, line .*" \ + "breakpoint on thread_function0" + +gdb_test "continue" \ + ".*Breakpoint 2.*thread_function0.*" \ + "continue to thread_function0" + +delete_breakpoints + +# Set the local watchpoint, and confirm that it traps as expected. +gdb_test "watch *myp" \ + "Hardware watchpoint 3\: \\*myp.*" \ + "set local watchpoint on *myp" + +gdb_test "continue" \ + "Hardware watchpoint.*Old value.*New value.*thread_function0.*" \ + "local watchpoint triggers" + +delete_breakpoints + +# Recreate the watchpoint, but this time with a condition we know +# won't trigger. This is so the watchpoint is inserted, and the +# target reports events, but GDB doesn't stop for them. We want to +# hit the breakpoints on the other thread, and make sure this +# watchpoint isn't deleted then. +gdb_test "watch *myp if trigger != 0" \ + "Hardware watchpoint 4\: \\*myp.*" \ + "set local watchpoint on *myp, with false conditional" + +# Run to a breakpoint on a different thread. The previous local +# watchpoint should not be deleted with the standard 'the program has +# left the block in which its expression is valid', because the +# thread_function0 thread should still be running in the loop. +gdb_test "break ${srcfile}:${inc_line_2}" \ + "Breakpoint 5 at .*: file .*${srcfile}, line .*" \ + "breakpoint on the other thread" + +gdb_test "continue" \ + "Breakpoint 5, thread_function1.*" \ + "the other thread stopped on breakpoint" + +# Delete the new breakpoint, we don't need it anymore. +gdb_test "delete 5" "" "" + +# Check if the local watchpoint hasn't been deleted (is still listed). +# This is simpler to check than expecting 'the program has left ...', +# and, is immune to string changes in that warning. +gdb_test "info breakpoints" \ + ".*4.*hw watchpoint.*keep.*y.*\\*myp.*" \ + "local watchpoint is still in breakpoint list" + +# Make the watchpoint condition eval true. +gdb_test "set trigger=1" "" "let local watchpoint trigger" + +gdb_test "continue" \ + "Hardware watchpoint.*Old value.*New value.*thread_function0.*" \ + "local watchpoint still triggers" + +# Confirm that the local watchpoint is indeed deleted when +# thread_function0 returns. +gdb_test "set *myp=0" "" "let thread_function0 return" + +gdb_test "break ${srcfile}:${bkpt_here}" \ + "Breakpoint 6 at .*: file .*${srcfile}, line .*" \ + "breakpoint on thread_function0's caller" + +gdb_test "continue" \ + ".*Watchpoint.*deleted.*" \ + "local watchpoint automatically deleted" Index: pending-step.exp =================================================================== --- pending-step.exp (nonexistent) +++ pending-step.exp (revision 816) @@ -0,0 +1,95 @@ +# Copyright (C) 2009, 2010 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 3 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, see . + +# Test that a resume cancels a previously unfinished or unreported +# single-step correctly. +# +# The test consists of several threads all running the same loop. +# There is a breakpoint set in the loop, hence all threads may hit it. +# The test then issues several "next" commands in a loop. +# +# scheduler-locking must be set to the default of "off". +# +# Here's what would happen in gdbserver: +# +# 1) We issue a "continue", and wait until a thread hits the +# breakpoint. Could be any thread, but assume thread 1 hits it. +# +# 2) We issue a "next" --- this single-steps thread 1, and resumes all +# other threads. +# +# 3) thread 2, due to scheduler-locking off, hits the breakpoint. +# gdbserver stops all other threads by sending them SIGSTOPs. +# +# 4) While being stopped in step 3, thread 1 reports a SIGTRAP, that +# corresponds to the finished single-step of step 2. gdbserver +# leaves the SIGTRAP pending to report later. +# +# 5) We issue another "next" --- this requests thread 2 to +# single-step, and all other threads to continue, including thread +# 1. Before resuming any thread, gdbserver notices that it +# remembers from step 4 a pending SIGTRAP to report for thread 1, +# so reports it now. +# +# 6) From GDB's perpective, this SIGTRAP can't represent a finished +# single-step, since thread 1 was not single-stepping (it was +# continued in step 5). Neither does this SIGTRAP correspond to a +# breakpoint hit. GDB reports to the user a spurious SIGTRAP. + +set testfile "pending-step" +set srcfile ${testfile}.c +set binfile ${objdir}/${subdir}/${testfile} + +if {[gdb_compile_pthreads "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable [list debug "incdir=${objdir}"]] != "" } { + return -1 +} + +# Start with a fresh gdb. + +gdb_exit +gdb_start +gdb_reinitialize_dir $srcdir/$subdir +gdb_load ${binfile} + +if ![runto_main] then { + fail "Can't run to main" + return 0 +} + +gdb_breakpoint [gdb_get_line_number "insert breakpoint here"] +gdb_continue_to_breakpoint "continue to first breakpoint hit" + +set test "next in multiple threads with breakpoints" +set iterations 20 +set ok 0 +for {set i 0} {$i < $iterations} {incr i} { + set ok 0 + gdb_test_multiple "next" "$test" { + -re "SIGTRAP.*$gdb_prompt $" { + fail "$test (spurious SIGTRAP)" + } + -re "$gdb_prompt $" { + set ok 1 + } + } + + if { $ok == 0 } { + break + } +} + +if { $ok } { + pass "$test" +} Index: step.c =================================================================== --- step.c (nonexistent) +++ step.c (revision 816) @@ -0,0 +1,221 @@ +/* step.c for step.exp */ +#include +#include +#include +#include +#include + +void alarm_handler (); +void alarm_handler1 (); +void alarm_handler2 (); +void thread1 (); +void thread2 (); + +#define TIME_LIMIT 30 + + +int count1 = 0; +int count2 = 0; + +pthread_t tid1, tid2; +pthread_attr_t attr1, attr2; + +pthread_mutex_t mut; +pthread_mutexattr_t mut_attr; + +pthread_condattr_t cv_attr_a, cv_attr_b; +pthread_cond_t cv_a, cv_b; + +struct cv_struct + { + char a; + char b; + } +test_struct; + +main () +{ + /*init la struct */ + test_struct.a = 0; + test_struct.b = 1; + + /* create le mutex */ + if (pthread_mutexattr_create (&mut_attr) == -1) + { + perror ("mutexattr_create"); + exit (1); + } + + + if (pthread_mutex_init (&mut, mut_attr) == -1) + { + perror ("mutex_init"); + exit (1); + } + + /* create 2 cv */ + if (pthread_condattr_create (&cv_attr_a) == -1) + { + perror ("condattr_create(1)"); + exit (1); + } + + if (pthread_cond_init (&cv_a, cv_attr_a) == -1) + { + perror ("cond_init(1)"); + exit (1); + } + + if (pthread_condattr_create (&cv_attr_b) == -1) + { + perror ("condattr_create(2)"); + exit (1); + } + + if (pthread_cond_init (&cv_b, cv_attr_b) == -1) + { + perror ("cond_init(2)"); + exit (1); + } + + /* create 2 threads of execution */ + if (pthread_attr_create (&attr1) == -1) + { + perror ("attr_create(1)"); + exit (1); + } + + if (pthread_create (&tid1, attr1, thread1, &count1) == -1) + { + perror ("pthread_create(1)"); + exit (1); + } + + if (pthread_attr_create (&attr2) == -1) + { + perror ("attr_create(2)"); + exit (1); + } + + if (pthread_create (&tid2, attr2, thread2, &count2) == -1) + { + perror ("pthread_create(2)"); + exit (1); + } + + /* set alarm to print out data and exit */ + signal (SIGALRM, alarm_handler); + alarm (TIME_LIMIT); + + for (;;) + pause (); +} + +void +thread1 (count) + int *count; +{ + tid_t tid; + + tid = getstid (); + printf ("Thread1 tid 0x%x (%d) \n", tid, tid); + printf ("Thread1 @tid=0x%x \n", &tid); + signal (SIGALRM, alarm_handler1); + + for (;;) + { + if (pthread_mutex_lock (&mut) == -1) + { + perror ("pthread_mutex_lock(1)"); + pthread_exit ((void *) 0); + } + + while (test_struct.a == 0) + { + if (pthread_cond_wait (&cv_a, &mut) == -1) + { + perror ("pthread_cond_wait(1)"); + pthread_exit ((void *) -1); + } + } + + (*count)++; + printf ("*******thread1 count %d\n", *count); + + test_struct.a = 0; + + test_struct.b = 1; + pthread_cond_signal (&cv_b); + + if (pthread_mutex_unlock (&mut) == -1) + { + perror ("pthread_mutex_unlock(1)"); + pthread_exit ((void *) -1); + } + } +} + +void +thread2 (count) + int *count; +{ + tid_t tid; + + tid = getstid (); + printf ("Thread2 tid 0x%x (%d) \n", tid, tid); + printf ("Thread1 @tid=0x%x \n", &tid); + signal (SIGALRM, alarm_handler2); + + for (;;) + { + if (pthread_mutex_lock (&mut) == -1) + { + perror ("pthread_mutex_lock(2)"); + pthread_exit ((void *) 0); + } + + while (test_struct.b == 0) + { + if (pthread_cond_wait (&cv_b, &mut) == -1) + { + perror ("pthread_cond_wait(2)"); + pthread_exit ((void *) -1); + } + } + + (*count)++; + printf ("*******thread2 count %d\n", *count); + + test_struct.b = 0; + + test_struct.a = 1; + pthread_cond_signal (&cv_a); + + if (pthread_mutex_unlock (&mut) == -1) + { + perror ("pthread_mutex_unlock(2)"); + pthread_exit ((void *) -1); + } + } +} + + +void +alarm_handler () +{ + printf ("\tcount1 (%d) \n\tcount2 (%d)\n", count1, count2); + exit (0); +} + +void +alarm_handler1 () +{ + printf ("ALARM thread 1\n"); +} + +void +alarm_handler2 () +{ + printf ("ALARM thread 2\n"); + pthread_exit ((void *) 0); +}
step.c Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +Id \ No newline at end of property Index: tls.exp =================================================================== --- tls.exp (nonexistent) +++ tls.exp (revision 816) @@ -0,0 +1,308 @@ +# tls.exp -- Expect script to test thread-local storage +# Copyright (C) 1992, 2003, 2007, 2008, 2009, 2010 +# 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 3 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, see . */ + +set testfile tls +set testfile2 tls2 +set srcfile ${testfile}.c +set srcfile2 ${testfile2}.c +set binfile ${objdir}/${subdir}/${testfile} + +if [istarget "*-*-linux"] then { + set target_cflags "-D_MIT_POSIX_THREADS" +} else { + set target_cflags "" +} + +if {[gdb_compile_pthreads "${srcdir}/${subdir}/${srcfile} ${srcdir}/${subdir}/${srcfile2}" "${binfile}" executable [list debug "incdir=${objdir}"]] != "" } { + return -1 +} + +### Compute the value of the a_thread_local variable. +proc compute_expected_value {value} { + set expected_value 0 + set i 0 + while { $i <= $value} { + incr expected_value $i + incr i + } + return $expected_value +} + +### Get the value of the variable 'me' for the current thread. +proc get_me_variable {tnum} { + global expect_out + global gdb_prompt + global decimal + + set value_of_me -1 + send_gdb "print me\n" + gdb_expect { + -re ".*= ($decimal).*\r\n$gdb_prompt $" { + set value_of_me $expect_out(1,string) + pass "$tnum thread print me" + } + -re "$gdb_prompt $" { + fail "$tnum thread print me" + } + timeout { + fail "$tnum thread print me (timeout)" + } + } + return ${value_of_me} +} + +### Check the values of the thread local variables in the thread. +### Also check that info address print the right things. +proc check_thread_local {number} { + set me_variable [get_me_variable $number] + set expected_value [compute_expected_value ${me_variable}] + + gdb_test "p a_thread_local" \ + "= $expected_value" \ + "${number} thread local storage" + + gdb_test "p another_thread_local" \ + "= $me_variable" \ + "${number} another thread local storage" + + gdb_test "info address a_thread_local" \ + ".*a_thread_local.*a thread-local variable at offset.*" \ + "${number} info address a_thread_local" + + gdb_test "info address another_thread_local" \ + ".*another_thread_local.*a thread-local variable at offset.*" \ + "${number} info address another_thread_local" +} + +### 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)" + } + } +} + +### Do a backtrace for the current thread, and check that the 'spin' routine +### is in it. This means we have one of the threads we created, rather +### than the main thread. Record the thread in the spin_threads +### array. Also remember the level of the 'spin' routine in the backtrace, for +### later use. +proc check_thread_stack {number spin_threads spin_threads_level} { + global gdb_prompt + global expect_out + global decimal + global hex + upvar $spin_threads tarr + upvar $spin_threads_level tarrl + + select_thread $number + send_gdb "where\n" + gdb_expect { + -re ".*(\[0-9\]+)\[ \t\]+$hex in spin \\(vp=(0x\[0-9a-f\]+).*\r\n$gdb_prompt $" { + if {[info exists tarr($number)]} { + fail "backtrace of thread number $number in spin" + } else { + pass "backtrace of thread number $number in spin" + set level $expect_out(1,string) + set tarrl($number) $level + set tarr($number) 1 + } + } + -re ".*$gdb_prompt $" { + set tarr($number) 0 + set tarrl($number) 0 + pass "backtrace of thread number $number not relevant" + } + timeout { + fail "backtrace of thread number $number (timeout)" + } + } +} + +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 a breakpoint at the "spin" routine to +# test the thread local's value. +# +gdb_test "b [gdb_get_line_number "here we know tls value"]" \ + ".*Breakpoint 2.*tls.*" "set breakpoint at all threads" + +# Set a bp at a point where we know all threads are alive. +# +gdb_test "b [gdb_get_line_number "still alive"]" \ + ".*Breakpoint 3.*tls.*" "set breakpoint at synch point" + +# Set a bp at the end to see if all threads are finished. +# +gdb_test "b [gdb_get_line_number "before exit"]" \ + ".*Breakpoint 4.*tls.*" "set breakpoint at exit" + +send_gdb "continue\n" +gdb_expect { + -re ".*Program received signal SIGSEGV.*a_thread_local = 0;.*$gdb_prompt $" { + # This is the first symptom if the gcc and binutils versions + # in use support TLS, but the system glibc does not. + unsupported "continue to first thread: system does not support TLS" + return -1 + } + -re ".*Program exited normally.*$gdb_prompt $" { + fail "continue to first thread: program runaway" + } + -re ".*Pass 0 done.*Pass 1 done.*$gdb_prompt $" { + fail "continue to first thread: program runaway 2" + } + -re ".*Breakpoint 2.*tls value.*$gdb_prompt $" { + pass "continue to first thread: get to thread" + } + -re ".*$gdb_prompt $" { + fail "continue to first thread: no progress?" + } + timeout { fail "continue to first thread (timeout)" } +} + +gdb_test "info thread" ".*Thread.*spin.*" \ + "at least one th in spin while stopped at first th" + +check_thread_local "first" + +gdb_test "continue" ".*Breakpoint 2.*tls value.*" "continue to second thread" +gdb_test "info thread" "Thread.*spin.*" \ + "at least one th in spin while stopped at second th" + +check_thread_local "second" + +gdb_test "continue" ".*Breakpoint 2.*tls value.*" "continue to third thread" +gdb_test "info thread" ".*Thread.*spin.*" \ + "at least one th in spin while stopped at third th" + +check_thread_local "third" + +gdb_test "continue" ".*Breakpoint 3.*still alive.*" "continue to synch point" + +set no_of_threads 0 +send_gdb "info thread\n" +gdb_expect { + -re "^info thread\[ \t\r\n\]+(\[0-9\]+) Thread.*$gdb_prompt $" { + set no_of_threads $expect_out(1,string) + pass "get number of threads" + } + -re "$gdb_prompt $" { + fail "get number of threads" + } + timeout { + fail "get number of threads (timeout)" + } +} + +array set spin_threads {} +unset spin_threads +array set spin_threads_level {} +unset spin_threads_level + +# For each thread check its backtrace to see if it is stopped at the +# spin routine. +for {set i 1} {$i <= $no_of_threads} {incr i} { + check_thread_stack $i spin_threads spin_threads_level +} + +### Loop through the threads and check the values of the tls variables. +### keep track of how many threads we find in the spin routine. +set thrs_in_spin 0 +foreach i [array names spin_threads] { + if {$spin_threads($i) == 1} { + incr thrs_in_spin + select_thread $i + set level $spin_threads_level($i) + # We expect to be in sem_wait, but if the thread has not yet + # been scheduled, we might be in sem_post still. We could be at + # any intermediate point in spin, too, but that is much less + # likely. + gdb_test "up $level" ".*spin.*sem_(wait|post).*" "thread $i up" + check_thread_local $i + } +} + +if {$thrs_in_spin == 0} { + fail "No thread backtrace reported spin (vsyscall kernel problem?)" +} + +gdb_test "continue" ".*Breakpoint 4.*before exit.*" "threads exited" + +send_gdb "info thread\n" +gdb_expect { + -re ".* 1 Thread.*2 Thread.*$gdb_prompt $" { + fail "Too many threads left at end" + } + -re ".*\\\* 1 Thread.*main.*$gdb_prompt $" { + pass "Expect only base thread at end" + } + -re ".*No stack.*$gdb_prompt $" { + fail "runaway at end" + } + -re ".*$gdb_prompt $" { + fail "mess at end" + } + timeout { fail "at end (timeout)" } +} + +# Start over and do some "info address" stuff +# +runto spin + +gdb_test "info address a_global" \ + ".*a_global.*static storage at address.*" "info address a_global" + +setup_kfail "gdb/1294" "*-*-*" +gdb_test "info address me" ".*me.*is a variable at offset.*" "info address me" + + +# Test LOC_UNRESOLVED references resolving for `extern' TLS variables. + +gdb_test "p a_thread_local" " = \[0-9\]+" +# Here it could crash with: Cannot access memory at address 0x0 +gdb_test "p file2_thread_local" " = \[0-9\]+" +# Depending on the current lookup scope we get LOC_UNRESOLVED or LOC_COMPUTED +# both printing: +# Symbol "file2_thread_local" is a thread-local variable at offset 8 in the thread-local storage for `.../gdb.threads/tls'. +gdb_test "info address file2_thread_local" "Symbol \"file2_thread_local\" is a thread-local variable.*" +# Here it could also crash with: Cannot access memory at address 0x0 +gdb_test "p a_thread_local" " = \[0-9\]+" "p a_thread_local second time" +gdb_test "info address a_thread_local" "Symbol \"a_thread_local\" is a thread-local variable.*" + +# Done! +# +gdb_exit + +return 0 Index: manythreads.c =================================================================== --- manythreads.c (nonexistent) +++ manythreads.c (revision 816) @@ -0,0 +1,69 @@ +/* Manythreads test program. + Copyright 2004, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. + + Written by Jeff Johnston + Contributed by Red Hat + + This file is part of GDB. + + 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 3 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, see . */ + +#include +#include +#include + +void * +thread_function (void *arg) +{ + int x = * (int *) arg; + + printf ("Thread <%d> executing\n", x); + + return NULL; +} + +int +main (int argc, char **argv) +{ + pthread_attr_t attr; + pthread_t threads[256]; + int args[256]; + int i, j; + + pthread_attr_init (&attr); + +#ifdef PTHREAD_STACK_MIN + pthread_attr_setstacksize (&attr, 2*PTHREAD_STACK_MIN); +#endif + + /* Create a ton of quick-executing threads, then wait for them to + complete. */ + for (i = 0; i < 1000; ++i) + { + for (j = 0; j < 256; ++j) + { + args[j] = i * 1000 + j; + pthread_create (&threads[j], &attr, thread_function, &args[j]); + } + + for (j = 0; j < 256; ++j) + { + pthread_join (threads[j], NULL); + } + } + + pthread_attr_destroy (&attr); + + return 0; +}
manythreads.c Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +Id \ No newline at end of property Index: watchthreads.c =================================================================== --- watchthreads.c (nonexistent) +++ watchthreads.c (revision 816) @@ -0,0 +1,80 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2002, 2003, 2004, 2007, 2008, 2009, 2010 + 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 3 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, see . + + This file is copied from schedlock.c. */ + +#include +#include +#include +#include + +void *thread_function (void *arg); /* Function executed by each thread. */ + +#define NUM 5 + +unsigned int args[NUM+1]; + +int +main () +{ + int res; + pthread_t threads[NUM]; + void *thread_result; + long i; + + /* To keep the test determinative, initialize args first, + then start all the threads. Otherwise, the way watchthreads.exp + is written, we have to worry about things like threads[0] getting + to 29 hits of args[0] before args[1] gets changed. */ + + for (i = 0; i < NUM; i++) + { + /* The call to usleep is so that when the watchpoint triggers, + the pc is still on the same line. */ + args[i] = 1; usleep (1); /* Init value. */ + } + + for (i = 0; i < NUM; i++) + { + res = pthread_create (&threads[i], + NULL, + thread_function, + (void *) i); + } + + args[i] = 1; + thread_function ((void *) i); + + exit (EXIT_SUCCESS); +} + +void * +thread_function (void *arg) +{ + int my_number = (long) arg; + int *myp = (int *) &args[my_number]; + + /* Don't run forever. Run just short of it :) */ + while (*myp > 0) + { + (*myp) ++; usleep (1); /* Loop increment. */ + } + + pthread_exit (NULL); +} +
watchthreads.c Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +Id \ No newline at end of property Index: watchthreads-reorder.c =================================================================== --- watchthreads-reorder.c (nonexistent) +++ watchthreads-reorder.c (revision 816) @@ -0,0 +1,364 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2009, 2010 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 3 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, see . */ + +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define gettid() syscall (__NR_gettid) + +/* Terminate always in the main task, it can lock up with SIGSTOPped GDB + otherwise. */ +#define TIMEOUT (gettid () == getpid() ? 10 : 15) + +static pid_t thread1_tid; +static pthread_cond_t thread1_tid_cond = PTHREAD_COND_INITIALIZER; +static pthread_mutex_t thread1_tid_mutex = PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP; + +static pid_t thread2_tid; +static pthread_cond_t thread2_tid_cond = PTHREAD_COND_INITIALIZER; +static pthread_mutex_t thread2_tid_mutex = PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP; + +static pthread_mutex_t terminate_mutex = PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP; + +/* These variables must have lower in-memory addresses than thread1_rwatch and + thread2_rwatch so that they take their watchpoint slots. */ + +static int unused1_rwatch; +static int unused2_rwatch; + +static volatile int thread1_rwatch; +static volatile int thread2_rwatch; + +/* Do not use alarm as it would create a ptrace event which would hang up us if + we are being traced by GDB which we stopped ourselves. */ + +static void timed_mutex_lock (pthread_mutex_t *mutex) +{ + int i; + struct timespec start, now; + + i = clock_gettime (CLOCK_MONOTONIC, &start); + assert (i == 0); + + do + { + i = pthread_mutex_trylock (mutex); + if (i == 0) + return; + assert (i == EBUSY); + + i = clock_gettime (CLOCK_MONOTONIC, &now); + assert (i == 0); + assert (now.tv_sec >= start.tv_sec); + } + while (now.tv_sec - start.tv_sec < TIMEOUT); + + fprintf (stderr, "Timed out waiting for internal lock!\n"); + exit (EXIT_FAILURE); +} + +static void * +thread1_func (void *unused) +{ + int i; + volatile int rwatch_store; + + timed_mutex_lock (&thread1_tid_mutex); + + /* THREAD1_TID_MUTEX must be already locked to avoid race. */ + thread1_tid = gettid (); + + i = pthread_cond_signal (&thread1_tid_cond); + assert (i == 0); + i = pthread_mutex_unlock (&thread1_tid_mutex); + assert (i == 0); + + rwatch_store = thread1_rwatch; + + /* Be sure the "T (tracing stop)" test can proceed for both threads. */ + timed_mutex_lock (&terminate_mutex); + i = pthread_mutex_unlock (&terminate_mutex); + assert (i == 0); + + return NULL; +} + +static void * +thread2_func (void *unused) +{ + int i; + volatile int rwatch_store; + + timed_mutex_lock (&thread2_tid_mutex); + + /* THREAD2_TID_MUTEX must be already locked to avoid race. */ + thread2_tid = gettid (); + + i = pthread_cond_signal (&thread2_tid_cond); + assert (i == 0); + i = pthread_mutex_unlock (&thread2_tid_mutex); + assert (i == 0); + + rwatch_store = thread2_rwatch; + + /* Be sure the "T (tracing stop)" test can proceed for both threads. */ + timed_mutex_lock (&terminate_mutex); + i = pthread_mutex_unlock (&terminate_mutex); + assert (i == 0); + + return NULL; +} + +static const char * +proc_string (const char *filename, const char *line) +{ + FILE *f; + static char buf[LINE_MAX]; + size_t line_len = strlen (line); + + f = fopen (filename, "r"); + if (f == NULL) + { + fprintf (stderr, "fopen (\"%s\") for \"%s\": %s\n", filename, line, + strerror (errno)); + exit (EXIT_FAILURE); + } + while (errno = 0, fgets (buf, sizeof (buf), f)) + { + char *s; + + s = strchr (buf, '\n'); + assert (s != NULL); + *s = 0; + + if (strncmp (buf, line, line_len) != 0) + continue; + + if (fclose (f)) + { + fprintf (stderr, "fclose (\"%s\") for \"%s\": %s\n", filename, line, + strerror (errno)); + exit (EXIT_FAILURE); + } + + return &buf[line_len]; + } + if (errno != 0) + { + fprintf (stderr, "fgets (\"%s\": %s\n", filename, strerror (errno)); + exit (EXIT_FAILURE); + } + fprintf (stderr, "\"%s\": No line \"%s\" found.\n", filename, line); + exit (EXIT_FAILURE); +} + +static unsigned long +proc_ulong (const char *filename, const char *line) +{ + const char *s = proc_string (filename, line); + long retval; + char *end; + + errno = 0; + retval = strtol (s, &end, 10); + if (retval < 0 || retval >= LONG_MAX || (end && *end)) + { + fprintf (stderr, "\"%s\":\"%s\": %ld, %s\n", filename, line, retval, + strerror (errno)); + exit (EXIT_FAILURE); + } + return retval; +} + +static void +state_wait (pid_t process, const char *wanted) +{ + char *filename; + int i; + struct timespec start, now; + const char *state; + + i = asprintf (&filename, "/proc/%lu/status", (unsigned long) process); + assert (i > 0); + + i = clock_gettime (CLOCK_MONOTONIC, &start); + assert (i == 0); + + do + { + state = proc_string (filename, "State:\t"); + if (strcmp (state, wanted) == 0) + { + free (filename); + return; + } + + if (sched_yield ()) + { + perror ("sched_yield()"); + exit (EXIT_FAILURE); + } + + i = clock_gettime (CLOCK_MONOTONIC, &now); + assert (i == 0); + assert (now.tv_sec >= start.tv_sec); + } + while (now.tv_sec - start.tv_sec < TIMEOUT); + + fprintf (stderr, "Timed out waiting for PID %lu \"%s\" (now it is \"%s\")!\n", + (unsigned long) process, wanted, state); + exit (EXIT_FAILURE); +} + +static volatile pid_t tracer = 0; +static pthread_t thread1, thread2; + +static void +cleanup (void) +{ + printf ("Resuming GDB PID %lu.\n", (unsigned long) tracer); + + if (tracer) + { + int i; + int tracer_save = tracer; + + tracer = 0; + + i = kill (tracer_save, SIGCONT); + assert (i == 0); + } +} + +int +main (int argc, char **argv) +{ + int i; + int standalone = 0; + + if (argc == 2 && strcmp (argv[1], "-s") == 0) + standalone = 1; + else + assert (argc == 1); + + setbuf (stdout, NULL); + + timed_mutex_lock (&thread1_tid_mutex); + timed_mutex_lock (&thread2_tid_mutex); + + timed_mutex_lock (&terminate_mutex); + + i = pthread_create (&thread1, NULL, thread1_func, NULL); + assert (i == 0); + + i = pthread_create (&thread2, NULL, thread2_func, NULL); + assert (i == 0); + + if (!standalone) + { + tracer = proc_ulong ("/proc/self/status", "TracerPid:\t"); + if (tracer == 0) + { + fprintf (stderr, "The testcase must be run by GDB!\n"); + exit (EXIT_FAILURE); + } + if (tracer != getppid ()) + { + fprintf (stderr, "The testcase parent must be our GDB tracer!\n"); + exit (EXIT_FAILURE); + } + } + + /* SIGCONT our debugger in the case of our crash as we would deadlock + otherwise. */ + + atexit (cleanup); + + printf ("Stopping GDB PID %lu.\n", (unsigned long) tracer); + + if (tracer) + { + i = kill (tracer, SIGSTOP); + assert (i == 0); + state_wait (tracer, "T (stopped)"); + } + + /* Threads are now waiting at timed_mutex_lock (thread1_tid_mutex) and so + they could not trigger the watchpoints before GDB gets unstopped later. + Threads get resumed at pthread_cond_wait below. Use `while' loops for + protection against spurious pthread_cond_wait wakeups. */ + + printf ("Waiting till the threads initialize their TIDs.\n"); + + while (thread1_tid == 0) + { + i = pthread_cond_wait (&thread1_tid_cond, &thread1_tid_mutex); + assert (i == 0); + } + + while (thread2_tid == 0) + { + i = pthread_cond_wait (&thread2_tid_cond, &thread2_tid_mutex); + assert (i == 0); + } + + printf ("Thread 1 TID = %lu, thread 2 TID = %lu, PID = %lu.\n", + (unsigned long) thread1_tid, (unsigned long) thread2_tid, + (unsigned long) getpid ()); + + printf ("Waiting till the threads get trapped by the watchpoints.\n"); + + if (tracer) + { + /* s390x-unknown-linux-gnu will fail with "R (running)". */ + + state_wait (thread1_tid, "T (tracing stop)"); + + state_wait (thread2_tid, "T (tracing stop)"); + } + + cleanup (); + + printf ("Joining the threads.\n"); + + i = pthread_mutex_unlock (&terminate_mutex); + assert (i == 0); + + i = pthread_join (thread1, NULL); + assert (i == 0); + + i = pthread_join (thread2, NULL); + assert (i == 0); + + printf ("Exiting.\n"); /* break-at-exit */ + + /* Just prevent compiler `warning: unusedX_rwatch defined but not used'. */ + unused1_rwatch = 1; + unused2_rwatch = 2; + + return EXIT_SUCCESS; +}
watchthreads-reorder.c Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +Id \ No newline at end of property Index: execl1.c =================================================================== --- execl1.c (nonexistent) +++ execl1.c (revision 816) @@ -0,0 +1,27 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2008, 2009, 2010 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 3 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, see . +*/ + +/* Test handling thread control across an execl. */ + +/* New exec image that doesn't load any thread library. */ + +int +main (int argc, char* argv[]) +{ + return 0; +}
execl1.c Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +Id \ No newline at end of property Index: tls-main.c =================================================================== --- tls-main.c (nonexistent) +++ tls-main.c (revision 816) @@ -0,0 +1,9 @@ +__thread int i_tls = 2; +int main () +{ + int result; + result = foo (); /* Call to foo should return 2, not 1. */ + result ++; + return 0; /* break here to check result */ +} +
tls-main.c Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +Id \ No newline at end of property Index: current-lwp-dead.exp =================================================================== --- current-lwp-dead.exp (nonexistent) +++ current-lwp-dead.exp (revision 816) @@ -0,0 +1,36 @@ +# This testcase is part of GDB, the GNU debugger. + +# Copyright 2009, 2010 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 3 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, see . + +# Please email any bugs, comments, and/or additions to this file to: +# bug-gdb@gnu.org + +# This only works with on Linux targets. +if ![istarget *-*-linux*] then { + return +} + +if { [prepare_for_testing current-lwp-dead.exp current-lwp-dead] } { + return -1 +} + +if {[runto_main] <= 0} { + untested current-lwp-dead.exp + return -1 +} + +gdb_breakpoint "fn_return" +gdb_continue_to_breakpoint "fn_return" ".*at-fn_return.*" Index: fork-thread-pending.c =================================================================== --- fork-thread-pending.c (nonexistent) +++ fork-thread-pending.c (revision 816) @@ -0,0 +1,109 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2008, 2009, 2010 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 3 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, see . */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define NUMTHREADS 10 + +volatile int done = 0; + +static void * +start (void *arg) +{ + while (!done) + usleep (100); + assert (0); + return arg; +} + +void * +thread_function (void *arg) +{ + int x = * (int *) arg; + + printf ("Thread <%d> executing\n", x); + + while (!done) + usleep (100); + + return NULL; +} + +void * +thread_forker (void *arg) +{ + int x = * (int *) arg; + pid_t pid; + int rv; + int i; + pthread_t thread; + + printf ("Thread forker <%d> executing\n", x); + + switch ((pid = fork ())) + { + case -1: + assert (0); + default: + wait (&rv); + done = 1; + break; + case 0: + i = pthread_create (&thread, NULL, start, NULL); + assert (i == 0); + i = pthread_join (thread, NULL); + assert (i == 0); + + assert (0); + } + + return NULL; +} + +int +main (void) +{ + pthread_t threads[NUMTHREADS]; + int args[NUMTHREADS]; + int i, j; + + /* Create a few threads that do mostly nothing, and then one that + forks. */ + for (j = 0; j < NUMTHREADS - 1; ++j) + { + args[j] = j; + pthread_create (&threads[j], NULL, thread_function, &args[j]); + } + + args[j] = j; + pthread_create (&threads[j], NULL, thread_forker, &args[j]); + + for (j = 0; j < NUMTHREADS; ++j) + { + pthread_join (threads[j], NULL); + } + + return 0; +}
fork-thread-pending.c Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +Id \ No newline at end of property Index: thread-specific.c =================================================================== --- thread-specific.c (nonexistent) +++ thread-specific.c (revision 816) @@ -0,0 +1,64 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2004, 2007, 2008, 2009, 2010 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 3 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, see . */ + +#include +#include +#include +#include + +void *thread_function(void *arg); + +unsigned int args[1]; + +int main() { + int res; + pthread_t threads[2]; + void *thread_result; + long i = 1; + + args[0] = 1; + res = pthread_create(&threads[0], + NULL, + thread_function, + (void *) 0); + + /* thread-specific.exp: last thread start. */ + args[1] = 1; + + /* Don't run forever. Run just short of it :) */ + while (i > 0) + { + /* thread-specific.exp: main loop. */ + (i) ++; + } + + exit(EXIT_SUCCESS); +} + +void *thread_function(void *arg) { + int my_number = (long) arg; + int *myp = (int *) &args[my_number]; + + /* Don't run forever. Run just short of it :) */ + while (*myp > 0) + { + /* thread-specific.exp: thread loop. */ + (*myp) ++; + } + + pthread_exit(NULL); +}
thread-specific.c Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +Id \ No newline at end of property Index: multi-create.c =================================================================== --- multi-create.c (nonexistent) +++ multi-create.c (revision 816) @@ -0,0 +1,91 @@ +/* Create threads from multiple threads in parallel. + Copyright 2007, 2008, 2009, 2010 Free Software Foundation, Inc. + + This file is part of GDB. + + 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 3 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, see . */ + +#include +#include +#include + +#define NUM_CREATE 1 +#define NUM_THREAD 8 + +void * +thread_function (void *arg) +{ + int x = * (int *) arg; + + printf ("Thread <%d> executing\n", x); + + return NULL; +} + +void * +create_function (void *arg) +{ + pthread_attr_t attr; + pthread_t threads[NUM_THREAD]; + int args[NUM_THREAD]; + int i = * (int *) arg; + int j; + + pthread_attr_init (&attr); /* set breakpoint 1 here. */ + pthread_attr_setstacksize (&attr, 2*PTHREAD_STACK_MIN); + + /* Create a ton of quick-executing threads, then wait for them to + complete. */ + for (j = 0; j < NUM_THREAD; ++j) + { + args[j] = i * 1000 + j; + pthread_create (&threads[j], &attr, thread_function, &args[j]); + } + + for (j = 0; j < NUM_THREAD; ++j) + pthread_join (threads[j], NULL); + + pthread_attr_destroy (&attr); + + return NULL; +} + +int +main (int argc, char **argv) +{ + pthread_attr_t attr; + pthread_t threads[NUM_CREATE]; + int args[NUM_CREATE]; + int n, i; + + pthread_attr_init (&attr); + pthread_attr_setstacksize (&attr, 2*PTHREAD_STACK_MIN); + + for (n = 0; n < 100; ++n) + { + for (i = 0; i < NUM_CREATE; i++) + { + args[i] = i; + pthread_create (&threads[i], &attr, create_function, &args[i]); + } + + create_function (&i); + for (i = 0; i < NUM_CREATE; i++) + pthread_join (threads[i], NULL); + } + + pthread_attr_destroy (&attr); + + return 0; +}
multi-create.c Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +Id \ No newline at end of property Index: schedlock.c =================================================================== --- schedlock.c (nonexistent) +++ schedlock.c (revision 816) @@ -0,0 +1,65 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2002, 2003, 2004, 2007, 2008, 2009, 2010 + 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 3 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, see . */ + +#include +#include +#include +#include + +void *thread_function(void *arg); /* Pointer to function executed by each thread */ + +#define NUM 1 + +unsigned int args[NUM+1]; + +int main() { + int res; + pthread_t threads[NUM]; + void *thread_result; + long i; + + for (i = 1; i <= NUM; i++) + { + args[i] = 1; + res = pthread_create(&threads[i - 1], + NULL, + thread_function, + (void *) i); + } + + /* schedlock.exp: last thread start. */ + args[0] = 1; + thread_function ((void *) 0); + + exit(EXIT_SUCCESS); +} + +void *thread_function(void *arg) { + int my_number = (long) arg; + int *myp = (int *) &args[my_number]; + + /* Don't run forever. Run just short of it :) */ + while (*myp > 0) + { + /* schedlock.exp: main loop. */ + (*myp) ++; + } + + pthread_exit(NULL); +} +
schedlock.c Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +Id \ No newline at end of property Index: interrupted-hand-call.exp =================================================================== --- interrupted-hand-call.exp (nonexistent) +++ interrupted-hand-call.exp (revision 816) @@ -0,0 +1,92 @@ +# Copyright (C) 2004, 2007, 2008, 2010 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 3 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, see . + +# Test recovering from a hand function call that gets interrupted +# by a signal in another thread. + +set NR_THREADS 4 + +if $tracelevel then { + strace $tracelevel +} + +set testfile "interrupted-hand-call" +set srcfile ${testfile}.c +set binfile ${objdir}/${subdir}/${testfile} + +if {[gdb_compile_pthreads "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable [list debug "incdir=${objdir}" "additional_flags=-DNR_THREADS=$NR_THREADS"]] != "" } { + return -1 +} + +# Some targets can't do function calls, so don't even bother with this +# test. +if [target_info exists gdb,cannot_call_functions] { + setup_xfail "*-*-*" 2416 + fail "This target can not call functions" + continue +} + +gdb_exit +gdb_start +gdb_reinitialize_dir $srcdir/$subdir +gdb_load ${binfile} + +if { ![runto_main] } { + fail "Can't run to main" + return 0 +} + +gdb_test "break all_threads_running" \ + "Breakpoint 2 at .*: file .*${srcfile}, line .*" \ + "breakpoint on all_threads_running" + +# Run the program and make sure GDB reports that we stopped after +# hitting breakpoint 2 in all_threads_running(). + +gdb_test "continue" \ + ".*Breakpoint 2, all_threads_running ().*" \ + "run to all_threads_running" + +# NOTE: Don't turn on scheduler-locking here. +# We want the main thread (hand_call_with_signal) and +# thread 1 (sigabrt_handler) to both run. + +gdb_test "call hand_call_with_signal()" \ + ".*in another thread.*" \ + "hand-call interrupted by signal in another thread" + +# Verify dummy stack frame is still present. + +gdb_test "maint print dummy-frames" ".*stack=.*" "dummy stack frame present" + +# Continuing now should exit the hand-call and pop the dummy frame. + +gdb_test "continue" "" "finish hand-call" + +gdb_test_multiple "maint print dummy-frames" "dummy frame popped" { + -re ".*stack=.*$gdb_prompt $" { + fail "dummy frame popped" + } + -re ".*$gdb_prompt $" { + pass "dummy frame popped" + } +} + +# Continue one last time, the program should exit normally. + +gdb_test "continue" "Program exited normally." \ + "continue to program exit" + +return 0 Index: tls.c =================================================================== --- tls.c (nonexistent) +++ tls.c (revision 816) @@ -0,0 +1,230 @@ +/* BeginSourceFile tls.c + + This file creates and deletes threads. It uses thread local storage + variables too. */ + +#include +#include +#include +#include +#include +#include +#include + +#define N_THREADS 3 + +/* Uncomment to turn on debugging output */ +/*#define START_DEBUG*/ + +/* Thread-local storage. */ +__thread int a_thread_local; +__thread int another_thread_local; + +/* psymtabs->symtabs resolving check. */ +extern __thread int file2_thread_local; + +/* Global variable just for info addr in gdb. */ +int a_global; + +/* Print the results of thread-local storage. */ +int thread_local_val[ N_THREADS ]; +int another_thread_local_val[ N_THREADS ]; + +/* Semaphores to make sure the threads are alive when we print the TLS + variables from gdb. */ +sem_t tell_main, tell_thread; + + +void print_error () +{ + switch (errno) + { + case EAGAIN: + fprintf (stderr, "EAGAIN\n"); + break; + case EINTR: + fprintf (stderr, "EINTR\n"); + break; + case EINVAL: + fprintf (stderr, "EINVAL\n"); + break; + case ENOSYS: + fprintf (stderr, "ENOSYS\n"); + break; + case ENOENT: + fprintf (stderr, "ENOENT\n"); + break; + case EDEADLK: + fprintf (stderr, "EDEADLK\n"); + break; + default: + fprintf (stderr, "Unknown error\n"); + break; + } +} + +/* Routine for each thread to run, does nothing. */ +void *spin( vp ) + void * vp; +{ + int me = (long) vp; + int i; + + /* Use a_global. */ + a_global++; + + a_thread_local = 0; + another_thread_local = me; + for( i = 0; i <= me; i++ ) { + a_thread_local += i; + } + + another_thread_local_val[me] = another_thread_local; + thread_local_val[ me ] = a_thread_local; /* here we know tls value */ + + if (sem_post (&tell_main) == -1) + { + fprintf (stderr, "th %d post on sem tell_main failed\n", me); + print_error (); + return; + } +#ifdef START_DEBUG + fprintf (stderr, "th %d post on tell main\n", me); +#endif + + while (1) + { +#ifdef START_DEBUG + fprintf (stderr, "th %d start wait on tell_thread\n", me); +#endif + if (sem_wait (&tell_thread) == 0) + break; + + if (errno == EINTR) + { +#ifdef START_DEBUG + fprintf (stderr, "th %d wait tell_thread got EINTR, rewaiting\n", me); +#endif + continue; + } + else + { + fprintf (stderr, "th %d wait on sem tell_thread failed\n", me); + print_error (); + return; + } + } + +#ifdef START_DEBUG + fprintf (stderr, "th %d Wait on tell_thread\n", me); +#endif + +} + +void +function_referencing_file2_thread_local (void) +{ + file2_thread_local = file2_thread_local; +} + +void +do_pass() +{ + int i; + pthread_t t[ N_THREADS ]; + int err; + + for( i = 0; i < N_THREADS; i++) + { + thread_local_val[i] = 0; + another_thread_local_val[i] = 0; + } + + if (sem_init (&tell_main, 0, 0) == -1) + { + fprintf (stderr, "tell_main semaphore init failed\n"); + return; + } + + if (sem_init (&tell_thread, 0, 0) == -1) + { + fprintf (stderr, "tell_thread semaphore init failed\n"); + return; + } + + /* 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 *) (long) i ); + if( err != 0 ) { + fprintf(stderr, "Error in thread %d create\n", i ); + } + } + + for( i = 0; i < N_THREADS; i++ ) + { + while (1) + { +#ifdef START_DEBUG + fprintf (stderr, "main %d start wait on tell_main\n", i); +#endif + if (sem_wait (&tell_main) == 0) + break; + + if (errno == EINTR) + { +#ifdef START_DEBUG + fprintf (stderr, "main %d wait tell_main got EINTR, rewaiting\n", i); +#endif + continue; + } + else + { + fprintf (stderr, "main %d wait on sem tell_main failed\n", i); + print_error (); + return; + } + } + } + +#ifdef START_DEBUG + fprintf (stderr, "main done waiting on tell_main\n"); +#endif + + i = 10; /* Here all threads should be still alive. */ + + for( i = 0; i < N_THREADS; i++ ) + { + if (sem_post (&tell_thread) == -1) + { + fprintf (stderr, "main %d post on sem tell_thread failed\n", i); + print_error (); + return; + } +#ifdef START_DEBUG + fprintf (stderr, "main %d post on tell_thread\n", i); +#endif + } + + for( i = 0; i < N_THREADS; i++ ) + { + err = pthread_join(t[i], NULL ); + if( err != 0 ) + { + fprintf (stderr, "error in thread %d join\n", i ); + } + } + + i = 10; /* Null line for setting bpts on. */ + +} + +int +main() +{ + do_pass (); + + return 0; /* Set breakpoint here before exit. */ +} + +/* EndSourceFile */
tls.c Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +Id \ No newline at end of property Index: thread-execl.c =================================================================== --- thread-execl.c (nonexistent) +++ thread-execl.c (revision 816) @@ -0,0 +1,48 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2009, 2010 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 3 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, see . */ + +#include +#include +#include + +static const char *image; + +void * +thread_execler (void *arg) +{ + /* Exec ourselves again. */ + if (execl (image, image, NULL) == -1) + { + perror ("execl"); + abort (); + } + + return NULL; +} + +int +main (int argc, char **argv) +{ + pthread_t thread; + + image = argv[0]; + + pthread_create (&thread, NULL, thread_execler, NULL); + pthread_join (thread, NULL); + + return 0; +}
thread-execl.c Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +Id \ No newline at end of property Index: threxit-hop-specific.exp =================================================================== --- threxit-hop-specific.exp (nonexistent) +++ threxit-hop-specific.exp (revision 816) @@ -0,0 +1,59 @@ +# Copyright (C) 2009, 2010 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 3 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, see . + +# Test that GDB doesn't get stuck when thread hoping over a thread +# specific breakpoint when the selected thread has gone away. + +set testfile "threxit-hop-specific" +set srcfile ${testfile}.c +set binfile ${objdir}/${subdir}/${testfile} + +if {[gdb_compile_pthreads "${srcdir}/${subdir}/${srcfile}" "${binfile}" \ + executable [list debug "incdir=${objdir}"]] != "" } { + return -1 +} + +# Start with a fresh gdb. + +gdb_exit +gdb_start +gdb_reinitialize_dir $srcdir/$subdir + +gdb_load ${binfile} + +runto_main + +# Get ourselves to the thread that exits +gdb_breakpoint "thread_function" +gdb_test "continue" ".*thread_function.*" "continue to thread start" + +# Set a thread specific breakpoint somewhere the main thread will pass +# by, but make it specific to the thread that is going to exit. Step +# over the pthread_exit call. GDB should still be able to step over +# the thread specific breakpoint, and reach the other breakpoint, +# which is not thread specific. +set bpthrline [gdb_get_line_number "set thread specific breakpoint here"] +gdb_test "break $bpthrline thread 2" \ + "Breakpoint .*$srcfile.*$bpthrline.*" \ + "set thread specific breakpoint" + +set bpexitline [gdb_get_line_number "set exit breakpoint here"] +gdb_breakpoint "$bpexitline" + +gdb_test "next" \ + ".*set exit breakpoint here.*" \ + "get past the thread specific breakpoint" + +return 0 Index: linux-dp.exp =================================================================== --- linux-dp.exp (nonexistent) +++ linux-dp.exp (revision 816) @@ -0,0 +1,391 @@ +# Copyright 1999, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 +# 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 3 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, see . + +# Please email any bugs, comments, and/or additions to this file to: +# bug-gdb@gnu.org + +#### Dining Philosophers, on LinuxThreads - Jim Blandy +#### +#### 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}] != ""} { + return -1 +} + +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"] +set expect_manager -1 +for {set i 0} {$i < 5} {incr i} { + gdb_continue_to_breakpoint "about to create philosopher: $i" + send_gdb "info threads\n" + set threads_before {} + gdb_expect { + -re "info threads\r\n" { + exp_continue + } + -re "^. +(\[0-9\]+ Thread \[-0-9a-fx\]+) \[^\n\]*\n" { + verbose -log "found thread $expect_out(1,string)" 2 + lappend threads_before $expect_out(1,string) + exp_continue + } + -re "^\[^\n\]*\n" { + verbose -log "skipping line" 2 + exp_continue -continue_timer + } + -re "^$gdb_prompt $" { + } + timeout { + fail "(timeout) info threads before: $i" + } + } + send_gdb "next\n" + set threads_created 0 + gdb_expect { + -re "^next\r\n" { + exp_continue + } + -re "^ *\[_!\] \[0-9\]* \[_!\]\r\n" { + # Ignore program output. + exp_continue -continue_timer + } + -re "^\\\[New \[^\]\n\]+\\\]\[^\n\]+\n" { + incr threads_created + exp_continue + } + -re "^189\[^\n\]+\n" { + exp_continue + } + -re "^$gdb_prompt $" { + } + -re "Program received signal.*(Unknown signal|SIGUSR|Real-time event).*$gdb_prompt $" { + # It would be nice if we could catch the message that GDB prints + # when it first notices that the thread library doesn't support + # debugging, or if we could explicitly ask GDB somehow. + unsupported "This GDB does not support threads on this system." + return -1 + } + -re "$gdb_prompt $" { + } + timeout { + fail "(timeout) create philosopher: $i" + } + } + if { $threads_created == 0 } { + # Not all targets announce new threads as they are created. + # For example, the GDB + # remote protocol target only finds out about threads when + # they actually report some event like a breakpoint hit, + # or when the user types 'info threads'. + unsupported "create philosopher: $i" + } elseif { $threads_created == 1 } { + if { $expect_manager < 0 } { + set expect_manager 0 + } + pass "create philosopher: $i" + } elseif { !$i && $threads_created == 2 } { + # Two threads are created the first time in LinuxThreads, + # where the second is the manager thread. In NPTL, there is none. + set expect_manager 1 + pass "create philosopher: $i" + } else { + fail "create philosopher: $i" + } + + send_gdb "info threads\n" + set threads_after {} + gdb_expect { + -re "info threads\r\n" { + exp_continue + } + -re "^. +(\[0-9\]+ Thread \[-0-9a-fx\]+) \[^\n\]*\n" { + set name $expect_out(1,string) + for {set j 0} {$j != [llength $threads_before] } {incr j} { + if {$name == [lindex $threads_before $j]} { + set threads_before [lreplace $threads_before $j $j] + set name "" + break + } + } + if { $name != "" } { + lappend threads_after $name + } + exp_continue + } + -re "^\[^\n\]*\n" { + verbose -log "skipping line" 2 + exp_continue -continue_timer + } + -re "^$gdb_prompt $" { + if { [llength $threads_before] != 0 } { + fail "info threads after: $i" + } elseif { !$i && [llength $threads_after] == 2 } { + set expect_manager 1 + pass "info threads after: $i" + } elseif { [llength $threads_after] == 1 } { + if { $expect_manager < 0 } { + set expect_manager 0 + } + pass "info threads after: $i" + } else { + fail "info threads after: $i" + } + } + timeout { + fail "(timeout) info threads after: $i" + } + } + +} + +set nthreads 6 + +# 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" +set info_threads_ptn "" +for {set i $nthreads} {$i > 0} {incr i -1} { + append info_threads_ptn "$i Thread .*" +} +append info_threads_ptn "\[\r\n\]+$gdb_prompt $" +set info_threads_manager_ptn "[expr $nthreads + 1] Thread .*$info_threads_ptn" + +gdb_test_multiple "info threads" "info threads 2" { + -re "$info_threads_manager_ptn" { + # We did see a manager thread. Check that against what we expected. + switch -exact -- $expect_manager { + -1 { + # We weren't sure whether to expect a manager thread. + pass "info threads 2" + } + 1 { + # We were expecting a manager thread. + pass "info threads 2" + } + 0 { + # We were not expecting to see the manager thread. + fail "info threads 2" + } + } + set expect_manager 1 + incr nthreads + } + -re "$info_threads_ptn" { + # We did not see a manager thread. Check that against what we + # expected. + switch -exact -- $expect_manager { + -1 { + # We weren't sure whether to expect a manager thread. + # Don't expect it from here on out. + pass "info threads 2" + } + 1 { + # We were expecting a manager thread, but we didn't see one. + fail "info threads 2" + } + 0 { + # We were not expecting to see the manager thread. + pass "info threads 2" + } + } + set expect_manager 0 + } +} + + +# Try setting a thread-specific breakpoint. +gdb_breakpoint "print_philosopher thread 5" +gdb_continue_to_breakpoint "thread 5's print" +# When there is no debugging info available for the thread library, +# the backtrace entry for philosopher's caller looks like: +# #1 0x4001c548 in pthread_create () from /lib/libpthread.so.0 +# If you do have debug info, the output obviously depends more on the +# exact library in use; under NPTL, you get: +# #2 0x0012b7fc in start_thread (arg=0x21) at pthread_create.c:264 +gdb_test "where" "print_philosopher.*philosopher.* \(from .*libpthread\|at pthread_create\).*" \ + "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. + +set main_seen 0 +set manager_seen 0 + +proc check_philosopher_stack {thread seen_name} { + global gdb_prompt + upvar $seen_name seen + global main_seen + global expect_manager manager_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 ".* in __pthread_manager \\(.*$gdb_prompt $" { + if {$manager_seen == 1} { + fail "manager thread is distinct: $thread" + } else { + set manager_seen 1 + pass "manager thread is distinct: $thread" + } + set interesting 1 + } + -re "pthread_start_thread.*\r\n$gdb_prompt $" { + ## Maybe the thread hasn't started yet. + pass $name + } + -re ".* in main \\(.*$gdb_prompt $" { + if {$main_seen == 1} { + fail "main is distinct: $thread" + } else { + set main_seen 1 + pass "main is distinct: $thread" + } + set interesting 1 + } + -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 {} +unset seen +for {set i 1} {$i <= $nthreads} {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" +} + +if {$manager_seen == $expect_manager} { + pass "manager thread found (not found) when expected" +} else { + fail "manager thread found (not found) when expected" +} Index: staticthreads.exp =================================================================== --- staticthreads.exp (nonexistent) +++ staticthreads.exp (revision 816) @@ -0,0 +1,101 @@ +# static.exp -- test script, for GDB, the GNU debugger. + +# Copyright 2004, 2005, 2007, 2008, 2009, 2010 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 3 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, see . + +# Based on manythreads written by Jeff Johnston, contributed by Red +# Hat. + +if $tracelevel then { + strace $tracelevel +} + +set prms_id 0 +set bug_id 0 + +set testfile "staticthreads" +set srcfile ${testfile}.c +set binfile ${objdir}/${subdir}/${testfile} +set static_flag "-static" + +if {[gdb_compile_pthreads "${srcdir}/${subdir}/${srcfile}" "${binfile}" \ + executable \ + [list debug "incdir=${objdir}" "additional_flags=${static_flag}" \ + ]] != "" } { + return -1 +} + +gdb_start +gdb_reinitialize_dir $srcdir/$subdir +gdb_load ${binfile} +gdb_test "set print sevenbit-strings" "" + + +# See if the static multi-threaded program runs. + +runto_main +gdb_test "break sem_post" +set test "Continue to main's call of sem_post" +gdb_test_multiple "continue" "$test" { + -re "Breakpoint .*, .*sem_post .*$gdb_prompt " { + pass "$test" + } + -re "Program received signal .*$gdb_prompt " { + kfail gdb/1328 "$test" + } +} + + +# See if handle SIG32 helps (a little) with a static multi-threaded +# program. + +set sig "SIG32" + +# SIGRTMIN is 37 on hppa-linux and hpux +if [istarget hppa*-*-*] { + set sig "SIG37" +} + +rerun_to_main +gdb_test "handle $sig nostop noprint pass" +set test "Handle $sig helps" +gdb_test "continue" " .*sem_post .*" "handle $sig helps" + + +# See if info threads produces anything approaching a thread list. + +set test "info threads" +gdb_test_multiple "info threads" "$test" { + -re " Thread .*$gdb_prompt " { + pass "$test" + } + -re "$gdb_prompt " { + kfail gdb/1328 "$test" + } +} + + +# Check that the program can be quit. + +set test "GDB exits with static thread program" +gdb_test_multiple "quit" "$test" { + -re "Quit anyway\\? \\(y or n\\) $" { + send_gdb "y\n" + exp_continue + } + eof { + pass "$test" + } +} Index: watchthreads2.exp =================================================================== --- watchthreads2.exp (nonexistent) +++ watchthreads2.exp (revision 816) @@ -0,0 +1,139 @@ +# This testcase is part of GDB, the GNU debugger. + +# Copyright 2009, 2010 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 3 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, see . + +# Check that watchpoints get propagated to all existing threads when the +# watchpoint is created. + +set NR_THREADS 4 +set X_INCR_COUNT 10 + +if $tracelevel { + strace $tracelevel +} + +set prms_id 0 +set bug_id 0 + +# This test verifies that a watchpoint is detected in the proper thread +# so the test is only meaningful on a system with hardware watchpoints. +if [target_info exists gdb,no_hardware_watchpoints] { + return 0; +} + +set testfile "watchthreads2" +set srcfile ${testfile}.c +set binfile ${objdir}/${subdir}/${testfile} +if {[gdb_compile_pthreads "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable [list debug "incdir=${objdir}" "additional_flags=-DNR_THREADS=$NR_THREADS -DX_INCR_COUNT=$X_INCR_COUNT"]] != "" } { + return -1 +} + +gdb_exit +gdb_start +gdb_reinitialize_dir $srcdir/$subdir +gdb_load ${binfile} + +gdb_test "set can-use-hw-watchpoints 1" "" "" + +# +# Run to `main' where we begin our tests. +# + +if ![runto_main] then { + gdb_suppress_tests +} + +gdb_test "break thread_started" \ + "Breakpoint 2 at .*: file .*${srcfile}, line .*" \ + "breakpoint on thread_started" + +# Run the program until all threads have hit thread_started. +# We use this as the vehicle to determine when gdb is aware +# of all threads (i.e. "info threads" would show all threads). + +set nr_started 0 +set message "run to thread_started" +for { set i 0 } { $i < $NR_THREADS } { incr i } { + gdb_test_multiple "continue" $message { + -re ".*Breakpoint 2, thread_started ().*$gdb_prompt $" { + incr nr_started + } + timeout { + set i $NR_THREADS + } + } +} +if { $nr_started == $NR_THREADS } { + pass "all threads started" +} else { + fail "all threads started" + # No point in continuing. + return -1 +} + +# Watch X, it will be modified by all threads. +# We want this watchpoint to be set *after* all threads are running. +gdb_test "watch x" "Hardware watchpoint 3: x" + +# Now that the watchpoint is set, we can let the threads increment X. +gdb_test "set var test_ready = 1" "" + +# While debugging. +#gdb_test "set debug infrun 1" "" + +set x_inc_line [gdb_get_line_number "X increment"] +set x_thread_loc "thread_function \\\(arg=.*\\\) at .*watchthreads.c:$x_inc_line" + +# X is incremented under a mutex, so we should get NR_THREADS * X_INCR_COUNT +# hits. +set limit [expr $NR_THREADS*$X_INCR_COUNT] +set x_count 0 +set done 0 + +set message "x watch loop" + +for {set i 0} {!$done && $i < $limit} {incr i} { + set test_flag 0 + + gdb_test_multiple "continue" $message { + -re "(.*Hardware watchpoint.*)$gdb_prompt $" { + set string $expect_out(1,string) + + if [regexp "Hardware watchpoint 3: x\[^\r\]*\r\[^\r\]*\r\[^\r\]*Old value = $x_count\[^\r\]*\r\[^\r\]*New value = [expr $x_count+1]\r" $string] { + incr x_count + set test_flag 1 + } else { + # We test for new value = old value + 1 each iteration. + # This can fail due to gdb/10116. + # This is caught after the loop exits. + } + } + -re "The program is not being run.*$gdb_prompt $" { + fail "$message (program terminated)" + } + } + + # If we fail above, don't bother continuing loop. + if { $test_flag == 0 } { + set done 1 + } +} + +if { $i == $limit } { + pass "all threads incremented x" +} else { + kfail "gdb/10116" "gdb can drop watchpoints in multithreaded app" +} Index: thread_check.exp =================================================================== --- thread_check.exp (nonexistent) +++ thread_check.exp (revision 816) @@ -0,0 +1,92 @@ +# Copyright (C) 2004, 2007, 2008, 2009, 2010 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 3 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, see . + +# This file was written by Manoj Iyer. (manjo@austin.ibm.com) +# Test break points and single step on thread functions. +# +# Test Purpose: +# - Test that breakpoints, continue in a threaded application works. +# On powerpc64-unknown-linux-gnu system, running kernel version +# 2.6.5-7.71-pseries64 this test is known to fail due to kernel bug +# in ptrace system call. +# +# Test Strategy: +# - thread_check.c creates 2 threads +# - start gdb +# - create 2 breakpoints #1 main() #2 tf() (the thread function) +# - run gdb till #1 main() breakpoint is reached +# - continue to breakpoint #2 tf() +# - delete all breakpoints +# - exit gdb. + +if $tracelevel then { + strace $tracelevel +} + +set prms_id 0 +set bug_id 0 + +set testfile "thread_check" +set srcfile ${testfile}.c +set binfile ${objdir}/${subdir}/${testfile} + +if {[gdb_compile_pthreads "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable [list debug "incdir=${objdir}"]] != "" } { + return -1 +} + + +gdb_start +gdb_reinitialize_dir $srcdir/$subdir +gdb_load ${binfile} + +if ![runto_main] then { + fail "Can't run to main" + return 1; +} + + +# +# set breakpoint at thread fucntion tf +# +gdb_test "break tf" \ + "Breakpoint.*at.* file .*$srcfile, line.*" \ + "breakpoint at tf" + + +# +# +# continue to tf() breakpoint #2 +# +gdb_test "continue" \ + ".*Breakpoint 2,.*tf.*at.*$srcfile:.*" \ + "continue to tf" + +# +# backtrace from thread function. +# +gdb_test "backtrace" \ + "#0 .*tf .*at .*$srcfile:.*" \ + "backtrace from thread function" + + +# +# delete all breakpoints +# +delete_breakpoints + +# +# exit gdb +# +gdb_exit Index: thread-unwindonsignal.exp =================================================================== --- thread-unwindonsignal.exp (nonexistent) +++ thread-unwindonsignal.exp (revision 816) @@ -0,0 +1,117 @@ +# Copyright (C) 2008, 2010 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 3 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, see . + +# Test use of unwindonsignal when a hand function call that gets interrupted +# by a signal in another thread. + +set NR_THREADS 4 + +if $tracelevel then { + strace $tracelevel +} + +set testfile "interrupted-hand-call" +set srcfile ${testfile}.c +set binfile ${objdir}/${subdir}/${testfile} + +if {[gdb_compile_pthreads "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable [list debug "incdir=${objdir}" "additional_flags=-DNR_THREADS=$NR_THREADS"]] != "" } { + return -1 +} + +# Some targets can't do function calls, so don't even bother with this +# test. +if [target_info exists gdb,cannot_call_functions] { + setup_xfail "*-*-*" 2416 + fail "This target can not call functions" + continue +} + +gdb_exit +gdb_start +gdb_reinitialize_dir $srcdir/$subdir +gdb_load ${binfile} + +if { ![runto_main] } { + fail "Can't run to main" + return 0 +} + +gdb_test "break all_threads_running" \ + "Breakpoint 2 at .*: file .*${srcfile}, line .*" \ + "breakpoint on all_threads_running" + +# Run the program and make sure GDB reports that we stopped after +# hitting breakpoint 2 in all_threads_running(). + +gdb_test "continue" \ + ".*Breakpoint 2, all_threads_running ().*" \ + "run to all_threads_running" + +# NOTE: Don't turn on scheduler-locking here. +# We want the main thread (hand_call_with_signal) and +# thread 1 (sigabrt_handler) to both run. + +# Do turn on unwindonsignal. +# We want to test gdb handling of the current thread changing when +# unwindonsignal is in effect. +gdb_test "set unwindonsignal on" \ + "" \ + "setting unwindonsignal" +gdb_test "show unwindonsignal" \ + "Unwinding of stack .* is on." \ + "showing unwindonsignal" + +gdb_test "call hand_call_with_signal()" \ + "The program received a signal.*" \ + "hand-call interrupted by signal in another thread" + +# Verify dummy stack frame is still present. +# ??? Should unwindonsignal still apply even if the program stops +# because of a signal in another thread? + +gdb_test "maint print dummy-frames" ".*stack=.*" "dummy stack frame present" + +# GDB 6.8 would perform the unwindonsignal, but on the thread that stopped, +# not the thread with the hand-called function. +# This is tested by verifying only one thread has main in its backtrace. + +gdb_test_multiple "thread apply all bt" "wrong thread not unwound" { + -re ".* in main .* in main .*$gdb_prompt $" { + fail "wrong thread not unwound" + } + -re ".* in main .*$gdb_prompt $" { + pass "wrong thread not unwound" + } +} + +# Continuing now should exit the hand-call and pop the dummy frame. + +gdb_test "continue" "" "finish hand-call" + +gdb_test_multiple "maint print dummy-frames" "dummy frame popped" { + -re ".*stack=.*$gdb_prompt $" { + fail "dummy frame popped" + } + -re ".*$gdb_prompt $" { + pass "dummy frame popped" + } +} + +# Continue one last time, the program should exit normally. + +gdb_test "continue" "Program exited normally." \ + "continue to program exit" + +return 0 Index: killed.exp =================================================================== --- killed.exp (nonexistent) +++ killed.exp (revision 816) @@ -0,0 +1,104 @@ +# Copyright 2002, 2003, 2005, 2007, 2008, 2009, 2010 +# 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 3 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, see . + +# Please email any bugs, comments, and/or additions to this file to: +# bug-gdb@gnu.org + +# This is a regression test for gdb/568 in the sources.redhat.com +# GNATS database. As of early June 2002, GDB could get sort of wedged +# debugging the program `killed.c': +# +# $ $D6/gdb/gdb -nw killed +# GNU gdb 2002-06-11-cvs +# Copyright 2002 Free Software Foundation, Inc. +# GDB is free software, covered by the GNU General Public License, and you are +# welcome to change it and/or distribute copies of it under certain conditions. +# Type "show copying" to see the conditions. +# There is absolutely no warranty for GDB. Type "show warranty" for details. +# This GDB was configured as "i686-pc-linux-gnu"... +# (gdb) run +# Starting program: /home/jimb/foo/play/killed +# [New Thread 1024 (LWP 6487)] +# [New Thread 2049 (LWP 6488)] +# [New Thread 1026 (LWP 6489)] +# Cannot find user-level thread for LWP 6487: generic error +# (gdb) quit +# The program is running. Exit anyway? (y or n) y +# Cannot find thread 2049: generic error +# (gdb) kill +# Kill the program being debugged? (y or n) y +# Cannot find thread 2049: generic error +# (gdb) The program is running. Exit anyway? (y or n) y +# Cannot find thread 2049: generic error +# (gdb) +# [7]+ Stopped $D6/gdb/gdb -nw killed +# $ kill %7 +# +# [7]+ Stopped $D6/gdb/gdb -nw killed +# $ kill -9 %7 +# +# [7]+ Stopped $D6/gdb/gdb -nw killed +# $ +# [7]+ Killed $D6/gdb/gdb -nw killed +# $ + +if $tracelevel then { + strace $tracelevel +} + +set prms_id 0 +set bug_id 0 + +set testfile "killed" +set srcfile ${testfile}.c +set binfile ${objdir}/${subdir}/${testfile} + +if {[gdb_compile_pthreads "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable [list debug "incdir=${objdir}"]] != "" } { + return -1 +} + + +gdb_start +gdb_reinitialize_dir $srcdir/$subdir +gdb_load ${binfile} + +gdb_run_cmd +gdb_expect { + -re "$gdb_prompt $" { + pass "run program to completion" + } + timeout { + fail "run program to completion (timeout)" + } +} + +# Try to quit. +send_gdb "quit\n" +gdb_expect { + -re "Quit anyway\\? \\(y or n\\) $" { + send_gdb "y\n" + exp_continue + } + eof { + pass "GDB exits after multi-threaded program exits messily" + } + -re "Cannot find thread ${decimal}: generic error\[\r\n\]*$gdb_prompt $" { + kfail "gdb/568" "GDB exits after multi-threaded program exits messily" + } + timeout { + fail "GDB exits after multi-threaded program exits messily (timeout)" + } +} Index: hand-call-in-threads.c =================================================================== --- hand-call-in-threads.c (nonexistent) +++ hand-call-in-threads.c (revision 816) @@ -0,0 +1,127 @@ +/* Test case for hand function calls in multi-threaded program. + + Copyright 2008, 2010 Free Software Foundation, Inc. + + This file is part of GDB. + + 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 3 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, see . */ + +#include +#include +#include +#include +#include + +#ifndef NR_THREADS +#define NR_THREADS 4 +#endif + +int thread_count; + +pthread_mutex_t thread_count_mutex; + +pthread_cond_t thread_count_condvar; + +void +incr_thread_count (void) +{ + pthread_mutex_lock (&thread_count_mutex); + ++thread_count; + if (thread_count == NR_THREADS) + pthread_cond_signal (&thread_count_condvar); + pthread_mutex_unlock (&thread_count_mutex); +} + +void +cond_wait (pthread_cond_t *cond, pthread_mutex_t *mut) +{ + pthread_mutex_lock (mut); + pthread_cond_wait (cond, mut); + pthread_mutex_unlock (mut); +} + +void +noreturn (void) +{ + pthread_mutex_t mut; + pthread_cond_t cond; + + pthread_mutex_init (&mut, NULL); + pthread_cond_init (&cond, NULL); + + /* Wait for a condition that will never be signaled, so we effectively + block the thread here. */ + cond_wait (&cond, &mut); +} + +void * +forever_pthread (void *unused) +{ + incr_thread_count (); + noreturn (); +} + +void +hand_call (void) +{ +} + +/* Wait until all threads are running. */ + +void +wait_all_threads_running (void) +{ + pthread_mutex_lock (&thread_count_mutex); + if (thread_count == NR_THREADS) + { + pthread_mutex_unlock (&thread_count_mutex); + return; + } + pthread_cond_wait (&thread_count_condvar, &thread_count_mutex); + if (thread_count == NR_THREADS) + { + pthread_mutex_unlock (&thread_count_mutex); + return; + } + pthread_mutex_unlock (&thread_count_mutex); + printf ("failed waiting for all threads to start\n"); + abort (); +} + +/* Called when all threads are running. + Easy place for a breakpoint. */ + +void +all_threads_running (void) +{ +} + +int +main (void) +{ + pthread_t forever[NR_THREADS]; + int i; + + pthread_mutex_init (&thread_count_mutex, NULL); + pthread_cond_init (&thread_count_condvar, NULL); + + for (i = 0; i < NR_THREADS; ++i) + pthread_create (&forever[i], NULL, forever_pthread, NULL); + + wait_all_threads_running (); + all_threads_running (); + + return 0; +} +
hand-call-in-threads.c Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +Id \ No newline at end of property Index: tls-nodebug.c =================================================================== --- tls-nodebug.c (nonexistent) +++ tls-nodebug.c (revision 816) @@ -0,0 +1,10 @@ +/* Test accessing TLS based variable without any debug info compiled. */ + +#include + +__thread int thread_local = 42; + +int main(void) +{ + return 0; +}
tls-nodebug.c Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +Id \ No newline at end of property Index: sigthread.exp =================================================================== --- sigthread.exp (nonexistent) +++ sigthread.exp (revision 816) @@ -0,0 +1,55 @@ +# sigthread.exp -- Expect script to test thread and signal interaction +# Copyright (C) 2007, 2008, 2009, 2010 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 3 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, see . */ + +set testfile sigthread +set srcfile ${testfile}.c +set binfile ${objdir}/${subdir}/${testfile} + +if {[gdb_compile_pthreads "${srcdir}/${subdir}/${srcfile}" "${binfile}" \ + executable { debug }] != "" } { + return -1 +} + +gdb_exit +gdb_start +gdb_reinitialize_dir $srcdir/$subdir +gdb_load ${binfile} + +if ![runto_main] then { + fail "Can't run to main" + return 0 +} + +gdb_test "handle SIGUSR1 nostop noprint pass" +gdb_test "handle SIGUSR2 nostop noprint pass" + +send_gdb "continue\n" +gdb_expect { + -re "Continuing" { + pass "continue" + } + timeout { + fail "continue (timeout)" + } +} + +# For this to work we must be sure to consume the "Continuing." +# message first, or GDB's signal handler may not be in place. +after 500 {send_gdb "\003"} + +# Make sure we do not get an internal error from hitting Control-C +# while many signals are flying back and forth. +gdb_test "" "Program received signal SIGINT.*" "stop with control-c" Index: pthreads.exp =================================================================== --- pthreads.exp (nonexistent) +++ pthreads.exp (revision 816) @@ -0,0 +1,329 @@ +# Copyright (C) 1996, 1997, 1999, 2000, 2001, 2002, 2003, 2004, 2007, 2008, +# 2009, 2010 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 3 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, see . + +# This file was written by Fred Fish. (fnf@cygnus.com) + +if $tracelevel then { + strace $tracelevel +} + +set prms_id 0 +set bug_id 0 + +# This only works with native configurations +if ![isnative] then { + return +} + +set testfile "pthreads" +set srcfile ${testfile}.c +set binfile ${objdir}/${subdir}/${testfile} + +# regexp for "horizontal" text (i.e. doesn't include newline or +# carriage return) +set horiz "\[^\n\r\]*" + +if [istarget "*-*-linux"] then { + set target_cflags "-D_MIT_POSIX_THREADS" +} else { + set target_cflags "" +} + +if {[gdb_compile_pthreads "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable [list debug "incdir=${objdir}"]] != "" } { + return -1 +} + + +# Start with a fresh gdb. + +gdb_exit +gdb_start +gdb_reinitialize_dir $srcdir/$subdir +gdb_load ${binfile} + +gdb_test "set print sevenbit-strings" "" +#gdb_test "set print address off" "" +gdb_test "set width 0" "" + +# We'll need this when we send_gdb a ^C to GDB. Need to do it before we +# run the program and gdb starts saving and restoring tty states. +# On Ultrix, we don't need it and it is really slow (because shell_escape +# doesn't use vfork). +if ![istarget "*-*-ultrix*"] then { + gdb_test "shell stty intr '^C'" "" +} + +proc all_threads_running {} { + global gdb_prompt + global srcfile + + # Reset all the counters to zero. + gdb_test "set var common_routine::hits=0" "" + gdb_test "set var common_routine::from_thread1=0" "" + gdb_test "set var common_routine::from_thread2=0" "" + gdb_test "set var common_routine::from_main=0" "" + gdb_test "set var common_routine::full_coverage=0" "" + + # Disable all breakpoints. + gdb_test "disable" "" + + # Set up a breakpoint that will cause us to stop when we have + # been called 15 times. This should be plenty of time to allow + # every thread to run at least once, since each thread sleeps for + # one second between calls to common_routine. + gdb_test "tbreak common_routine if hits >= 15" "" + + # Start all the threads running again and wait for the inferior + # to stop. Since no other breakpoints are set at this time + # we should stop only when we have been previously called 15 times. + + send_gdb "continue\n" + gdb_expect { + -re "Continuing.*common_routine.*at.*$srcfile.*$gdb_prompt $" {} + default { + fail "continue until common routine run 15 times" + return 0 + } + timeout { + fail "continue until common routine run 15 times (timeout)" + return 0 + } + } + + # Check that we stopped when we actually expected to stop, by + # verifying that there have been 15 previous hits. + + # NOTE: Because of synchronization behavior, it is possible for + # more than one thread to increment "hits" between one breakpoint + # trap and the next. So stopping after 16 or 17 hits should be + # considered acceptable. + + send_gdb "p common_routine::hits\n" + gdb_expect { + -re ".*= 15\r\n$gdb_prompt $" { + pass "stopped before calling common_routine 15 times" + } + -re ".*= 16\r\n$gdb_prompt $" { + pass "stopped before calling common_routine 15 times (16 times)" + } + -re ".*= 17\r\n$gdb_prompt $" { + pass "stopped before calling common_routine 15 times (17 times)" + } + default { + fail "stopped before calling common_routine 15 times" + return 0 + } + -re ".*$gdb_prompt $" { + fail "stopped before calling common_routine 15 times" + return 0 + } + timeout { + fail "stopped before calling common_routine 15 times (timeout)" + return 0 + } + } + + # Also check that all of the threads have run, which will only be true + # if the full_coverage variable is set. + + send_gdb "p common_routine::full_coverage\n" + gdb_expect { + -re ".* = 1.*$gdb_prompt $" {} + -re ".* = 0.*$gdb_prompt $" { + fail "some threads didn't run" + return 0 + } + default { + fail "some threads didn't run" + return 0 + } + timeout { + fail "some threads didn't run (timeout)" + return 0 + } + } + + # Looks fine, return success. + return 1 +} + +proc test_startup {} { + global srcdir srcfile gdb_prompt expect_out + global horiz + global main_id thread1_id thread2_id + + # We should be able to do an info threads before starting any others. + send_gdb "info threads\n" + gdb_expect { + -re ".*Thread.*main.*$gdb_prompt $" { + pass "info threads" + } + -re "\r\n$gdb_prompt $" { + unsupported "gdb does not support pthreads for this machine" + return 0 + } + } + + # 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 .*$srcfile.*" + 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 .*$srcfile.*" + 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 +} + +proc check_control_c {} { + global gdb_prompt + + # Verify that all threads are running. + if [all_threads_running] then { + pass "All threads running after startup" + } + + # Send a continue followed by ^C to the process to stop it. + send_gdb "continue\n" + gdb_expect { + -re "Continuing." { + pass "Continue with all threads running" + } + timeout { + fail "Continue with all threads running (timeout)" + } + } + after 2000 + send_gdb "\003" + set description "Stopped with a ^C" + gdb_expect { + -re "Program received signal SIGINT.*$gdb_prompt $" { + pass $description + } + -re "Quit.*$gdb_prompt $" { + pass $description + } + timeout { + fail "$description (timeout)" + return 1; + } + } + gdb_test "bt" "" + + # Verify that all threads can be run again after a ^C stop. + if [all_threads_running] then { + pass "All threads running after continuing from ^C stop" + } + return 0; +} + +proc check_backtraces {} { + global gdb_prompt main_id thread1_id thread2_id + + # Check that the "thread apply N backtrace" command works + + gdb_test "thread apply $main_id backtrace" \ + ".* 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 + # three threads with a single gdb command + + gdb_test "thread apply $main_id $thread1_id $thread2_id bt" \ + ".* in main .* in thread1 .* in thread2.*" \ + "apply backtrace command to all three threads" + + # Check that we can do thread specific backtraces + # This also tests that we can do thread specific breakpoints. + + gdb_test "break common_routine thread $thread2_id" \ + "Breakpoint .* at 0x.* file .* line .*" \ + "set break at common_routine in thread 2" + + send_gdb "continue\n" + gdb_expect { + -re "Breakpoint .* common_routine \\(arg=2\\).*" { + pass "continue to bkpt at common_routine in thread 2" + send_gdb "backtrace\n" + gdb_expect { + -re "#0.*common_routine \\(arg=2\\).*#1.*thread2.*" { + pass "backtrace from thread 2 bkpt in common_routine" + } + default { + fail "backtrace from thread 2 bkpt in common_routine" + } + timeout { + fail "backtrace from thread 2 bkpt in common_routine (timeout)" + } + } + } + -re "Breakpoint .* common_routine \\(arg=0\\).*" { + fail "continue to bkpt at common_routine in thread 2 (arg=0)" + } + -re "Breakpoint .* common_routine \\(arg=1\\).*" { + fail "continue to bkpt at common_routine in thread 2 (arg=1)" + } + -re ".*$gdb_prompt" { + fail "continue to bkpt at common_routine in thread 2" + } + default { + fail "continue to bkpt at common_routine in thread 2 (default)" + } + timeout { + fail "continue to bkpt at common_routine in thread 2 (timeout)" + } + } +} + +setup_xfail "alpha-*-osf*" +if [runto_main] then { + clear_xfail "alpha-*-osf*" + if [test_startup] then { + if [check_control_c] then { + warning "Could not stop child with ^C; skipping rest of tests.\n" + return; + } + check_backtraces + } +} +clear_xfail "alpha-*-osf*" Index: tls2.c =================================================================== --- tls2.c (nonexistent) +++ tls2.c (revision 816) @@ -0,0 +1,25 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2008, 2009, 2010 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 3 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, see . */ + +extern __thread int a_thread_local; +__thread int file2_thread_local; + +void +function_referencing_a_thread_local (void) +{ + a_thread_local = a_thread_local; +}
tls2.c Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +Id \ No newline at end of property Index: step.exp =================================================================== --- step.exp (nonexistent) +++ step.exp (revision 816) @@ -0,0 +1,197 @@ +# step.exp -- Expect script to test gdb with step.c +# Copyright (C) 1992, 1997, 2007, 2008, 2009, 2010 +# 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 3 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, see . + +# This file was written by Hiro Sugawara. (hiro@lynx.com) +# +# This test really needs some major surgery to be acceptable, but +# I'm just about burnt out on lynx work, so I'm not doing it now. +# +# * The test has an indeterminate number of pass/fails +# for each run (it runs a small group of tests until +# it's timer kicks off). This is very bad for nightly +# automated regression testing. +# +# * It tries to "step" from withint he prologue of a +# function. This isn't support in gdb (it's going +# to act like a continue). +# +# * This test rarely check that it stopped in sensible +# places. (see previous bullet -- this test doesn't +# catch the fact it continued rather than stepped) + + +if $tracelevel then { + strace $tracelevel +} + +set program_exited 0 + +proc set_bp { where } { + global gdb_prompt + + send_gdb "break $where\n" + # The first regexp is what we get with -g, the second without -g. + gdb_expect { + -re "Break.* at .*: file .*, line \[0-9\]*.*$gdb_prompt $" {} + -re "Breakpoint \[0-9\]* at 0x\[0-9a-f\]*.*$gdb_prompt $" {} + -re "$gdb_prompt $" { fail "setting breakpoint at $where" ; return 0 } + timeout { fail "setting breakpoint at $where (timeout)" ; return 0 } + } + pass "set_bp" +} + +proc step_it { cmd } { + global gdb_prompt + global program_exited + + send_gdb "$cmd\n" + gdb_expect { + -re "0x\[0-9A-Fa-f\]* *in.*\r\n$gdb_prompt $" { pass "step_it"; return 0 } + -re "0x\[0-9A-Fa-f\]* *\[0-9\]*.*\r\n$gdb_prompt $" { pass "step_it"; return 1 } + -re "Program exited .*\n$gdb_prompt $" { + set program_exited 1 + return -1 + } + -re "$gdb_prompt $" { fail "single-stepping ($cmd).\n" ; return -1 } + timeout { fail "single-stepping ($cmd) timout.\n" ; return -1 } + } +} + +proc step_inst {} { + step_it "stepi" +} + +proc step_source {} { + step_it "step" +} + +proc continue_all {} { + global gdb_prompt + + send_gdb "continue\n" + gdb_expect { + -re "Breakpoint \[0-9\]*, thread\[0-9\]* .*$gdb_prompt $" { + pass "continue_all" + return 0 + } + -re "Program exited .*\n$gdb_prompt $" { + set program_exited 1 + return 1; + } + -re "$gdb_prompt $" { fail "continue" ; return -1 } + timeout { fail "continue (timeout)" ; return -1 } + } +} + +proc check_threads { num_threads } { + global gdb_prompt + + set curr_thread 0 + send_gdb "info threads\n" + while { $num_threads > 0 } { + gdb_expect { + -re "\\* *\[0-9\]* process \[0-9\]* thread \[0-9\]* .*\n" { + incr curr_thread + set num_threads [expr $num_threads - 1] + } + -re " *\[0-9\]* process \[0-9\]* thread \[0-9\]* .*\n" { + set num_threads [expr $num_threads - 1] + } + -re "$gdb_prompt $" { + if { $num_threads < 0 } { + fail "check_threads (too many)" ; return -1 + } + break + } + timeout { fail "check_threads (timeout)" ; return -1 } + } + } + + if { $curr_thread == 0 } { + fail "check_threads (no current thread)\n" + return -1 + } + if { $curr_thread > 1 } { + fail "check_threads (more than one current thread)\n" + return -1 + } + return 0 +} + +proc test_cond_wait {} { + global program_exited + + set_bp 135 + runto 179 + while { 1 } { + set stepi_counter 0 + while { [step_inst] } { + if { $program_exited } { break } + incr stepi_counter + if { $stepi_counter > 30 } { + fail "too many stepi's per line\n" + return -1 + } + } + if { $program_exited } { break } + step_source + if { $program_exited } { break } + continue_all + if { $program_exited } { break } + check_threads 3 + } +} + +proc do_tests {} { + global prms_id + global bug_id + global subdir + global objdir + global srcdir + global binfile + global gdb_prompt + + set prms_id 0 + set bug_id 0 + + # Start with a fresh gdb. + + gdb_exit + gdb_start + gdb_reinitialize_dir $srcdir/$subdir + gdb_load $objdir/$subdir/$binfile + + send_gdb "set width 0\n" + gdb_expect -re "$gdb_prompt $" + + test_cond_wait +} + +# Check to see if we have an executable to test. If not, then either we +# haven't tried to compile one, or the compilation failed for some reason. +# In either case, just notify the user and skip the tests in this file. + +set binfile "step" +set srcfile "step.c" + +if ![file exists $objdir/$subdir/$binfile] then { + if $all_flag then { + warning "$binfile does not exist; tests suppressed." + } +} else { + do_tests +} Index: interrupted-hand-call.c =================================================================== --- interrupted-hand-call.c (nonexistent) +++ interrupted-hand-call.c (revision 816) @@ -0,0 +1,149 @@ +/* Test case for hand function calls interrupted by a signal in another thread. + + Copyright 2008, 2010 Free Software Foundation, Inc. + + This file is part of GDB. + + 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 3 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, see . */ + +#include +#include +#include +#include +#include +#include + +#ifndef NR_THREADS +#define NR_THREADS 4 +#endif + +pthread_t threads[NR_THREADS]; + +/* Number of threads currently running. */ +int thread_count; + +pthread_mutex_t thread_count_mutex; + +pthread_cond_t thread_count_condvar; + +sig_atomic_t sigabrt_received; + +void +incr_thread_count (void) +{ + pthread_mutex_lock (&thread_count_mutex); + ++thread_count; + if (thread_count == NR_THREADS) + pthread_cond_signal (&thread_count_condvar); + pthread_mutex_unlock (&thread_count_mutex); +} + +void +cond_wait (pthread_cond_t *cond, pthread_mutex_t *mut) +{ + pthread_mutex_lock (mut); + pthread_cond_wait (cond, mut); + pthread_mutex_unlock (mut); +} + +void +noreturn (void) +{ + pthread_mutex_t mut; + pthread_cond_t cond; + + pthread_mutex_init (&mut, NULL); + pthread_cond_init (&cond, NULL); + + /* Wait for a condition that will never be signaled, so we effectively + block the thread here. */ + cond_wait (&cond, &mut); +} + +void * +thread_entry (void *unused) +{ + incr_thread_count (); + noreturn (); +} + +void +sigabrt_handler (int signo) +{ + sigabrt_received = 1; +} + +/* Helper to test a hand-call being "interrupted" by a signal on another + thread. */ + +void +hand_call_with_signal (void) +{ + const struct timespec ts = { 0, 10000000 }; /* 0.01 sec */ + + sigabrt_received = 0; + pthread_kill (threads[0], SIGABRT); + while (! sigabrt_received) + nanosleep (&ts, NULL); +} + +/* Wait until all threads are running. */ + +void +wait_all_threads_running (void) +{ + pthread_mutex_lock (&thread_count_mutex); + if (thread_count == NR_THREADS) + { + pthread_mutex_unlock (&thread_count_mutex); + return; + } + pthread_cond_wait (&thread_count_condvar, &thread_count_mutex); + if (thread_count == NR_THREADS) + { + pthread_mutex_unlock (&thread_count_mutex); + return; + } + pthread_mutex_unlock (&thread_count_mutex); + printf ("failed waiting for all threads to start\n"); + abort (); +} + +/* Called when all threads are running. + Easy place for a breakpoint. */ + +void +all_threads_running (void) +{ +} + +int +main (void) +{ + int i; + + signal (SIGABRT, sigabrt_handler); + + pthread_mutex_init (&thread_count_mutex, NULL); + pthread_cond_init (&thread_count_condvar, NULL); + + for (i = 0; i < NR_THREADS; ++i) + pthread_create (&threads[i], NULL, thread_entry, NULL); + + wait_all_threads_running (); + all_threads_running (); + + return 0; +} +
interrupted-hand-call.c Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +Id \ No newline at end of property Index: manythreads.exp =================================================================== --- manythreads.exp (nonexistent) +++ manythreads.exp (revision 816) @@ -0,0 +1,175 @@ +# manythreads.exp -- Expect script to test stopping many threads +# Copyright (C) 2004, 2006, 2007, 2008, 2009, 2010 +# 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 3 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, see . + +# This file was written by Jeff Johnston. (jjohnstn@redhat.com) + +if $tracelevel then { + strace $tracelevel +} + +set prms_id 0 +set bug_id 0 + +set testfile "manythreads" +set srcfile ${testfile}.c +set binfile ${objdir}/${subdir}/${testfile} + +if {[gdb_compile_pthreads "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable [list debug "incdir=${objdir}"]] != "" } { + return -1 +} + +gdb_start +gdb_reinitialize_dir $srcdir/$subdir +gdb_load ${binfile} +gdb_test "set print sevenbit-strings" "" +runto_main + +# We'll need this when we send_gdb a ^C to GDB. Need to do it before we +# run the program and gdb starts saving and restoring tty states. +# On Ultrix, we don't need it and it is really slow (because shell_escape +# doesn't use vfork). +if ![istarget "*-*-ultrix*"] then { + gdb_test "shell stty intr '^C'" "" +} + +set message "first continue" +gdb_test_multiple "continue" "first continue" { + -re "error:.*$gdb_prompt $" { + fail "$message" + } + -re "Continuing" { + pass "$message" + } +} + +# Wait one second. This is better than the TCL "after" command, because +# we don't lose GDB's output while we do it. +remote_expect host 1 { timeout { } } + +# Send a Ctrl-C and verify that we can do info threads and continue +send_gdb "\003" +set message "stop threads 1" +gdb_test_multiple "" "stop threads 1" { + -re "\\\[New \[^\]\]*\\\]\r\n" { + exp_continue + } + -re "\\\[\[^\]\]* exited\\\]\r\n" { + exp_continue + } + -re "Thread \[^\n\]* executing\r\n" { + exp_continue + } + -re "Program received signal SIGINT.*$gdb_prompt $" { + pass "$message" + } + timeout { + fail "$message (timeout)" + } +} + +set cmd "info threads" +set ok 0 +gdb_test_multiple $cmd $cmd { + -re " 1 Thread " { + set ok 1 + exp_continue + } + -re ".*\r\n" { + # Eat this line and continue, to prevent the buffer overflowing. + exp_continue + } + -re "$gdb_prompt $" { + if { $ok } { + pass $cmd + } else { + fail $cmd + } + } +} + +set message "second continue" +gdb_test_multiple "continue" "second continue" { + -re "error:.*$gdb_prompt $" { + fail "$message" + } + -re "Continuing" { + pass "$message" + } +} + +# Wait another second. If the program stops on its own, GDB has failed +# to handle duplicate SIGINTs sent to multiple threads. +set failed 0 +remote_expect host 1 { + -re "\\\[New \[^\]\]*\\\]\r\n" { + exp_continue -continue_timer + } + -re "\\\[\[^\]\]* exited\\\]\r\n" { + exp_continue -continue_timer + } + -re "Thread \[^\n\]* executing\r\n" { + exp_continue -continue_timer + } + -re "Program received signal SIGINT.*$gdb_prompt $" { + if { $failed == 0 } { + fail "check for duplicate SIGINT" + } + send_gdb "continue\n" + set failed 1 + exp_continue + } + timeout { + if { $failed == 0 } { + pass "check for duplicate SIGINT" + } + } +} + +# Send another Ctrl-C and verify that we can do info threads and quit +send_gdb "\003" +set message "stop threads 2" +gdb_test_multiple "" "stop threads 2" { + -re "\\\[New \[^\]\]*\\\]\r\n" { + exp_continue + } + -re "\\\[\[^\]\]* exited\\\]\r\n" { + exp_continue + } + -re "Thread \[^\n\]* executing\r\n" { + exp_continue + } + -re "Program received signal SIGINT.*$gdb_prompt $" { + pass "$message" + } + timeout { + fail "$message (timeout)" + } +} + +gdb_test_multiple "quit" "GDB exits after stopping multithreaded program" { + -re "Quit anyway\\? \\(y or n\\) $" { + send_gdb "y\n" + exp_continue + } + eof { + pass "GDB exits after stopping multithreaded program" + } + timeout { + fail "GDB exits after stopping multithreaded program (timeout)" + } +} + Index: watchthreads-reorder.exp =================================================================== --- watchthreads-reorder.exp (nonexistent) +++ watchthreads-reorder.exp (revision 816) @@ -0,0 +1,103 @@ +# This testcase is part of GDB, the GNU debugger. + +# Copyright 2009, 2010 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 3 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, see . + +# Test GDB can cope with two watchpoints being hit by different threads at the +# same time, GDB reports one of them and after "continue" to report the other +# one GDB should not be confused by differently set watchpoints that time. +# This is the goal of "reorder1". "reorder0" tests the basic functionality of +# two watchpoints being hit at the same time, without reordering them during the +# stop. The formerly broken functionality is due to the all-stop mode default +# "show breakpoint always-inserted" being "off". Formerly the remembered hit +# could be assigned during continuation of a thread with pending SIGTRAP to the +# different/new watchpoint, just based on the watchpoint/debug register number. + +if {(![istarget "i?86-*-*"] && ![istarget "x86_64-*-*"] + && ![istarget "ia64-*-*"]) + || [target_info exists gdb,no_hardware_watchpoints] + || ![istarget *-*-linux*]} { + return 0 +} + +set testfile "watchthreads-reorder" +set srcfile ${testfile}.c +set binfile ${objdir}/${subdir}/${testfile} +if {[gdb_compile_pthreads "${srcdir}/${subdir}/${srcfile}" ${binfile} executable [list debug additional_flags=-lrt]] != "" } { + return -1 +} + +foreach reorder {0 1} { + + global pf_prefix + set prefix_test $pf_prefix + lappend pf_prefix "reorder$reorder:" + + clean_restart $testfile + + gdb_test "set can-use-hw-watchpoints 1" + + if ![runto_main] { + return -1 + } + + # Use "rwatch" as "watch" would report the watchpoint changed just based on its + # read memory value during a stop by unrelated event. We are interested in not + # losing the hardware watchpoint trigger. + + gdb_test "rwatch thread1_rwatch" "Hardware read watchpoint \[0-9\]+: thread1_rwatch" + set test "rwatch thread2_rwatch" + gdb_test_multiple $test $test { + -re "Target does not support this type of hardware watchpoint\\.\r\n$gdb_prompt $" { + # ppc64 supports at most 1 hw watchpoints. + unsupported $test + return + } + -re "Hardware read watchpoint \[0-9\]+: thread2_rwatch\r\n$gdb_prompt $" { + pass $test + } + } + gdb_breakpoint [gdb_get_line_number "break-at-exit"] + + # The watchpoints can happen in arbitrary order depending on random: + # SEL: Found 2 SIGTRAP events, selecting #[01] + # As GDB contains no srand() on the specific host/OS it will behave always the + # same. Such order cannot be guaranteed for GDB in general. + + gdb_test "continue" \ + "Hardware read watchpoint \[0-9\]+: thread\[12\]_rwatch\r\n\r\nValue = 0\r\n0x\[0-9a-f\]+ in thread\[12\]_func .*" \ + "continue a" + + if $reorder { + # GDB orders watchpoints by their addresses so inserting new variables + # with lower addresses will shift the former watchpoints to higher + # debug registers. + + gdb_test "rwatch unused1_rwatch" "Hardware read watchpoint \[0-9\]+: unused1_rwatch" + gdb_test "rwatch unused2_rwatch" "Hardware read watchpoint \[0-9\]+: unused2_rwatch" + } + + gdb_test "continue" \ + "Hardware read watchpoint \[0-9\]+: thread\[12\]_rwatch\r\n\r\nValue = 0\r\n0x\[0-9a-f\]+ in thread\[12\]_func .*" \ + "continue b" + + # While the debug output itself is not checked in this testcase one bug was + # found in the DEBUG_INFRUN code path. + gdb_test "set debug infrun 1" + + gdb_continue_to_breakpoint "break-at-exit" ".*break-at-exit.*" + + set pf_prefix $prefix_test +} Index: watchthreads.exp =================================================================== --- watchthreads.exp (nonexistent) +++ watchthreads.exp (revision 816) @@ -0,0 +1,199 @@ +# This testcase is part of GDB, the GNU debugger. + +# Copyright 2004, 2007, 2008, 2009, 2010 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 3 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, see . + +# Check that GDB can support multiple watchpoints across threads. + +if $tracelevel { + strace $tracelevel +} + +set prms_id 0 +set bug_id 0 + +# This test verifies that a watchpoint is detected in the proper thread +# so the test is only meaningful on a system with hardware watchpoints. +if [target_info exists gdb,no_hardware_watchpoints] { + return 0; +} + +proc target_no_stopped_data { } { + return [istarget s390*-*-*] +} + +set testfile "watchthreads" +set srcfile ${testfile}.c +set binfile ${objdir}/${subdir}/${testfile} +if {[gdb_compile_pthreads "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable [list debug "incdir=${objdir}"]] != "" } { + return -1 +} + +gdb_exit +gdb_start +gdb_reinitialize_dir $srcdir/$subdir +gdb_load ${binfile} + +gdb_test "set can-use-hw-watchpoints 1" "" "" + +# +# Run to `main' where we begin our tests. +# + +if ![runto_main] then { + gdb_suppress_tests +} + +set args_0 0 +set args_1 0 + +# Watch values that will be modified by distinct threads. +gdb_test "watch args\[0\]" "Hardware watchpoint 2: args\\\[0\\\]" +gdb_test "watch args\[1\]" "Hardware watchpoint 3: args\\\[1\\\]" +set hwwp_2_enabled 1 +set hwwp_3_enabled 1 + +set init_line [gdb_get_line_number "Init value"] +set inc_line [gdb_get_line_number "Loop increment"] +set main_loc "main \\\(\\\) at .*watchthreads.c:$init_line" +set thread0_loc "thread_function \\\(arg=0x0\\\) at .*watchthreads.c:$inc_line" +set thread1_loc "thread_function \\\(arg=0x1\\\) at .*watchthreads.c:$inc_line" + +# Loop and continue to allow both watchpoints to be triggered. +for {set i 0} {$i < 30} {incr i} { + set test_flag_0 0 + set test_flag_1 0 + set test_flag 0 + gdb_test_multiple "continue" "threaded watch loop" { + -re "(.*Hardware watchpoint.*)$gdb_prompt $" { + # At least one hardware watchpoint was hit. Check if both were. + set string $expect_out(1,string) + + if [regexp "Hardware watchpoint 2: args\\\[0\\\]\[^\r\]*\r\[^\r\]*\r\[^\r\]*Old value = $args_0\[^\r\]*\r\[^\r\]*New value = [expr $args_0+1]\r" $string] { + incr args_0 + incr test_flag_0 + } + if [regexp "Hardware watchpoint 3: args\\\[1\\\]\[^\r\]*\r\[^\r\]*\r\[^\r\]*Old value = $args_1\[^\r\]*\r\[^\r\]*New value = [expr $args_1+1]\r" $string] { + incr args_1 + incr test_flag_1 + } + + set expected_loc "bogus location" + if { $test_flag_0 == 1 && $test_flag_1 == 0 && $args_0 == 1 } { + set expected_loc $main_loc + } elseif { $test_flag_0 == 0 && $test_flag_1 == 1 && $args_1 == 1 } { + set expected_loc $main_loc + } elseif { $test_flag_0 == 1 && $test_flag_1 == 0 } { + set expected_loc $thread0_loc + } elseif { $test_flag_0 == 0 && $test_flag_1 == 1 } { + set expected_loc $thread1_loc + } elseif { $test_flag_0 + $test_flag_1 == 2 } { + # On S/390, or any other system which can not report the + # stopped data address, it is OK to report two watchpoints + # at once in this test. Make sure the reported location + # corresponds to at least one of the watchpoints (and not, + # e.g., __nptl_create_event). On other systems, we should + # report the two watchpoints serially. + if { [target_no_stopped_data] } { + set expected_loc "($main_loc|$thread0_loc|$thread1_loc)" + } + } + + if [ regexp "$expected_loc" $string ] { + set test_flag 1 + } else { + fail "threaded watch loop" + } + + # If one of the watchpoints is disabled, we'd better not stop there. + if { !$hwwp_2_enabled && $test_flag_0 } { + fail "disabled hw watchpoint 2 triggered" + } + if { !$hwwp_3_enabled && $test_flag_1 } { + fail "disabled hw watchpoint 3 triggered" + } + + # If we get to 10 in one of the watched locations disable it so we + # see some of the other watched location. + # 10 is chosen so we're guaranteed to come through here. + if { $hwwp_2_enabled && $hwwp_3_enabled } { + if { $args_0 >= 10 && $hwwp_2_enabled } { + gdb_test "disable 2" "" + set hwwp_2_enabled 0 + } elseif { $args_1 >= 10 && $hwwp_3_enabled } { + gdb_test "disable 3" "" + set hwwp_3_enabled 0 + } + } + } + } + + # If we fail above, don't bother continuing loop + if { $test_flag == 0 } { + set i 30; + } +} + +# Print success message if loop succeeded. +if { $test_flag == 1 } { + pass "threaded watch loop" +} + +# Verify that we hit first watchpoint in main thread. +set message "first watchpoint on args\[0\] hit" +if { $args_0 > 0 } { + pass $message +} else { + fail $message +} + +# Verify that we hit second watchpoint in main thread. +set message "first watchpoint on args\[1\] hit" +if { $args_1 > 0 } { + pass $message +} else { + fail $message +} + +# Verify that we hit first watchpoint in child thread. +set message "watchpoint on args\[0\] hit in thread" +if { $args_0 > 1 } { + pass $message +} else { + fail $message +} + +# Verify that we hit second watchpoint in child thread. +set message "watchpoint on args\[1\] hit in thread" +if { $args_1 > 1 } { + pass $message +} else { + fail $message +} + +# Verify that all watchpoint hits are accounted for. +set message "combination of threaded watchpoints = 30" +if { [target_no_stopped_data] } { + # See above. If we allow two watchpoints to be hit at once, we + # may have more than 30 hits total. + set result [expr $args_0 + $args_1 >= 30] +} else { + set result [expr $args_0 + $args_1 == 30] +} +if { $result } { + pass $message +} else { + fail $message +}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.