diff options
Diffstat (limited to 'gdb')
-rw-r--r-- | gdb/ChangeLog | 20 | ||||
-rw-r--r-- | gdb/infrun.c | 16 | ||||
-rw-r--r-- | gdb/thread.c | 72 |
3 files changed, 86 insertions, 22 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 50c56c9..a733f0d 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,23 @@ +2020-01-10 Pedro Alves <palves@redhat.com> + + * gdbthread.h (scoped_restore_current_thread) + <dont_restore, restore, m_dont_restore>: Declare. + * thread.c (thread_alive): Add assertion. Return bool. + (switch_to_thread_if_alive): New. + (prune_threads): Switch inferior/thread. + (print_thread_info_1): Switch thread before calling target methods. + (scoped_restore_current_thread::restore): New, factored out from + ... + (scoped_restore_current_thread::~scoped_restore_current_thread): + ... this. + (scoped_restore_current_thread::scoped_restore_current_thread): + Add assertion. + (thread_apply_all_command, thread_select): Use + switch_to_thread_if_alive. + * infrun.c (proceed, restart_threads, handle_signal_stop) + (switch_back_to_stepped_thread): Switch current thread before + calling target methods. + 2020-01-10 Pedro Alves <palves@redhat.com> * inferior.c (switch_to_inferior_no_thread): New function, diff --git a/gdb/infrun.c b/gdb/infrun.c index d876634..2fa5cd8 100644 --- a/gdb/infrun.c +++ b/gdb/infrun.c @@ -2940,6 +2940,8 @@ proceed (CORE_ADDR addr, enum gdb_signal siggnal) { for (thread_info *tp : all_non_exited_threads (resume_ptid)) { + switch_to_thread_no_regs (tp); + /* Ignore the current thread here. It's handled afterwards. */ if (tp == cur_thr) @@ -2957,6 +2959,8 @@ proceed (CORE_ADDR addr, enum gdb_signal siggnal) thread_step_over_chain_enqueue (tp); } + + switch_to_thread (cur_thr); } /* Enqueue the current thread last, so that we move all other @@ -2993,6 +2997,8 @@ proceed (CORE_ADDR addr, enum gdb_signal siggnal) Start all other threads that are implicitly resumed too. */ for (thread_info *tp : all_non_exited_threads (resume_ptid)) { + switch_to_thread_no_regs (tp); + if (tp->resumed) { if (debug_infrun) @@ -4377,6 +4383,7 @@ stop_all_threads (void) "infrun: %s executing, " "need stop\n", target_pid_to_str (t->ptid).c_str ()); + switch_to_thread_no_regs (t); target_stop (t->ptid); t->stop_requested = 1; } @@ -5221,6 +5228,8 @@ restart_threads (struct thread_info *event_thread) for (thread_info *tp : all_non_exited_threads ()) { + switch_to_thread_no_regs (tp); + if (tp == event_thread) { if (debug_infrun) @@ -5479,9 +5488,8 @@ handle_signal_stop (struct execution_control_state *ecs) { struct regcache *regcache = get_thread_regcache (ecs->event_thread); struct gdbarch *reg_gdbarch = regcache->arch (); - scoped_restore save_inferior_ptid = make_scoped_restore (&inferior_ptid); - inferior_ptid = ecs->ptid; + switch_to_thread (ecs->event_thread); fprintf_unfiltered (gdb_stdlog, "infrun: stop_pc = %s\n", paddress (reg_gdbarch, @@ -6924,6 +6932,8 @@ switch_back_to_stepped_thread (struct execution_control_state *ecs) for (thread_info *tp : all_non_exited_threads ()) { + switch_to_thread_no_regs (tp); + /* Ignore threads of processes the caller is not resuming. */ if (!sched_multi @@ -6975,6 +6985,8 @@ switch_back_to_stepped_thread (struct execution_control_state *ecs) return 1; } } + + switch_to_thread (ecs->event_thread); } return 0; diff --git a/gdb/thread.c b/gdb/thread.c index 630899c..17a79e2 100644 --- a/gdb/thread.c +++ b/gdb/thread.c @@ -62,8 +62,6 @@ static int highest_thread_num; spawned new threads we haven't heard of yet. */ static int threads_executing; -static int thread_alive (struct thread_info *); - /* RAII type used to increase / decrease the refcount of each thread in a given list of threads. */ @@ -679,14 +677,38 @@ any_live_thread_of_inferior (inferior *inf) } /* Return true if TP is an active thread. */ -static int -thread_alive (struct thread_info *tp) +static bool +thread_alive (thread_info *tp) { if (tp->state == THREAD_EXITED) - return 0; - if (!target_thread_alive (tp->ptid)) - return 0; - return 1; + return false; + + /* Ensure we're looking at the right target stack. */ + gdb_assert (tp->inf == current_inferior ()); + + return target_thread_alive (tp->ptid); +} + +/* Switch to thread TP if it is alive. Returns true if successfully + switched, false otherwise. */ + +static bool +switch_to_thread_if_alive (thread_info *thr) +{ + scoped_restore_current_thread restore_thread; + + /* Switch inferior first, so that we're looking at the right target + stack. */ + switch_to_inferior_no_thread (thr->inf); + + if (thread_alive (thr)) + { + switch_to_thread (thr); + restore_thread.dont_restore (); + return true; + } + + return false; } /* See gdbthreads.h. */ @@ -694,9 +716,15 @@ thread_alive (struct thread_info *tp) void prune_threads (void) { + scoped_restore_current_thread restore_thread; + for (thread_info *tp : all_threads_safe ()) - if (!thread_alive (tp)) - delete_thread (tp); + { + switch_to_inferior_no_thread (tp->inf); + + if (!thread_alive (tp)) + delete_thread (tp); + } } /* See gdbthreads.h. */ @@ -1037,6 +1065,9 @@ print_thread_info_1 (struct ui_out *uiout, const char *requested_threads, gdb::optional<ui_out_emit_list> list_emitter; gdb::optional<ui_out_emit_table> table_emitter; + /* We'll be switching threads temporarily below. */ + scoped_restore_current_thread restore_thread; + if (uiout->is_mi_like_p ()) list_emitter.emplace (uiout, "threads"); else @@ -1054,6 +1085,10 @@ print_thread_info_1 (struct ui_out *uiout, const char *requested_threads, if (!uiout->is_mi_like_p ()) { + /* Switch inferiors so we're looking at the right + target stack. */ + switch_to_inferior_no_thread (tp->inf); + target_id_col_width = std::max (target_id_col_width, thread_target_id_str (tp).size ()); @@ -1085,9 +1120,6 @@ print_thread_info_1 (struct ui_out *uiout, const char *requested_threads, uiout->table_body (); } - /* We'll be switching threads temporarily. */ - scoped_restore_current_thread restore_thread; - for (inferior *inf : all_inferiors ()) for (thread_info *tp : inf->threads ()) { @@ -1116,6 +1148,9 @@ print_thread_info_1 (struct ui_out *uiout, const char *requested_threads, if (show_global_ids || uiout->is_mi_like_p ()) uiout->field_signed ("id", tp->global_num); + /* Switch to the thread (and inferior / target). */ + switch_to_thread (tp); + /* For the CLI, we stuff everything into the target-id field. This is a gross hack to make the output come out looking correct. The underlying problem here is that ui-out has no @@ -1147,9 +1182,8 @@ print_thread_info_1 (struct ui_out *uiout, const char *requested_threads, uiout->text ("(running)\n"); else { - /* The switch below puts us at the top of the stack (leaf + /* The switch above put us at the top of the stack (leaf frame). */ - switch_to_thread (tp); print_stack_frame (get_selected_frame (NULL), /* For MI output, print frame level. */ uiout->is_mi_like_p (), @@ -1662,7 +1696,7 @@ thread_apply_all_command (const char *cmd, int from_tty) scoped_restore_current_thread restore_thread; for (thread_info *thr : thr_list_cpy) - if (thread_alive (thr)) + if (switch_to_thread_if_alive (thr)) thr_try_catch_cmd (thr, cmd, from_tty, flags); } } @@ -1819,7 +1853,7 @@ thread_apply_command (const char *tidlist, int from_tty) continue; } - if (!thread_alive (tp)) + if (!switch_to_thread_if_alive (tp)) { warning (_("Thread %s has terminated."), print_thread_id (tp)); continue; @@ -1987,11 +2021,9 @@ show_print_thread_events (struct ui_file *file, int from_tty, void thread_select (const char *tidstr, thread_info *tp) { - if (!thread_alive (tp)) + if (!switch_to_thread_if_alive (tp)) error (_("Thread ID %s has terminated."), tidstr); - switch_to_thread (tp); - annotate_thread_changed (); /* Since the current thread may have changed, see if there is any |