[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:
Pedro Alves 2014-12-29 19:41:07 +00:00
parent 9c02b52532
commit 582511be69
8 changed files with 518 additions and 358 deletions

View file

@ -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>
* thread-db.c (find_new_threads_callback): Ignore thread if the

File diff suppressed because it is too large Load diff

View file

@ -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_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.
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. */
int last_status;
/* When stopped is set, this is where the lwp stopped, with
decr_pc_after_break already accounted for. */
/* When stopped is set, this is where the lwp last stopped, with
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;
/* 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;
/* STOPPED_BY_WATCHPOINT is non-zero if this LWP stopped with a data
watchpoint trap. */
int stopped_by_watchpoint;
/* The reason the LWP last stopped, if we need to track it
(breakpoint, watchpoint, etc.) */
enum lwp_stop_reason stop_reason;
/* On architectures where it is possible to know the data address of
a triggered watchpoint, STOPPED_DATA_ADDRESS is non-zero, and

View file

@ -805,7 +805,7 @@ x86_linux_prepare_to_resume (struct lwp_info *lwp)
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);
}

View file

@ -1610,6 +1610,40 @@ breakpoint_inserted_here (CORE_ADDR addr)
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
validate_inserted_breakpoint (struct raw_breakpoint *bp)
{

View file

@ -90,6 +90,16 @@ int breakpoint_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
breakpoint. */

View file

@ -304,9 +304,6 @@ struct target_ops
the pause call. */
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. */
void (*stabilize_threads) (void);
@ -453,13 +450,6 @@ int kill_inferior (int);
(*the_target->unpause_all) (unfreeze); \
} while (0)
#define cancel_breakpoints() \
do \
{ \
if (the_target->cancel_breakpoints) \
(*the_target->cancel_breakpoints) (); \
} while (0)
#define stabilize_threads() \
do \
{ \

View file

@ -2443,7 +2443,6 @@ clear_installed_tracepoints (void)
struct tracepoint *prev_stpoint;
pause_all (1);
cancel_breakpoints ();
prev_stpoint = NULL;
@ -3433,9 +3432,6 @@ stop_tracing (void)
We can't now, since we may be getting here due to the inferior
agent calling us. */
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
recorded. */
@ -6538,7 +6534,6 @@ upload_fast_traceframes (void)
trace_debug ("Done uploading traceframes [%d]\n", curr_tbctrl_idx);
pause_all (1);
cancel_breakpoints ();
delete_breakpoint (about_to_request_buffer_space_bkpt);
about_to_request_buffer_space_bkpt = NULL;