Use keep_going in proceed and start_step_over too

The main motivation of this patch is sharing more code between the
proceed (starting the inferior for the first time) and keep_going
(restarting the inferior after handling an event) paths and using the
step_over_chain queue now embedded in the thread_info object for
pending in-line step-overs too (instead of just for displaced
stepping).

So this commit:

 - splits out a new keep_going_pass_signal function out of keep_going
   that is just like keep_going except for the bits that clear the
   signal to pass if the signal is set to "handle nopass".

 - makes proceed use keep_going too.

 - Makes start_step_over use keep_going_pass_signal instead of lower
   level displaced stepping things.

One user visible change: if inserting breakpoints while trying to
proceed fails, we now get:

  (gdb) si
  Warning:
  Could not insert hardware watchpoint 7.
  Could not insert hardware breakpoints:
  You may have requested too many hardware breakpoints/watchpoints.

  Command aborted.
  (gdb)

while before we only saw warnings with no indication that the command
was cancelled:

  (gdb) si
  Warning:
  Could not insert hardware watchpoint 7.
  Could not insert hardware breakpoints:
  You may have requested too many hardware breakpoints/watchpoints.

  (gdb)

Tested on x86_64-linux-gnu, ppc64-linux-gnu and s390-linux-gnu.

gdb/ChangeLog:
2015-08-07  Pedro Alves  <palves@redhat.com>

	* gdbthread.h (struct thread_info) <prev_pc>: Extend comment.
	* infrun.c (struct execution_control_state): Move higher up in the
	file.
	(reset_ecs): New function.
	(start_step_over): Now returns int.  Rewrite to use
	keep_going_pass_signal instead of manually starting a displaced step.
	(resume): Don't call set_running here.  If displaced stepping
	can't start now, clear trap_expected.
	(find_thread_needs_step_over): Delete function.
	(proceed): Set up finish_thread_state_cleanup.  Call set_running.
	If the current thread needs a step over, push it in the step-over
	chain.  Don't set insert breakpoints nor call resume directly
	here.  Instead rewrite to use start_step_over and
	keep_going_pass_signal.
	(finish_step_over): New function.
	(handle_signal_stop): Call finish_step_over instead of
	start_step_over.
	(switch_back_to_stepped_thread): If the event thread needs another
	step-over do that first.  Use start_step_over.
	(keep_going_pass_signal): New function, factored out from ...
	(keep_going): ... here.
	(_initialize_infrun): Comment moved here.
	* thread.c (set_running_thread): New function.
	(set_running, finish_thread_state): Use set_running_thread.
This commit is contained in:
Pedro Alves
2015-08-07 17:23:58 +01:00
parent c2829269f5
commit 4d9d9d0423
4 changed files with 364 additions and 321 deletions

View File

@ -852,44 +852,62 @@ thread_change_ptid (ptid_t old_ptid, ptid_t new_ptid)
observer_notify_thread_ptid_changed (old_ptid, new_ptid);
}
/* Helper for set_running, that marks one thread either running or
stopped. */
static int
set_running_thread (struct thread_info *tp, int running)
{
int started = 0;
if (running && tp->state == THREAD_STOPPED)
started = 1;
tp->state = running ? THREAD_RUNNING : THREAD_STOPPED;
if (!running)
{
/* If the thread is now marked stopped, remove it from
the step-over queue, so that we don't try to resume
it until the user wants it to. */
if (tp->step_over_next != NULL)
thread_step_over_chain_remove (tp);
}
return started;
}
void
set_running (ptid_t ptid, int running)
{
struct thread_info *tp;
int all = ptid_equal (ptid, minus_one_ptid);
int any_started = 0;
/* We try not to notify the observer if no thread has actually changed
the running state -- merely to reduce the number of messages to
frontend. Frontend is supposed to handle multiple *running just fine. */
if (all || ptid_is_pid (ptid))
{
int any_started = 0;
for (tp = thread_list; tp; tp = tp->next)
if (all || ptid_get_pid (tp->ptid) == ptid_get_pid (ptid))
{
if (tp->state == THREAD_EXITED)
continue;
if (running && tp->state == THREAD_STOPPED)
if (set_running_thread (tp, running))
any_started = 1;
tp->state = running ? THREAD_RUNNING : THREAD_STOPPED;
}
if (any_started)
observer_notify_target_resumed (ptid);
}
else
{
int started = 0;
tp = find_thread_ptid (ptid);
gdb_assert (tp);
gdb_assert (tp != NULL);
gdb_assert (tp->state != THREAD_EXITED);
if (running && tp->state == THREAD_STOPPED)
started = 1;
tp->state = running ? THREAD_RUNNING : THREAD_STOPPED;
if (started)
observer_notify_target_resumed (ptid);
if (set_running_thread (tp, running))
any_started = 1;
}
if (any_started)
observer_notify_target_resumed (ptid);
}
static int
@ -1008,9 +1026,8 @@ finish_thread_state (ptid_t ptid)
continue;
if (all || ptid_get_pid (ptid) == ptid_get_pid (tp->ptid))
{
if (tp->executing && tp->state == THREAD_STOPPED)
if (set_running_thread (tp, tp->executing))
any_started = 1;
tp->state = tp->executing ? THREAD_RUNNING : THREAD_STOPPED;
}
}
}
@ -1020,9 +1037,8 @@ finish_thread_state (ptid_t ptid)
gdb_assert (tp);
if (tp->state != THREAD_EXITED)
{
if (tp->executing && tp->state == THREAD_STOPPED)
if (set_running_thread (tp, tp->executing))
any_started = 1;
tp->state = tp->executing ? THREAD_RUNNING : THREAD_STOPPED;
}
}