[gdbserver] linux-low.c: better starvation avoidance, handle non-stop mode too
This patch applies the same starvation avoidance improvements of the previous patch to the Linux gdbserver side. Without this, the test added by the following commit (gdb.threads/non-stop-fair-events.exp) always fails with time outs. gdb/gdbserver/ 2015-01-09 Pedro Alves <palves@redhat.com> * linux-low.c (step_over_bkpt): Move higher up in the file. (handle_extended_wait): Don't store the stop_pc here. (get_stop_pc): Adjust comments and rename to ... (check_stopped_by_breakpoint): ... this. Record whether the LWP stopped for a software breakpoint or hardware breakpoint. (thread_still_has_status_pending_p): New function. (status_pending_p_callback): Use thread_still_has_status_pending_p. If the event is no longer interesting, resume the LWP. (handle_tracepoints): Add assert. (maybe_move_out_of_jump_pad): Remove cancel_breakpoints call. (wstatus_maybe_breakpoint): New function. (cancel_breakpoint): Delete function. (check_stopped_by_watchpoint): New function, factored out from linux_low_filter_event. (lp_status_maybe_breakpoint): Delete function. (linux_low_filter_event): Remove filter_ptid argument. Leave thread group exits pending here. Store the LWP's stop PC. Always leave events pending. (linux_wait_for_event_filtered): Pull all events out of the kernel, and leave them all pending. (count_events_callback, select_event_lwp_callback): Consider all events. (cancel_breakpoints_callback, linux_cancel_breakpoints): Delete. (select_event_lwp): Only give preference to the stepping LWP in all-stop mode. Adjust comments. (ignore_event): New function. (linux_wait_1): Delete 'retry' label. Use ignore_event. Remove references to cancel_breakpoints. Adjust to renames. Also give equal priority to all LWPs that have had events in non-stop mode. If reporting a software breakpoint event, unadjust the LWP's PC. (linux_wait): If linux_wait_1 returned an ignored event, retry. (stuck_in_jump_pad_callback, move_out_of_jump_pad_callback): Adjust. (linux_resume_one_lwp): Store the LWP's PC. Adjust. (resume_status_pending_p): Use thread_still_has_status_pending_p. (linux_stopped_by_watchpoint): Adjust. (linux_target_ops): Remove reference to linux_cancel_breakpoints. * linux-low.h (enum lwp_stop_reason): New. (struct lwp_info) <stop_pc>: Adjust comment. <stopped_by_watchpoint>: Delete field. <stop_reason>: New field. * linux-x86-low.c (x86_linux_prepare_to_resume): Adjust. * mem-break.c (software_breakpoint_inserted_here) (hardware_breakpoint_inserted_here): New function. * mem-break.h (software_breakpoint_inserted_here) (hardware_breakpoint_inserted_here): Declare. * target.h (struct target_ops) <cancel_breakpoints>: Remove field. (cancel_breakpoints): Delete. * tracepoint.c (clear_installed_tracepoints, stop_tracing) (upload_fast_traceframes): Remove references to cancel_breakpoints.
This commit is contained in:
parent
9c02b52532
commit
582511be69
8 changed files with 518 additions and 358 deletions
|
@ -1,3 +1,58 @@
|
||||||
|
2015-01-09 Pedro Alves <palves@redhat.com>
|
||||||
|
|
||||||
|
* linux-low.c (step_over_bkpt): Move higher up in the file.
|
||||||
|
(handle_extended_wait): Don't store the stop_pc here.
|
||||||
|
(get_stop_pc): Adjust comments and rename to ...
|
||||||
|
(check_stopped_by_breakpoint): ... this. Record whether the LWP
|
||||||
|
stopped for a software breakpoint or hardware breakpoint.
|
||||||
|
(thread_still_has_status_pending_p): New function.
|
||||||
|
(status_pending_p_callback): Use
|
||||||
|
thread_still_has_status_pending_p. If the event is no longer
|
||||||
|
interesting, resume the LWP.
|
||||||
|
(handle_tracepoints): Add assert.
|
||||||
|
(maybe_move_out_of_jump_pad): Remove cancel_breakpoints call.
|
||||||
|
(wstatus_maybe_breakpoint): New function.
|
||||||
|
(cancel_breakpoint): Delete function.
|
||||||
|
(check_stopped_by_watchpoint): New function, factored out from
|
||||||
|
linux_low_filter_event.
|
||||||
|
(lp_status_maybe_breakpoint): Delete function.
|
||||||
|
(linux_low_filter_event): Remove filter_ptid argument.
|
||||||
|
Leave thread group exits pending here. Store the LWP's stop PC.
|
||||||
|
Always leave events pending.
|
||||||
|
(linux_wait_for_event_filtered): Pull all events out of the
|
||||||
|
kernel, and leave them all pending.
|
||||||
|
(count_events_callback, select_event_lwp_callback): Consider all
|
||||||
|
events.
|
||||||
|
(cancel_breakpoints_callback, linux_cancel_breakpoints): Delete.
|
||||||
|
(select_event_lwp): Only give preference to the stepping LWP in
|
||||||
|
all-stop mode. Adjust comments.
|
||||||
|
(ignore_event): New function.
|
||||||
|
(linux_wait_1): Delete 'retry' label. Use ignore_event. Remove
|
||||||
|
references to cancel_breakpoints. Adjust to renames. Also give
|
||||||
|
equal priority to all LWPs that have had events in non-stop mode.
|
||||||
|
If reporting a software breakpoint event, unadjust the LWP's PC.
|
||||||
|
(linux_wait): If linux_wait_1 returned an ignored event, retry.
|
||||||
|
(stuck_in_jump_pad_callback, move_out_of_jump_pad_callback):
|
||||||
|
Adjust.
|
||||||
|
(linux_resume_one_lwp): Store the LWP's PC. Adjust.
|
||||||
|
(resume_status_pending_p): Use thread_still_has_status_pending_p.
|
||||||
|
(linux_stopped_by_watchpoint): Adjust.
|
||||||
|
(linux_target_ops): Remove reference to linux_cancel_breakpoints.
|
||||||
|
* linux-low.h (enum lwp_stop_reason): New.
|
||||||
|
(struct lwp_info) <stop_pc>: Adjust comment.
|
||||||
|
<stopped_by_watchpoint>: Delete field.
|
||||||
|
<stop_reason>: New field.
|
||||||
|
* linux-x86-low.c (x86_linux_prepare_to_resume): Adjust.
|
||||||
|
* mem-break.c (software_breakpoint_inserted_here)
|
||||||
|
(hardware_breakpoint_inserted_here): New function.
|
||||||
|
* mem-break.h (software_breakpoint_inserted_here)
|
||||||
|
(hardware_breakpoint_inserted_here): Declare.
|
||||||
|
* target.h (struct target_ops) <cancel_breakpoints>: Remove field.
|
||||||
|
(cancel_breakpoints): Delete.
|
||||||
|
* tracepoint.c (clear_installed_tracepoints, stop_tracing)
|
||||||
|
(upload_fast_traceframes): Remove references to
|
||||||
|
cancel_breakpoints.
|
||||||
|
|
||||||
2015-01-09 Pedro Alves <palves@redhat.com>
|
2015-01-09 Pedro Alves <palves@redhat.com>
|
||||||
|
|
||||||
* thread-db.c (find_new_threads_callback): Ignore thread if the
|
* thread-db.c (find_new_threads_callback): Ignore thread if the
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -230,6 +230,24 @@ extern struct linux_target_ops the_low_target;
|
||||||
#define get_thread_lwp(thr) ((struct lwp_info *) (inferior_target_data (thr)))
|
#define get_thread_lwp(thr) ((struct lwp_info *) (inferior_target_data (thr)))
|
||||||
#define get_lwp_thread(lwp) ((lwp)->thread)
|
#define get_lwp_thread(lwp) ((lwp)->thread)
|
||||||
|
|
||||||
|
/* Reasons an LWP last stopped. */
|
||||||
|
|
||||||
|
enum lwp_stop_reason
|
||||||
|
{
|
||||||
|
/* Either not stopped, or stopped for a reason that doesn't require
|
||||||
|
special tracking. */
|
||||||
|
LWP_STOPPED_BY_NO_REASON,
|
||||||
|
|
||||||
|
/* Stopped by a software breakpoint. */
|
||||||
|
LWP_STOPPED_BY_SW_BREAKPOINT,
|
||||||
|
|
||||||
|
/* Stopped by a hardware breakpoint. */
|
||||||
|
LWP_STOPPED_BY_HW_BREAKPOINT,
|
||||||
|
|
||||||
|
/* Stopped by a watchpoint. */
|
||||||
|
LWP_STOPPED_BY_WATCHPOINT
|
||||||
|
};
|
||||||
|
|
||||||
/* This struct is recorded in the target_data field of struct thread_info.
|
/* This struct is recorded in the target_data field of struct thread_info.
|
||||||
|
|
||||||
On linux ``all_threads'' is keyed by the LWP ID, which we use as the
|
On linux ``all_threads'' is keyed by the LWP ID, which we use as the
|
||||||
|
@ -269,8 +287,9 @@ struct lwp_info
|
||||||
/* When stopped is set, the last wait status recorded for this lwp. */
|
/* When stopped is set, the last wait status recorded for this lwp. */
|
||||||
int last_status;
|
int last_status;
|
||||||
|
|
||||||
/* When stopped is set, this is where the lwp stopped, with
|
/* When stopped is set, this is where the lwp last stopped, with
|
||||||
decr_pc_after_break already accounted for. */
|
decr_pc_after_break already accounted for. If the LWP is
|
||||||
|
running, this is the address at which the lwp was resumed. */
|
||||||
CORE_ADDR stop_pc;
|
CORE_ADDR stop_pc;
|
||||||
|
|
||||||
/* If this flag is set, STATUS_PENDING is a waitstatus that has not yet
|
/* If this flag is set, STATUS_PENDING is a waitstatus that has not yet
|
||||||
|
@ -278,9 +297,9 @@ struct lwp_info
|
||||||
int status_pending_p;
|
int status_pending_p;
|
||||||
int status_pending;
|
int status_pending;
|
||||||
|
|
||||||
/* STOPPED_BY_WATCHPOINT is non-zero if this LWP stopped with a data
|
/* The reason the LWP last stopped, if we need to track it
|
||||||
watchpoint trap. */
|
(breakpoint, watchpoint, etc.) */
|
||||||
int stopped_by_watchpoint;
|
enum lwp_stop_reason stop_reason;
|
||||||
|
|
||||||
/* On architectures where it is possible to know the data address of
|
/* On architectures where it is possible to know the data address of
|
||||||
a triggered watchpoint, STOPPED_DATA_ADDRESS is non-zero, and
|
a triggered watchpoint, STOPPED_DATA_ADDRESS is non-zero, and
|
||||||
|
|
|
@ -805,7 +805,7 @@ x86_linux_prepare_to_resume (struct lwp_info *lwp)
|
||||||
lwp->arch_private->debug_registers_changed = 0;
|
lwp->arch_private->debug_registers_changed = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (clear_status || lwp->stopped_by_watchpoint)
|
if (clear_status || lwp->stop_reason == LWP_STOPPED_BY_WATCHPOINT)
|
||||||
x86_linux_dr_set (ptid, DR_STATUS, 0);
|
x86_linux_dr_set (ptid, DR_STATUS, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1610,6 +1610,40 @@ breakpoint_inserted_here (CORE_ADDR addr)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* See mem-break.h. */
|
||||||
|
|
||||||
|
int
|
||||||
|
software_breakpoint_inserted_here (CORE_ADDR addr)
|
||||||
|
{
|
||||||
|
struct process_info *proc = current_process ();
|
||||||
|
struct raw_breakpoint *bp;
|
||||||
|
|
||||||
|
for (bp = proc->raw_breakpoints; bp != NULL; bp = bp->next)
|
||||||
|
if (bp->raw_type == raw_bkpt_type_sw
|
||||||
|
&& bp->pc == addr
|
||||||
|
&& bp->inserted)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* See mem-break.h. */
|
||||||
|
|
||||||
|
int
|
||||||
|
hardware_breakpoint_inserted_here (CORE_ADDR addr)
|
||||||
|
{
|
||||||
|
struct process_info *proc = current_process ();
|
||||||
|
struct raw_breakpoint *bp;
|
||||||
|
|
||||||
|
for (bp = proc->raw_breakpoints; bp != NULL; bp = bp->next)
|
||||||
|
if (bp->raw_type == raw_bkpt_type_hw
|
||||||
|
&& bp->pc == addr
|
||||||
|
&& bp->inserted)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
validate_inserted_breakpoint (struct raw_breakpoint *bp)
|
validate_inserted_breakpoint (struct raw_breakpoint *bp)
|
||||||
{
|
{
|
||||||
|
|
|
@ -90,6 +90,16 @@ int breakpoint_here (CORE_ADDR addr);
|
||||||
|
|
||||||
int breakpoint_inserted_here (CORE_ADDR addr);
|
int breakpoint_inserted_here (CORE_ADDR addr);
|
||||||
|
|
||||||
|
/* Returns TRUE if there's any inserted software breakpoint at
|
||||||
|
ADDR. */
|
||||||
|
|
||||||
|
int software_breakpoint_inserted_here (CORE_ADDR addr);
|
||||||
|
|
||||||
|
/* Returns TRUE if there's any inserted hardware (code) breakpoint at
|
||||||
|
ADDR. */
|
||||||
|
|
||||||
|
int hardware_breakpoint_inserted_here (CORE_ADDR addr);
|
||||||
|
|
||||||
/* Clear all breakpoint conditions and commands associated with a
|
/* Clear all breakpoint conditions and commands associated with a
|
||||||
breakpoint. */
|
breakpoint. */
|
||||||
|
|
||||||
|
|
|
@ -304,9 +304,6 @@ struct target_ops
|
||||||
the pause call. */
|
the pause call. */
|
||||||
void (*unpause_all) (int unfreeze);
|
void (*unpause_all) (int unfreeze);
|
||||||
|
|
||||||
/* Cancel all pending breakpoints hits in all threads. */
|
|
||||||
void (*cancel_breakpoints) (void);
|
|
||||||
|
|
||||||
/* Stabilize all threads. That is, force them out of jump pads. */
|
/* Stabilize all threads. That is, force them out of jump pads. */
|
||||||
void (*stabilize_threads) (void);
|
void (*stabilize_threads) (void);
|
||||||
|
|
||||||
|
@ -453,13 +450,6 @@ int kill_inferior (int);
|
||||||
(*the_target->unpause_all) (unfreeze); \
|
(*the_target->unpause_all) (unfreeze); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
#define cancel_breakpoints() \
|
|
||||||
do \
|
|
||||||
{ \
|
|
||||||
if (the_target->cancel_breakpoints) \
|
|
||||||
(*the_target->cancel_breakpoints) (); \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
#define stabilize_threads() \
|
#define stabilize_threads() \
|
||||||
do \
|
do \
|
||||||
{ \
|
{ \
|
||||||
|
|
|
@ -2443,7 +2443,6 @@ clear_installed_tracepoints (void)
|
||||||
struct tracepoint *prev_stpoint;
|
struct tracepoint *prev_stpoint;
|
||||||
|
|
||||||
pause_all (1);
|
pause_all (1);
|
||||||
cancel_breakpoints ();
|
|
||||||
|
|
||||||
prev_stpoint = NULL;
|
prev_stpoint = NULL;
|
||||||
|
|
||||||
|
@ -3433,9 +3432,6 @@ stop_tracing (void)
|
||||||
We can't now, since we may be getting here due to the inferior
|
We can't now, since we may be getting here due to the inferior
|
||||||
agent calling us. */
|
agent calling us. */
|
||||||
pause_all (1);
|
pause_all (1);
|
||||||
/* Since we're removing breakpoints, cancel breakpoint hits,
|
|
||||||
possibly related to the breakpoints we're about to delete. */
|
|
||||||
cancel_breakpoints ();
|
|
||||||
|
|
||||||
/* Stop logging. Tracepoints can still be hit, but they will not be
|
/* Stop logging. Tracepoints can still be hit, but they will not be
|
||||||
recorded. */
|
recorded. */
|
||||||
|
@ -6538,7 +6534,6 @@ upload_fast_traceframes (void)
|
||||||
trace_debug ("Done uploading traceframes [%d]\n", curr_tbctrl_idx);
|
trace_debug ("Done uploading traceframes [%d]\n", curr_tbctrl_idx);
|
||||||
|
|
||||||
pause_all (1);
|
pause_all (1);
|
||||||
cancel_breakpoints ();
|
|
||||||
|
|
||||||
delete_breakpoint (about_to_request_buffer_space_bkpt);
|
delete_breakpoint (about_to_request_buffer_space_bkpt);
|
||||||
about_to_request_buffer_space_bkpt = NULL;
|
about_to_request_buffer_space_bkpt = NULL;
|
||||||
|
|
Loading…
Reference in a new issue