# This testcase is part of GDB, the GNU debugger.
-# Copyright 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
+# Copyright 2007-2020 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
# watch commands.
#
-if $tracelevel then {
- strace $tracelevel
+# This test verifies that a watchpoint is detected in the proper thread
+# so the test is only meaningful on a system with hardware watchpoints.
+# More specifically, the implementation of this test uses access
+# watchpoints, so skip it when those are not available.
+if {[skip_hw_watchpoint_access_tests]} {
+ return 0
}
-set testfile watch_thread_num
-set srcfile ${testfile}.c
-set binfile ${objdir}/${subdir}/${testfile}
+standard_testfile .c
# What compiler are we using?
#
-if [get_compiler_info ${binfile}] {
+if [get_compiler_info] {
return -1
}
return -1
}
-gdb_exit
-gdb_start
-gdb_reinitialize_dir $srcdir/$subdir
-gdb_load ${binfile}
+clean_restart ${binfile}
-if { ![runto main] } then {
+if { ![runto_main] } then {
fail "run to main"
return
}
-# Disable hardware watchpoints if necessary.
-if [target_info exists gdb,no_hardware_watchpoints] {
- gdb_test "set can-use-hw-watchpoints 0" "" ""
-}
-
-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 "watch shared_var thread 0" "Invalid thread ID: 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" {
+gdb_test_multiple "thread" "thread command" {
-re ".*Current thread is (\[0-9\]*).*$gdb_prompt $" {
- pass "Thread command"
+ pass "thread command"
}
}
set thread_num "$expect_out(1,string)"
-gdb_test "disable 2" "" "Disable breakpoint 2"
-gdb_test "watch shared_var thread $thread_num" "atchpoint 3: shared_var" "Watchpoint on shared variable"
-gdb_test "info breakpoint 3" "stop only in thread $thread_num"
+delete_breakpoints
+
+# 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.
-for {set i 1} {$i <= 10} {incr i 1} {
+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" "atchpoint 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
}