diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog index cd38459b698..aa1e22b8d3e 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,3 +1,21 @@ +2015-01-09 Pedro Alves + + * gdb.base/annota1.exp (thread_test): Use srcfile and binfile from + the global scope. Set a breakpoint after all threads are started + rather than stepping over two source lines. Expect the prompt. + * gdb.base/watch_thread_num.c (threads_started_barrier): New + global. + (NUM): Now 15. + (main): Use threads_started_barrier to wait for all threads to + start. Main thread no longer calls thread_function. Exit after + 180 seconds. + (loop): New function. + (thread_function): Wait on threads_started_barrier barrier. Call + 'loop' at each iteration. + * gdb.base/watch_thread_num.exp: Continue to breakpoint after all + threads have started, instead of hardcoding number of "next" + steps. Use an access watchpoint instead of a write watchpoint. + 2015-01-09 Pedro Alves * gdb.threads/ia64-sigill.c (threads_started_barrier): New global. diff --git a/gdb/testsuite/gdb.base/annota1.exp b/gdb/testsuite/gdb.base/annota1.exp index 239b047b17a..c19b9456a25 100644 --- a/gdb/testsuite/gdb.base/annota1.exp +++ b/gdb/testsuite/gdb.base/annota1.exp @@ -440,7 +440,7 @@ if { [remote_file host exists core] } { } proc thread_test {} { - global subdir srcdir testfile + global subdir srcdir testfile srcfile binfile global gdb_prompt old_gdb_prompt set srcfile watch_thread_num.c set binfile [standard_output_file ${testfile}-watch_thread_num] @@ -457,6 +457,9 @@ proc thread_test {} { return } + set linenum [gdb_get_line_number "all threads started"] + gdb_breakpoint "$linenum" + set gdb_prompt \ "\r\n\032\032pre-prompt\r\n$gdb_prompt \r\n\032\032prompt\r\n" @@ -465,8 +468,8 @@ proc thread_test {} { } } - gdb_test_multiple "next 2" "new thread" { - -re ".*\032\032new-thread" { + gdb_test_multiple "continue" "new thread" { + -re "\032\032new-thread.*\r\n$gdb_prompt$" { pass "new thread" } } diff --git a/gdb/testsuite/gdb.base/watch_thread_num.c b/gdb/testsuite/gdb.base/watch_thread_num.c index 1466aedba40..55b4867bd17 100644 --- a/gdb/testsuite/gdb.base/watch_thread_num.c +++ b/gdb/testsuite/gdb.base/watch_thread_num.c @@ -27,7 +27,11 @@ void *thread_function (void *arg); /* Pointer to function executed by each thread */ -#define NUM 5 +static pthread_barrier_t threads_started_barrier; + +#define NUM 15 + +static int num_threads = NUM; static unsigned int shared_var = 1; @@ -37,6 +41,8 @@ int main () { void *thread_result; long i; + pthread_barrier_init (&threads_started_barrier, NULL, NUM + 1); + for (i = 0; i < NUM; i++) { res = pthread_create (&threads[i], @@ -45,18 +51,29 @@ int main () { (void *) i); } - thread_result = thread_function ((void *) i); + pthread_barrier_wait (&threads_started_barrier); + + sleep (180); /* all threads started */ exit (EXIT_SUCCESS); } +void +loop (void) +{ +} + void *thread_function (void *arg) { int my_number = (long) arg; + + pthread_barrier_wait (&threads_started_barrier); + /* Don't run forever. Run just short of it :) */ while (shared_var > 0) { shared_var++; usleep (1); /* Loop increment. */ + loop (); } pthread_exit (NULL); diff --git a/gdb/testsuite/gdb.base/watch_thread_num.exp b/gdb/testsuite/gdb.base/watch_thread_num.exp index 571005d7d6d..d559f22386f 100644 --- a/gdb/testsuite/gdb.base/watch_thread_num.exp +++ b/gdb/testsuite/gdb.base/watch_thread_num.exp @@ -47,12 +47,14 @@ if { ![runto main] } then { gdb_test "watch shared_var thread 0" "Unknown thread 0\." "Watchpoint on invalid thread" gdb_test "watch shared_var thread" "A syntax error in expression, near `thread'\." "Invalid watch syntax" -gdb_test "Next 5" ".*" +set bpexitline [gdb_get_line_number "all threads started"] +gdb_breakpoint "$bpexitline" +gdb_continue_to_breakpoint "all threads started" -gdb_test "break thread_function" "Breakpoint \[0-9\].*" \ - "Set breakpoint at thread_function" +gdb_test "break loop" "Breakpoint \[0-9\].*" \ + "Set breakpoint at loop" -gdb_test "continue" ".*Breakpoint 2.*" "Stopped in thread_function" +gdb_test "continue" ".*Breakpoint .*loop.*" "Stopped in loop" gdb_test_multiple "thread" "Thread command" { -re ".*Current thread is (\[0-9\]*).*$gdb_prompt $" { @@ -62,15 +64,35 @@ gdb_test_multiple "thread" "Thread command" { set thread_num "$expect_out(1,string)" -gdb_test_no_output "disable 2" "Disable breakpoint 2" -gdb_test "watch shared_var thread $thread_num" "Hardware watchpoint 3: shared_var" "Watchpoint on shared variable" -gdb_test "info breakpoint 3" "stop only in thread $thread_num" +delete_breakpoints -for {set i 1} {$i <= 10} {incr i 1} { +# We use an access watchpoint rather than a write watchpoint, because +# GDB can drop the latter when multiple threads trigger events +# simultaneously, on targets with continuable watchpoints, such as +# x86. See PR breakpoints/10116. + +gdb_test "awatch shared_var thread $thread_num" \ + "Hardware access \\(read/write\\) watchpoint .*: shared_var.*" \ + "Watchpoint on shared variable" + +gdb_test "info breakpoint \$bpnum" \ + "stop only in thread $thread_num" \ + "info breakpoint shows watchpoint is thread-specific" + +for {set i 1} {$i <= 5} {incr i} { set watchpoint "Watchpoint triggered iteration $i" set check "Check thread that triggered iteration $i" - gdb_test "continue" "Hardware watchpoint 3: shared_var.*" $watchpoint + set test $watchpoint + gdb_test_multiple "continue" $test { + -re "infrun:" { + # Avoid timeouts when debugging GDB. + exp_continue + } + -re "Hardware access \\(read/write\\) watchpoint .*: shared_var.*$gdb_prompt $" { + pass $test + } + } gdb_test "thread" ".*Current thread is $thread_num .*" $check }