|  | /* Multi-thread control defs for remote server for GDB. | 
|  | Copyright (C) 1993-2024 Free Software Foundation, Inc. | 
|  |  | 
|  | This file is part of GDB. | 
|  |  | 
|  | This program is free software; you can redistribute it and/or modify | 
|  | it under the terms of the GNU General Public License as published by | 
|  | the Free Software Foundation; either version 3 of the License, or | 
|  | (at your option) any later version. | 
|  |  | 
|  | This program is distributed in the hope that it will be useful, | 
|  | but WITHOUT ANY WARRANTY; without even the implied warranty of | 
|  | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
|  | GNU General Public License for more details. | 
|  |  | 
|  | You should have received a copy of the GNU General Public License | 
|  | along with this program.  If not, see <http://www.gnu.org/licenses/>.  */ | 
|  |  | 
|  | #ifndef GDBSERVER_GDBTHREAD_H | 
|  | #define GDBSERVER_GDBTHREAD_H | 
|  |  | 
|  | #include "gdbsupport/function-view.h" | 
|  | #include "gdbsupport/intrusive_list.h" | 
|  | #include <memory> | 
|  |  | 
|  | struct btrace_target_info; | 
|  | struct regcache; | 
|  |  | 
|  | struct thread_info : public intrusive_list_node<thread_info> | 
|  | { | 
|  | thread_info (ptid_t id, process_info *process, void *target_data) | 
|  | : id (id), m_process (process), m_target_data (target_data) | 
|  | {} | 
|  |  | 
|  | /* Return the process owning this thread.  */ | 
|  | process_info *process () const | 
|  | { return m_process; } | 
|  |  | 
|  | struct regcache *regcache () | 
|  | { return m_regcache.get (); } | 
|  |  | 
|  | void set_regcache (std::unique_ptr<struct regcache> regcache) | 
|  | { m_regcache = std::move (regcache); } | 
|  |  | 
|  | void *target_data () | 
|  | { return m_target_data; } | 
|  |  | 
|  | /* The id of this thread.  */ | 
|  | ptid_t id; | 
|  |  | 
|  | /* The last resume GDB requested on this thread.  */ | 
|  | enum resume_kind last_resume_kind = resume_continue; | 
|  |  | 
|  | /* The last wait status reported for this thread.  */ | 
|  | struct target_waitstatus last_status; | 
|  |  | 
|  | /* True if LAST_STATUS hasn't been reported to GDB yet.  */ | 
|  | int status_pending_p = 0; | 
|  |  | 
|  | /* Given `while-stepping', a thread may be collecting data for more | 
|  | than one tracepoint simultaneously.  E.g.: | 
|  |  | 
|  | ff0001  INSN1 <-- TP1, while-stepping 10 collect $regs | 
|  | ff0002  INSN2 | 
|  | ff0003  INSN3 <-- TP2, collect $regs | 
|  | ff0004  INSN4 <-- TP3, while-stepping 10 collect $regs | 
|  | ff0005  INSN5 | 
|  |  | 
|  | Notice that when instruction INSN5 is reached, the while-stepping | 
|  | actions of both TP1 and TP3 are still being collected, and that TP2 | 
|  | had been collected meanwhile.  The whole range of ff0001-ff0005 | 
|  | should be single-stepped, due to at least TP1's while-stepping | 
|  | action covering the whole range. | 
|  |  | 
|  | On the other hand, the same tracepoint with a while-stepping action | 
|  | may be hit by more than one thread simultaneously, hence we can't | 
|  | keep the current step count in the tracepoint itself. | 
|  |  | 
|  | This is the head of the list of the states of `while-stepping' | 
|  | tracepoint actions this thread is now collecting; NULL if empty. | 
|  | Each item in the list holds the current step of the while-stepping | 
|  | action.  */ | 
|  | struct wstep_state *while_stepping = nullptr; | 
|  |  | 
|  | /* Branch trace target information for this thread.  */ | 
|  | struct btrace_target_info *btrace = nullptr; | 
|  |  | 
|  | /* Thread options GDB requested with QThreadOptions.  */ | 
|  | gdb_thread_options thread_options = 0; | 
|  |  | 
|  | private: | 
|  | process_info *m_process; | 
|  | std::unique_ptr<struct regcache> m_regcache = nullptr; | 
|  | void *m_target_data; | 
|  | }; | 
|  |  | 
|  | /* Return a pointer to the first thread, or NULL if there isn't one.  */ | 
|  |  | 
|  | thread_info *get_first_thread (void); | 
|  |  | 
|  | thread_info *find_thread_ptid (ptid_t ptid); | 
|  |  | 
|  | /* Find any thread of the PID process.  Returns NULL if none is | 
|  | found.  */ | 
|  | thread_info *find_any_thread_of_pid (int pid); | 
|  |  | 
|  | /* Find the first thread for which FUNC returns true.  Return NULL if no thread | 
|  | satisfying FUNC is found.  */ | 
|  |  | 
|  | thread_info *find_thread (gdb::function_view<bool (thread_info *)> func); | 
|  |  | 
|  | /* Like the above, but only consider threads with pid PID.  */ | 
|  |  | 
|  | thread_info *find_thread (int pid, | 
|  | gdb::function_view<bool (thread_info *)> func); | 
|  |  | 
|  | /* Find the first thread that matches FILTER for which FUNC returns true. | 
|  | Return NULL if no thread satisfying these conditions is found.  */ | 
|  |  | 
|  | thread_info *find_thread (ptid_t filter, | 
|  | gdb::function_view<bool (thread_info *)> func); | 
|  |  | 
|  | /* Invoke FUNC for each thread.  */ | 
|  |  | 
|  | void for_each_thread (gdb::function_view<void (thread_info *)> func); | 
|  |  | 
|  | /* Like the above, but only consider threads matching PTID.  */ | 
|  |  | 
|  | void for_each_thread | 
|  | (ptid_t ptid, gdb::function_view<void (thread_info *)> func); | 
|  |  | 
|  | /* Find a random thread that matches PTID and for which FUNC (THREAD) | 
|  | returns true.  If no entry is found then return nullptr.  */ | 
|  |  | 
|  | thread_info *find_thread_in_random | 
|  | (gdb::function_view<bool (thread_info *)> func); | 
|  |  | 
|  | /* Like the above, but only consider threads matching PTID.  */ | 
|  |  | 
|  | thread_info *find_thread_in_random | 
|  | (ptid_t ptid, gdb::function_view<bool (thread_info *)> func); | 
|  |  | 
|  | /* Switch the current thread.  */ | 
|  |  | 
|  | void switch_to_thread (thread_info *thread); | 
|  |  | 
|  | /* Save/restore current thread.  */ | 
|  |  | 
|  | class scoped_restore_current_thread | 
|  | { | 
|  | public: | 
|  | scoped_restore_current_thread (); | 
|  | ~scoped_restore_current_thread (); | 
|  |  | 
|  | DISABLE_COPY_AND_ASSIGN (scoped_restore_current_thread); | 
|  |  | 
|  | /* Cancel restoring on scope exit.  */ | 
|  | void dont_restore () { m_dont_restore = true; } | 
|  |  | 
|  | private: | 
|  | bool m_dont_restore = false; | 
|  | process_info *m_process; | 
|  | thread_info *m_thread; | 
|  | }; | 
|  |  | 
|  | #endif /* GDBSERVER_GDBTHREAD_H */ |