Rewrite non-continuable watchpoints handling
authorPedro Alves <palves@redhat.com>
Wed, 15 Oct 2014 19:18:30 +0000 (20:18 +0100)
committerPedro Alves <palves@redhat.com>
Wed, 15 Oct 2014 19:18:30 +0000 (20:18 +0100)
commit963f9c80cb3f12fb779cf3189072ac48946da96c
tree527f5d71df8f5e01985f508a01d460a52a831037
parent6cc83d2a4000e89e4f6f2eb33ffade2d72acfa0f
Rewrite non-continuable watchpoints handling

When GDB finds out the target triggered a watchpoint, and the target
has non-continuable watchpoints, GDB sets things up to step past the
instruction that triggered the watchpoint.  This is just like stepping
past a breakpoint, but goes through a different mechanism - it resumes
only the thread that needs to step past the watchpoint, but also
switches a "infwait state" global, that has the effect that the next
target_wait only wait for events only from that thread.

This forcing of a ptid to pass to target_wait obviously becomes a
bottleneck if we ever support stepping past different watchpoints
simultaneously (in separate processes).

It's also unnecessary -- the target should only return events for
threads that have been resumed; if no other thread than the one we're
stepping past the watchpoint has been resumed, then those other
threads should not report events.  If we couldn't assume that, then
stepping past regular breakpoints would be broken for not likewise
forcing a similar infwait_state.

So this patch eliminates infwait_state, and instead teaches keep_going
to mark step_over_info in a way that has the breakpoints module skip
inserting watchpoints (because we're stepping past one), like it skips
breakpoints when we're stepping past one.

Tested on:

 - x86_64 Fedora 20 (continuable watchpoints)
 - PPC64 Fedora 18  (non-steppable watchpoints)

gdb/
2014-10-15  Pedro Alves  <palves@redhat.com>

* breakpoint.c (should_be_inserted): Don't insert watchpoints if
trying to step past a non-steppable watchpoint.
* gdbthread.h (struct thread_info) <stepping_over_watchpoint>: New
field.
* infrun.c (struct step_over_info): Add new field
'nonsteppable_watchpoint_p' and adjust comments.
(set_step_over_info): New 'nonsteppable_watchpoint_p' parameter.
Adjust.
(clear_step_over_info): Clear nonsteppable_watchpoint_p as well.
(stepping_past_nonsteppable_watchpoint): New function.
(step_over_info_valid_p): Also return true if stepping past a
nonsteppable watchpoint.
(proceed): Adjust call to set_step_over_info.  Remove reference to
init_infwait_state.
(init_wait_for_inferior): Remove reference to init_infwait_state.
(waiton_ptid): Delete global.
(struct execution_control_state)
<stepped_after_stopped_by_watchpoint>: Delete field.
(wait_for_inferior, fetch_inferior_event): Always pass
minus_one_ptid to target_wait.
(init_thread_stepping_state): Clear 'stepping_over_watchpoint'
field.
(init_infwait_state): Delete function.
(handle_inferior_event): Remove infwait_state handling.
(handle_signal_stop) <watchpoints handling>: Adjust after
stepped_after_stopped_by_watchpoint removal.  Don't remove
breakpoints here nor set infwait_state.  Set the thread's
stepping_over_watchpoint flag, and call keep_going instead.
(keep_going): Handle stepping_over_watchpoint.  Adjust
set_step_over_info calls.
* infrun.h (stepping_past_nonsteppable_watchpoint): Declare
function.
gdb/ChangeLog
gdb/breakpoint.c
gdb/gdbthread.h
gdb/infrun.c
gdb/infrun.h