diff options
-rw-r--r-- | gdb/ChangeLog | 17 | ||||
-rw-r--r-- | gdb/gdbthread.h | 17 | ||||
-rw-r--r-- | gdb/thread.c | 97 |
3 files changed, 59 insertions, 72 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog index cd2af5c..ff1fd7f 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,5 +1,22 @@ 2020-06-18 Pedro Alves <palves@redhat.com> + PR gdb/25412 + * gdbthread.h (delete_thread, delete_thread_silent) + (find_thread_ptid): Update comments. + * thread.c (current_thread_): New global. + (is_current_thread): Move higher, and reimplement. + (inferior_thread): Reimplement. + (set_thread_exited): Use bool. Add assertions. + (add_thread_silent): Simplify thread-reuse handling by always + calling delete_thread. + (delete_thread): Remove intro comment. + (find_thread_ptid): Skip exited threads. + (switch_to_thread_no_regs): Write to current_thread_. + (switch_to_no_thread): Check CURRENT_THREAD_ instead of + INFERIOR_PTID. Clear current_thread_. + +2020-06-18 Pedro Alves <palves@redhat.com> + * aix-thread.c (pd_update): Use switch_to_thread. 2020-06-18 Pedro Alves <palves@redhat.com> diff --git a/gdb/gdbthread.h b/gdb/gdbthread.h index 710b4c6..0166b20 100644 --- a/gdb/gdbthread.h +++ b/gdb/gdbthread.h @@ -415,12 +415,13 @@ extern struct thread_info *add_thread_with_info (process_stratum_target *targ, ptid_t ptid, private_thread_info *); -/* Delete an existing thread list entry. */ +/* Delete thread THREAD and notify of thread exit. If the thread is + currently not deletable, don't actually delete it but still tag it + as exited and do the notification. */ extern void delete_thread (struct thread_info *thread); -/* Delete an existing thread list entry, and be quiet about it. Used - after the process this thread having belonged to having already - exited, for example. */ +/* Like delete_thread, but be quiet about it. Used when the process + this thread belonged to has already exited, for example. */ extern void delete_thread_silent (struct thread_info *thread); /* Delete a step_resume_breakpoint from the thread database. */ @@ -460,15 +461,15 @@ extern bool in_thread_list (process_stratum_target *targ, ptid_t ptid); global id, not the system's). */ extern int valid_global_thread_id (int global_id); -/* Find thread PTID of inferior INF. */ +/* Find (non-exited) thread PTID of inferior INF. */ extern thread_info *find_thread_ptid (inferior *inf, ptid_t ptid); -/* Search function to lookup a thread by 'pid'. */ +/* Search function to lookup a (non-exited) thread by 'ptid'. */ extern struct thread_info *find_thread_ptid (process_stratum_target *targ, ptid_t ptid); -/* Search function to lookup a thread by 'ptid'. Only searches in - threads of INF. */ +/* Search function to lookup a (non-exited) thread by 'ptid'. Only + searches in threads of INF. */ extern struct thread_info *find_thread_ptid (inferior *inf, ptid_t ptid); /* Find thread by GDB global thread ID. */ diff --git a/gdb/thread.c b/gdb/thread.c index 02672f0..f0722d3 100644 --- a/gdb/thread.c +++ b/gdb/thread.c @@ -55,6 +55,9 @@ static int highest_thread_num; +/* The current/selected thread. */ +static thread_info *current_thread_; + /* RAII type used to increase / decrease the refcount of each thread in a given list of threads. */ @@ -78,13 +81,19 @@ private: const std::vector<thread_info *> &m_thrds; }; +/* Returns true if THR is the current thread. */ + +static bool +is_current_thread (const thread_info *thr) +{ + return thr == current_thread_; +} struct thread_info* inferior_thread (void) { - struct thread_info *tp = find_thread_ptid (current_inferior (), inferior_ptid); - gdb_assert (tp); - return tp; + gdb_assert (current_thread_ != nullptr); + return current_thread_; } /* Delete the breakpoint pointed at by BP_P, if there's one. */ @@ -194,7 +203,7 @@ clear_thread_inferior_resources (struct thread_info *tp) /* Set the TP's state as exited. */ static void -set_thread_exited (thread_info *tp, int silent) +set_thread_exited (thread_info *tp, bool silent) { /* Dead threads don't need to step-over. Remove from queue. */ if (tp->step_over_next != NULL) @@ -245,7 +254,12 @@ new_thread (struct inferior *inf, ptid_t ptid) struct thread_info *last; for (last = inf->thread_list; last->next != NULL; last = last->next) - ; + gdb_assert (ptid != last->ptid + || last->state == THREAD_EXITED); + + gdb_assert (ptid != last->ptid + || last->state == THREAD_EXITED); + last->next = tp; } @@ -255,51 +269,15 @@ new_thread (struct inferior *inf, ptid_t ptid) struct thread_info * add_thread_silent (process_stratum_target *targ, ptid_t ptid) { - inferior *inf; - - thread_info *tp = find_thread_ptid (targ, ptid); - if (tp) - /* Found an old thread with the same id. It has to be dead, - otherwise we wouldn't be adding a new thread with the same id. - The OS is reusing this id --- delete it, and recreate a new - one. */ - { - /* In addition to deleting the thread, if this is the current - thread, then we need to take care that delete_thread doesn't - really delete the thread if it is inferior_ptid. Create a - new template thread in the list with an invalid ptid, switch - to it, delete the original thread, reset the new thread's - ptid, and switch to it. */ - - if (inferior_ptid == ptid) - { - thread_info *new_thr = new_thread (tp->inf, null_ptid); - - /* Make switch_to_thread not read from the thread. */ - new_thr->state = THREAD_EXITED; - switch_to_no_thread (); - - /* Now we can delete it. */ - delete_thread (tp); - - /* Now reset its ptid, and reswitch inferior_ptid to it. */ - new_thr->ptid = ptid; - new_thr->state = THREAD_STOPPED; - switch_to_thread (new_thr); - - gdb::observers::new_thread.notify (new_thr); - - /* All done. */ - return new_thr; - } + inferior *inf = find_inferior_ptid (targ, ptid); - inf = tp->inf; - - /* Just go ahead and delete it. */ - delete_thread (tp); - } - else - inf = find_inferior_ptid (targ, ptid); + /* We may have an old thread with the same id in the thread list. + If we do, it must be dead, otherwise we wouldn't be adding a new + thread with the same id. The OS is reusing this id --- delete + the old thread, and create a new one. */ + thread_info *tp = find_thread_ptid (inf, ptid); + if (tp != nullptr) + delete_thread (tp); tp = new_thread (inf, ptid); gdb::observers::new_thread.notify (tp); @@ -349,14 +327,6 @@ thread_info::~thread_info () xfree (this->name); } -/* Returns true if THR is the current thread. */ - -static bool -is_current_thread (const thread_info *thr) -{ - return thr->inf == current_inferior () && thr->ptid == inferior_ptid; -} - /* See gdbthread.h. */ bool @@ -482,10 +452,7 @@ delete_thread_1 (thread_info *thr, bool silent) delete tp; } -/* Delete thread THREAD and notify of thread exit. If this is the - current thread, don't actually delete it, but tag it as exited and - do the notification. If this is the user selected thread, clear - it. */ +/* See gdbthread.h. */ void delete_thread (thread_info *thread) @@ -535,7 +502,7 @@ find_thread_ptid (process_stratum_target *targ, ptid_t ptid) struct thread_info * find_thread_ptid (inferior *inf, ptid_t ptid) { - for (thread_info *tp : inf->threads ()) + for (thread_info *tp : inf->non_exited_threads ()) if (tp->ptid == ptid) return tp; @@ -1317,7 +1284,8 @@ switch_to_thread_no_regs (struct thread_info *thread) set_current_program_space (inf->pspace); set_current_inferior (inf); - inferior_ptid = thread->ptid; + current_thread_ = thread; + inferior_ptid = current_thread_->ptid; } /* See gdbthread.h. */ @@ -1325,9 +1293,10 @@ switch_to_thread_no_regs (struct thread_info *thread) void switch_to_no_thread () { - if (inferior_ptid == null_ptid) + if (current_thread_ == nullptr) return; + current_thread_ = nullptr; inferior_ptid = null_ptid; reinit_frame_cache (); } |