diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog index 694d4adc1d..fa6cd7d4ff 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,3 +1,10 @@ +2009-04-27 Doug Evans + + * gdb.threads/watchthreads.c (main): Initialize args before starting + the threads. Plus formatting cleanup. + * gdb.threads/watchthreads.exp: Avoid errant failures due to + biased scheduling of one thread. + 2009-04-27 Jerome Guitton * gdb.cp/templates.cc (GetMax): New template. diff --git a/gdb/testsuite/gdb.threads/watchthreads.c b/gdb/testsuite/gdb.threads/watchthreads.c index 16d3ce3be8..7a51f573a9 100644 --- a/gdb/testsuite/gdb.threads/watchthreads.c +++ b/gdb/testsuite/gdb.threads/watchthreads.c @@ -22,34 +22,49 @@ #include #include -void *thread_function(void *arg); /* Pointer to function executed by each thread */ +void *thread_function (void *arg); /* Function executed by each thread. */ #define NUM 5 unsigned int args[NUM+1]; -int main() { +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++) { - args[i] = 1; /* Init value. */ - res = pthread_create(&threads[i], - NULL, - thread_function, - (void *) 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); + exit (EXIT_SUCCESS); } -void *thread_function(void *arg) { +void * +thread_function (void *arg) +{ int my_number = (long) arg; int *myp = (int *) &args[my_number]; @@ -59,6 +74,6 @@ void *thread_function(void *arg) { (*myp) ++; usleep (1); /* Loop increment. */ } - pthread_exit(NULL); + pthread_exit (NULL); } diff --git a/gdb/testsuite/gdb.threads/watchthreads.exp b/gdb/testsuite/gdb.threads/watchthreads.exp index 8859c6d3d9..6f32af5839 100644 --- a/gdb/testsuite/gdb.threads/watchthreads.exp +++ b/gdb/testsuite/gdb.threads/watchthreads.exp @@ -62,8 +62,10 @@ 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 [expr [gdb_get_line_number "Init value"]+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" @@ -114,6 +116,27 @@ for {set i 0} {$i < 30} {incr i} { } 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 + } + } } }