aboutsummaryrefslogtreecommitdiff
path: root/gdb/infrun.c
diff options
context:
space:
mode:
Diffstat (limited to 'gdb/infrun.c')
-rw-r--r--gdb/infrun.c139
1 files changed, 87 insertions, 52 deletions
diff --git a/gdb/infrun.c b/gdb/infrun.c
index 12f1cd3..d1a2d9b 100644
--- a/gdb/infrun.c
+++ b/gdb/infrun.c
@@ -1056,6 +1056,17 @@ delete_breakpoint_current_contents (arg)
When this function actually returns it means the inferior
should be left stopped and GDB should read more commands. */
+/* This enum encodes possible reasons for doing a target_wait, so that
+ wfi can call target_wait in one place. (Ultimately the call will be
+ moved out of the infinite loop entirely.) */
+
+enum wfi_states {
+ wfi_normal_state,
+ wfi_thread_hop_state,
+ wfi_nullified_state,
+ wfi_nonstep_watch_state
+};
+
void
wait_for_inferior ()
{
@@ -1081,6 +1092,10 @@ wait_for_inferior ()
int stepping_through_sigtramp = 0;
int new_thread_event;
int stepped_after_stopped_by_watchpoint;
+ struct target_waitstatus tmpstatus;
+ enum wfi_states wfi_state;
+ int waiton_pid;
+ struct target_waitstatus *wp;
old_cleanups = make_cleanup (delete_breakpoint_current_contents,
&step_resume_breakpoint);
@@ -1105,43 +1120,75 @@ wait_for_inferior ()
if (may_switch_from_inferior_pid)
switched_from_inferior_pid = inferior_pid;
+ wfi_state = wfi_normal_state;
+
while (1)
{
- overlay_cache_invalid = 1;
+ if (wfi_state == wfi_normal_state)
+ {
+ overlay_cache_invalid = 1;
- /* We have to invalidate the registers BEFORE calling target_wait because
- they can be loaded from the target while in target_wait. This makes
- remote debugging a bit more efficient for those targets that provide
- critical registers as part of their normal status mechanism. */
+ /* We have to invalidate the registers BEFORE calling
+ target_wait because they can be loaded from the target
+ while in target_wait. This makes remote debugging a bit
+ more efficient for those targets that provide critical
+ registers as part of their normal status mechanism. */
- registers_changed ();
+ registers_changed ();
+ waiton_pid = -1;
+ wp = &w;
+ }
if (target_wait_hook)
- pid = target_wait_hook (-1, &w);
+ pid = target_wait_hook (waiton_pid, wp);
else
- pid = target_wait (-1, &w);
-
- /* Since we've done a wait, we have a new event. Don't carry
- over any expectations about needing to step over a
- breakpoint. */
- thread_step_needed = 0;
+ pid = target_wait (waiton_pid, wp);
- /* See comments where a TARGET_WAITKIND_SYSCALL_RETURN event is
- serviced in this loop, below. */
- if (enable_hw_watchpoints_after_wait)
+ switch (wfi_state)
{
- TARGET_ENABLE_HW_WATCHPOINTS (inferior_pid);
- enable_hw_watchpoints_after_wait = 0;
- }
+ case wfi_normal_state:
+ /* Since we've done a wait, we have a new event. Don't
+ carry over any expectations about needing to step over a
+ breakpoint. */
+ thread_step_needed = 0;
- stepped_after_stopped_by_watchpoint = 0;
+ /* See comments where a TARGET_WAITKIND_SYSCALL_RETURN event
+ is serviced in this loop, below. */
+ if (enable_hw_watchpoints_after_wait)
+ {
+ TARGET_ENABLE_HW_WATCHPOINTS (inferior_pid);
+ enable_hw_watchpoints_after_wait = 0;
+ }
+ stepped_after_stopped_by_watchpoint = 0;
+ break;
+
+ case wfi_thread_hop_state:
+ insert_breakpoints ();
- /* Gross.
+ /* We need to restart all the threads now,
+ * unles we're running in scheduler-locked mode.
+ * FIXME: shouldn't we look at CURRENTLY_STEPPING ()?
+ */
+ if (scheduler_mode == schedlock_on)
+ target_resume (pid, 0, TARGET_SIGNAL_0);
+ else
+ target_resume (-1, 0, TARGET_SIGNAL_0);
+ wfi_state = wfi_normal_state;
+ continue;
- We goto this label from elsewhere in wait_for_inferior when we want
- to continue the main loop without calling "wait" and trashing the
- waitstatus contained in W. */
- have_waited:
+ case wfi_nullified_state:
+ break;
+
+ case wfi_nonstep_watch_state:
+ insert_breakpoints ();
+
+ /* FIXME-maybe: is this cleaner than setting a flag? Does it
+ handle things like signals arriving and other things happening
+ in combination correctly? */
+ stepped_after_stopped_by_watchpoint = 1;
+ break;
+ }
+ wfi_state = wfi_normal_state;
flush_cached_frames ();
@@ -1536,11 +1583,10 @@ wait_for_inferior ()
/* FIXME: What if a signal arrives instead of the
single-step happening? */
- if (target_wait_hook)
- target_wait_hook (pid, &w);
- else
- target_wait (pid, &w);
- insert_breakpoints ();
+ waiton_pid = pid;
+ wp = &w;
+ wfi_state = wfi_thread_hop_state;
+ continue;
}
/* We need to restart all the threads now,
@@ -1551,7 +1597,7 @@ wait_for_inferior ()
target_resume (pid, 0, TARGET_SIGNAL_0);
else
target_resume (-1, 0, TARGET_SIGNAL_0);
- continue;
+ continue;
}
else
{
@@ -1673,21 +1719,17 @@ wait_for_inferior ()
/* if (INSTRUCTION_NULLIFIED && CURRENTLY_STEPPING ()) */
if (INSTRUCTION_NULLIFIED)
{
- struct target_waitstatus tmpstatus;
-
registers_changed ();
target_resume (pid, 1, TARGET_SIGNAL_0);
/* We may have received a signal that we want to pass to
the inferior; therefore, we must not clobber the waitstatus
- in W. So we call wait ourselves, then continue the loop
- at the "have_waited" label. */
- if (target_wait_hook)
- target_wait_hook (pid, &tmpstatus);
- else
- target_wait (pid, &tmpstatus);
+ in W. */
- goto have_waited;
+ wfi_state = wfi_nullified_state;
+ waiton_pid = pid;
+ wp = &tmpstatus;
+ continue;
}
/* It may not be necessary to disable the watchpoint to stop over
@@ -1727,17 +1769,10 @@ wait_for_inferior ()
registers_changed ();
target_resume (pid, 1, TARGET_SIGNAL_0); /* Single step */
- if (target_wait_hook)
- target_wait_hook (pid, &w);
- else
- target_wait (pid, &w);
- insert_breakpoints ();
-
- /* FIXME-maybe: is this cleaner than setting a flag? Does it
- handle things like signals arriving and other things happening
- in combination correctly? */
- stepped_after_stopped_by_watchpoint = 1;
- goto have_waited;
+ waiton_pid = pid;
+ wp = &w;
+ wfi_state = wfi_nonstep_watch_state;
+ continue;
}
/* It may be possible to simply continue after a watchpoint. */
@@ -2477,7 +2512,7 @@ wait_for_inferior ()
s = find_pc_symtab (stop_pc);
if (s && s->language != language_asm)
- SKIP_PROLOGUE (stop_func_start);
+ stop_func_start = SKIP_PROLOGUE (stop_func_start);
}
sal = find_pc_line (stop_func_start, 0);
/* Use the step_resume_break to step until