diff options
Diffstat (limited to 'gdb/infrun.c')
-rw-r--r-- | gdb/infrun.c | 93 |
1 files changed, 34 insertions, 59 deletions
diff --git a/gdb/infrun.c b/gdb/infrun.c index 3c58ff2..33aa674 100644 --- a/gdb/infrun.c +++ b/gdb/infrun.c @@ -623,7 +623,7 @@ proceed_after_vfork_done (struct thread_info *thread, target_pid_to_str (thread->ptid)); switch_to_thread (thread->ptid); - clear_proceed_status (); + clear_proceed_status (0); proceed ((CORE_ADDR) -1, GDB_SIGNAL_DEFAULT, 0); } @@ -1721,15 +1721,6 @@ maybe_software_singlestep (struct gdbarch *gdbarch, CORE_ADDR pc) return hw_step; } -/* Return a ptid representing the set of threads that we will proceed, - in the perspective of the user/frontend. We may actually resume - fewer threads at first, e.g., if a thread is stopped at a - breakpoint that needs stepping-off, but that should not be visible - to the user/frontend, and neither should the frontend/user be - allowed to proceed any of the threads that happen to be stopped for - internal run control handling, if a previous command wanted them - resumed. */ - ptid_t user_visible_resume_ptid (int step) { @@ -1757,6 +1748,12 @@ user_visible_resume_ptid (int step) resume_ptid = inferior_ptid; } + /* We may actually resume fewer threads at first, e.g., if a thread + is stopped at a breakpoint that needs stepping-off, but that + should not be visible to the user/frontend, and neither should + the frontend/user be allowed to proceed any of the threads that + happen to be stopped for internal run control handling, if a + previous command wanted them resumed. */ return resume_ptid; } @@ -2032,6 +2029,11 @@ clear_proceed_status_thread (struct thread_info *tp) "infrun: clear_proceed_status_thread (%s)\n", target_pid_to_str (tp->ptid)); + /* If this signal should not be seen by program, give it zero. + Used for debugging signals. */ + if (!signal_pass_state (tp->suspend.stop_signal)) + tp->suspend.stop_signal = GDB_SIGNAL_0; + tp->control.trap_expected = 0; tp->control.step_range_start = 0; tp->control.step_range_end = 0; @@ -2051,26 +2053,24 @@ clear_proceed_status_thread (struct thread_info *tp) bpstat_clear (&tp->control.stop_bpstat); } -static int -clear_proceed_status_callback (struct thread_info *tp, void *data) -{ - if (is_exited (tp->ptid)) - return 0; - - clear_proceed_status_thread (tp); - return 0; -} - void -clear_proceed_status (void) +clear_proceed_status (int step) { if (!non_stop) { - /* In all-stop mode, delete the per-thread status of all - threads, even if inferior_ptid is null_ptid, there may be - threads on the list. E.g., we may be launching a new - process, while selecting the executable. */ - iterate_over_threads (clear_proceed_status_callback, NULL); + struct thread_info *tp; + ptid_t resume_ptid; + + resume_ptid = user_visible_resume_ptid (step); + + /* In all-stop mode, delete the per-thread status of all threads + we're about to resume, implicitly and explicitly. */ + ALL_NON_EXITED_THREADS (tp) + { + if (!ptid_match (tp->ptid, resume_ptid)) + continue; + clear_proceed_status_thread (tp); + } } if (!ptid_equal (inferior_ptid, null_ptid)) @@ -2252,6 +2252,9 @@ proceed (CORE_ADDR addr, enum gdb_signal siggnal, int step) regcache_write_pc (regcache, addr); } + if (siggnal != GDB_SIGNAL_DEFAULT) + tp->suspend.stop_signal = siggnal; + /* Record the interpreter that issued the execution command that caused this thread to resume. If the top level interpreter is MI/async, and the execution command was a CLI command @@ -2318,38 +2321,6 @@ proceed (CORE_ADDR addr, enum gdb_signal siggnal, int step) tp->control.trap_expected = tp->stepping_over_breakpoint; - if (!non_stop) - { - /* Pass the last stop signal to the thread we're resuming, - irrespective of whether the current thread is the thread that - got the last event or not. This was historically GDB's - behaviour before keeping a stop_signal per thread. */ - - struct thread_info *last_thread; - ptid_t last_ptid; - struct target_waitstatus last_status; - - get_last_target_status (&last_ptid, &last_status); - if (!ptid_equal (inferior_ptid, last_ptid) - && !ptid_equal (last_ptid, null_ptid) - && !ptid_equal (last_ptid, minus_one_ptid)) - { - last_thread = find_thread_ptid (last_ptid); - if (last_thread) - { - tp->suspend.stop_signal = last_thread->suspend.stop_signal; - last_thread->suspend.stop_signal = GDB_SIGNAL_0; - } - } - } - - if (siggnal != GDB_SIGNAL_DEFAULT) - tp->suspend.stop_signal = siggnal; - /* If this signal should not be seen by program, - give it zero. Used for debugging signals. */ - else if (!signal_program[tp->suspend.stop_signal]) - tp->suspend.stop_signal = GDB_SIGNAL_0; - annotate_starting (); /* Make sure that output from GDB appears before output from the @@ -2443,7 +2414,7 @@ init_wait_for_inferior (void) breakpoint_init_inferior (inf_starting); - clear_proceed_status (); + clear_proceed_status (0); target_last_wait_ptid = minus_one_ptid; @@ -5190,6 +5161,10 @@ switch_back_to_stepped_thread (struct execution_control_state *ecs) what keep_going does as well, if we call it. */ ecs->event_thread->control.trap_expected = 0; + /* Likewise, clear the signal if it should not be passed. */ + if (!signal_program[ecs->event_thread->suspend.stop_signal]) + ecs->event_thread->suspend.stop_signal = GDB_SIGNAL_0; + /* If scheduler locking applies even if not stepping, there's no need to walk over threads. Above we've checked whether the current thread is stepping. If some other thread not the |