xref: /netbsd-src/external/gpl3/gdb/dist/gdbserver/gdbthread.h (revision 2be465b09aca4bf6e67814eb0e0f409087138d90)
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