diff options
author | Pedro Alves <palves@redhat.com> | 2009-11-21 21:17:17 +0000 |
---|---|---|
committer | Pedro Alves <palves@redhat.com> | 2009-11-21 21:17:17 +0000 |
commit | f6bc20088048522ffb945254f59f824f5cbdaebd (patch) | |
tree | 88a4983875865ce7d3659f85c5628703923eb225 /gdb/testsuite/gdb.threads | |
parent | 8c2fb5deb3f40d81b448d54d7eaa02cde2c6e014 (diff) | |
download | gdb-f6bc20088048522ffb945254f59f824f5cbdaebd.zip gdb-f6bc20088048522ffb945254f59f824f5cbdaebd.tar.gz gdb-f6bc20088048522ffb945254f59f824f5cbdaebd.tar.bz2 |
gdb/
* breakpoint.h (struct breakpoint) <watchpoint_thread>: New field.
* breakpoint.c (watchpoint_in_thread_scope): New.
(update_watchpoint): Skip if the local watchpoint's thread doesn't
match the current thread, or if the current thread is running.
(watchpoint_check): Ditto.
(watch_command_1): Set the watchpoint's watchpoint_thread field.
gdb/testsuite/
* gdb.threads/local-watch-wrong-thread.c,
gdb.threads/local-watch-wrong-thread.exp: New files.
Diffstat (limited to 'gdb/testsuite/gdb.threads')
-rw-r--r-- | gdb/testsuite/gdb.threads/local-watch-wrong-thread.c | 88 | ||||
-rw-r--r-- | gdb/testsuite/gdb.threads/local-watch-wrong-thread.exp | 122 |
2 files changed, 210 insertions, 0 deletions
diff --git a/gdb/testsuite/gdb.threads/local-watch-wrong-thread.c b/gdb/testsuite/gdb.threads/local-watch-wrong-thread.c new file mode 100644 index 0000000..7aed14c --- /dev/null +++ b/gdb/testsuite/gdb.threads/local-watch-wrong-thread.c @@ -0,0 +1,88 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2002, 2003, 2004, 2007, 2008, 2009 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 <unistd.h> +#include <stdlib.h> +#include <pthread.h> + +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); +} diff --git a/gdb/testsuite/gdb.threads/local-watch-wrong-thread.exp b/gdb/testsuite/gdb.threads/local-watch-wrong-thread.exp new file mode 100644 index 0000000..ecd7be9 --- /dev/null +++ b/gdb/testsuite/gdb.threads/local-watch-wrong-thread.exp @@ -0,0 +1,122 @@ +# This testcase is part of GDB, the GNU debugger. + +# Copyright 2009 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 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" |