18dffb485Schristos /* Multi-thread control defs for remote server for GDB. 2*2be465b0Schristos Copyright (C) 1993-2024 Free Software Foundation, Inc. 38dffb485Schristos 48dffb485Schristos This file is part of GDB. 58dffb485Schristos 68dffb485Schristos This program is free software; you can redistribute it and/or modify 78dffb485Schristos it under the terms of the GNU General Public License as published by 88dffb485Schristos the Free Software Foundation; either version 3 of the License, or 98dffb485Schristos (at your option) any later version. 108dffb485Schristos 118dffb485Schristos This program is distributed in the hope that it will be useful, 128dffb485Schristos but WITHOUT ANY WARRANTY; without even the implied warranty of 138dffb485Schristos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 148dffb485Schristos GNU General Public License for more details. 158dffb485Schristos 168dffb485Schristos You should have received a copy of the GNU General Public License 178dffb485Schristos along with this program. If not, see <http://www.gnu.org/licenses/>. */ 188dffb485Schristos 198dffb485Schristos #ifndef GDBSERVER_GDBTHREAD_H 208dffb485Schristos #define GDBSERVER_GDBTHREAD_H 218dffb485Schristos 228dffb485Schristos #include "gdbsupport/common-gdbthread.h" 238dffb485Schristos #include "inferiors.h" 248dffb485Schristos 258dffb485Schristos #include <list> 268dffb485Schristos 278dffb485Schristos struct btrace_target_info; 288dffb485Schristos struct regcache; 298dffb485Schristos 308dffb485Schristos struct thread_info 318dffb485Schristos { 324b169a6bSchristos thread_info (ptid_t id, void *target_data) 334b169a6bSchristos : id (id), target_data (target_data) 344b169a6bSchristos {} 354b169a6bSchristos 364b169a6bSchristos ~thread_info () 374b169a6bSchristos { 384b169a6bSchristos free_register_cache (this->regcache_data); 394b169a6bSchristos } 404b169a6bSchristos 418dffb485Schristos /* The id of this thread. */ 428dffb485Schristos ptid_t id; 438dffb485Schristos 448dffb485Schristos void *target_data; 454b169a6bSchristos struct regcache *regcache_data = nullptr; 468dffb485Schristos 478dffb485Schristos /* The last resume GDB requested on this thread. */ 484b169a6bSchristos enum resume_kind last_resume_kind = resume_continue; 498dffb485Schristos 508dffb485Schristos /* The last wait status reported for this thread. */ 518dffb485Schristos struct target_waitstatus last_status; 528dffb485Schristos 538dffb485Schristos /* True if LAST_STATUS hasn't been reported to GDB yet. */ 544b169a6bSchristos int status_pending_p = 0; 558dffb485Schristos 568dffb485Schristos /* Given `while-stepping', a thread may be collecting data for more 578dffb485Schristos than one tracepoint simultaneously. E.g.: 588dffb485Schristos 598dffb485Schristos ff0001 INSN1 <-- TP1, while-stepping 10 collect $regs 608dffb485Schristos ff0002 INSN2 618dffb485Schristos ff0003 INSN3 <-- TP2, collect $regs 628dffb485Schristos ff0004 INSN4 <-- TP3, while-stepping 10 collect $regs 638dffb485Schristos ff0005 INSN5 648dffb485Schristos 658dffb485Schristos Notice that when instruction INSN5 is reached, the while-stepping 668dffb485Schristos actions of both TP1 and TP3 are still being collected, and that TP2 678dffb485Schristos had been collected meanwhile. The whole range of ff0001-ff0005 688dffb485Schristos should be single-stepped, due to at least TP1's while-stepping 698dffb485Schristos action covering the whole range. 708dffb485Schristos 718dffb485Schristos On the other hand, the same tracepoint with a while-stepping action 728dffb485Schristos may be hit by more than one thread simultaneously, hence we can't 738dffb485Schristos keep the current step count in the tracepoint itself. 748dffb485Schristos 758dffb485Schristos This is the head of the list of the states of `while-stepping' 768dffb485Schristos tracepoint actions this thread is now collecting; NULL if empty. 778dffb485Schristos Each item in the list holds the current step of the while-stepping 788dffb485Schristos action. */ 794b169a6bSchristos struct wstep_state *while_stepping = nullptr; 808dffb485Schristos 818dffb485Schristos /* Branch trace target information for this thread. */ 824b169a6bSchristos struct btrace_target_info *btrace = nullptr; 83*2be465b0Schristos 84*2be465b0Schristos /* Thread options GDB requested with QThreadOptions. */ 85*2be465b0Schristos gdb_thread_options thread_options = 0; 868dffb485Schristos }; 878dffb485Schristos 888dffb485Schristos extern std::list<thread_info *> all_threads; 898dffb485Schristos 908dffb485Schristos void remove_thread (struct thread_info *thread); 918dffb485Schristos struct thread_info *add_thread (ptid_t ptid, void *target_data); 928dffb485Schristos 938dffb485Schristos /* Return a pointer to the first thread, or NULL if there isn't one. */ 948dffb485Schristos 958dffb485Schristos struct thread_info *get_first_thread (void); 968dffb485Schristos 978dffb485Schristos struct thread_info *find_thread_ptid (ptid_t ptid); 988dffb485Schristos 998dffb485Schristos /* Find any thread of the PID process. Returns NULL if none is 1008dffb485Schristos found. */ 1018dffb485Schristos struct thread_info *find_any_thread_of_pid (int pid); 1028dffb485Schristos 1038dffb485Schristos /* Find the first thread for which FUNC returns true. Return NULL if no thread 1048dffb485Schristos satisfying FUNC is found. */ 1058dffb485Schristos 1068dffb485Schristos template <typename Func> 1078dffb485Schristos static thread_info * 1088dffb485Schristos find_thread (Func func) 1098dffb485Schristos { 1108dffb485Schristos std::list<thread_info *>::iterator next, cur = all_threads.begin (); 1118dffb485Schristos 1128dffb485Schristos while (cur != all_threads.end ()) 1138dffb485Schristos { 1148dffb485Schristos next = cur; 1158dffb485Schristos next++; 1168dffb485Schristos 1178dffb485Schristos if (func (*cur)) 1188dffb485Schristos return *cur; 1198dffb485Schristos 1208dffb485Schristos cur = next; 1218dffb485Schristos } 1228dffb485Schristos 1238dffb485Schristos return NULL; 1248dffb485Schristos } 1258dffb485Schristos 1268dffb485Schristos /* Like the above, but only consider threads with pid PID. */ 1278dffb485Schristos 1288dffb485Schristos template <typename Func> 1298dffb485Schristos static thread_info * 1308dffb485Schristos find_thread (int pid, Func func) 1318dffb485Schristos { 1328dffb485Schristos return find_thread ([&] (thread_info *thread) 1338dffb485Schristos { 1348dffb485Schristos return thread->id.pid () == pid && func (thread); 1358dffb485Schristos }); 1368dffb485Schristos } 1378dffb485Schristos 1388dffb485Schristos /* Find the first thread that matches FILTER for which FUNC returns true. 1398dffb485Schristos Return NULL if no thread satisfying these conditions is found. */ 1408dffb485Schristos 1418dffb485Schristos template <typename Func> 1428dffb485Schristos static thread_info * 1438dffb485Schristos find_thread (ptid_t filter, Func func) 1448dffb485Schristos { 1458dffb485Schristos return find_thread ([&] (thread_info *thread) { 1468dffb485Schristos return thread->id.matches (filter) && func (thread); 1478dffb485Schristos }); 1488dffb485Schristos } 1498dffb485Schristos 1508dffb485Schristos /* Invoke FUNC for each thread. */ 1518dffb485Schristos 1528dffb485Schristos template <typename Func> 1538dffb485Schristos static void 1548dffb485Schristos for_each_thread (Func func) 1558dffb485Schristos { 1568dffb485Schristos std::list<thread_info *>::iterator next, cur = all_threads.begin (); 1578dffb485Schristos 1588dffb485Schristos while (cur != all_threads.end ()) 1598dffb485Schristos { 1608dffb485Schristos next = cur; 1618dffb485Schristos next++; 1628dffb485Schristos func (*cur); 1638dffb485Schristos cur = next; 1648dffb485Schristos } 1658dffb485Schristos } 1668dffb485Schristos 1678dffb485Schristos /* Like the above, but only consider threads with pid PID. */ 1688dffb485Schristos 1698dffb485Schristos template <typename Func> 1708dffb485Schristos static void 1718dffb485Schristos for_each_thread (int pid, Func func) 1728dffb485Schristos { 1738dffb485Schristos for_each_thread ([&] (thread_info *thread) 1748dffb485Schristos { 1758dffb485Schristos if (pid == thread->id.pid ()) 1768dffb485Schristos func (thread); 1778dffb485Schristos }); 1788dffb485Schristos } 1798dffb485Schristos 1808dffb485Schristos /* Find the a random thread for which FUNC (THREAD) returns true. If 1818dffb485Schristos no entry is found then return NULL. */ 1828dffb485Schristos 1838dffb485Schristos template <typename Func> 1848dffb485Schristos static thread_info * 1858dffb485Schristos find_thread_in_random (Func func) 1868dffb485Schristos { 1878dffb485Schristos int count = 0; 1888dffb485Schristos int random_selector; 1898dffb485Schristos 1908dffb485Schristos /* First count how many interesting entries we have. */ 1918dffb485Schristos for_each_thread ([&] (thread_info *thread) { 1928dffb485Schristos if (func (thread)) 1938dffb485Schristos count++; 1948dffb485Schristos }); 1958dffb485Schristos 1968dffb485Schristos if (count == 0) 1978dffb485Schristos return NULL; 1988dffb485Schristos 1998dffb485Schristos /* Now randomly pick an entry out of those. */ 2008dffb485Schristos random_selector = (int) 2018dffb485Schristos ((count * (double) rand ()) / (RAND_MAX + 1.0)); 2028dffb485Schristos 2038dffb485Schristos thread_info *thread = find_thread ([&] (thread_info *thr_arg) { 2048dffb485Schristos return func (thr_arg) && (random_selector-- == 0); 2058dffb485Schristos }); 2068dffb485Schristos 2078dffb485Schristos gdb_assert (thread != NULL); 2088dffb485Schristos 2098dffb485Schristos return thread; 2108dffb485Schristos } 2118dffb485Schristos 2128dffb485Schristos /* Get current thread ID (Linux task ID). */ 2138dffb485Schristos #define current_ptid (current_thread->id) 2148dffb485Schristos 2158dffb485Schristos /* Get the ptid of THREAD. */ 2168dffb485Schristos 2178dffb485Schristos static inline ptid_t 2188dffb485Schristos ptid_of (const thread_info *thread) 2198dffb485Schristos { 2208dffb485Schristos return thread->id; 2218dffb485Schristos } 2228dffb485Schristos 2238dffb485Schristos /* Get the pid of THREAD. */ 2248dffb485Schristos 2258dffb485Schristos static inline int 2268dffb485Schristos pid_of (const thread_info *thread) 2278dffb485Schristos { 2288dffb485Schristos return thread->id.pid (); 2298dffb485Schristos } 2308dffb485Schristos 2318dffb485Schristos /* Get the lwp of THREAD. */ 2328dffb485Schristos 2338dffb485Schristos static inline long 2348dffb485Schristos lwpid_of (const thread_info *thread) 2358dffb485Schristos { 2368dffb485Schristos return thread->id.lwp (); 2378dffb485Schristos } 2388dffb485Schristos 2394b169a6bSchristos /* Switch the current thread. */ 2404b169a6bSchristos 2414b169a6bSchristos void switch_to_thread (thread_info *thread); 2424b169a6bSchristos 2434b169a6bSchristos /* Save/restore current thread. */ 2444b169a6bSchristos 2454b169a6bSchristos class scoped_restore_current_thread 2464b169a6bSchristos { 2474b169a6bSchristos public: 2484b169a6bSchristos scoped_restore_current_thread (); 2494b169a6bSchristos ~scoped_restore_current_thread (); 2504b169a6bSchristos 2514b169a6bSchristos DISABLE_COPY_AND_ASSIGN (scoped_restore_current_thread); 2524b169a6bSchristos 2534b169a6bSchristos /* Cancel restoring on scope exit. */ 2544b169a6bSchristos void dont_restore () { m_dont_restore = true; } 2554b169a6bSchristos 2564b169a6bSchristos private: 2574b169a6bSchristos bool m_dont_restore = false; 2584b169a6bSchristos process_info *m_process; 2594b169a6bSchristos thread_info *m_thread; 2604b169a6bSchristos }; 2614b169a6bSchristos 2628dffb485Schristos #endif /* GDBSERVER_GDBTHREAD_H */ 263