PR21994, readelf looping on verdefs
[deliverable/binutils-gdb.git] / gdb / gdbthread.h
index 4cd739089b049c9e361ab8436e53d594f2355e4c..046bf95cf6fc7e07460dc60aa9c236d025539736 100644 (file)
@@ -31,6 +31,8 @@ struct symtab;
 #include "common/vec.h"
 #include "target/waitstatus.h"
 #include "cli/cli-utils.h"
+#include "common/refcounted-object.h"
+#include "common-gdbthread.h"
 
 /* Frontend view of the thread state.  Possible extensions: stepping,
    finishing, until(ling),...  */
@@ -177,7 +179,24 @@ typedef struct value *value_ptr;
 DEF_VEC_P (value_ptr);
 typedef VEC (value_ptr) value_vec;
 
-struct thread_info
+/* Threads are intrusively refcounted objects.  Being the
+   user-selected thread is normally considered an implicit strong
+   reference and is thus not accounted in the refcount, unlike
+   inferior objects.  This is necessary, because there's no "current
+   thread" pointer.  Instead the current thread is inferred from the
+   inferior_ptid global.  However, when GDB needs to remember the
+   selected thread to later restore it, GDB bumps the thread object's
+   refcount, to prevent something deleting the thread object before
+   reverting back (e.g., due to a "kill" command).  If the thread
+   meanwhile exits before being re-selected, then the thread object is
+   left listed in the thread list, but marked with state
+   THREAD_EXITED.  (See make_cleanup_restore_current_thread and
+   delete_thread).  All other thread references are considered weak
+   references.  Placing a thread in the thread list is an implicit
+   strong reference, and is thus not accounted for in the thread's
+   refcount.  */
+
+class thread_info : public refcounted_object
 {
 public:
   explicit thread_info (inferior *inf, ptid_t ptid);
@@ -186,22 +205,8 @@ public:
   bool deletable () const
   {
     /* If this is the current thread, or there's code out there that
-       relies on it existing (m_refcount > 0) we can't delete yet.  */
-    return (m_refcount == 0 && !ptid_equal (ptid, inferior_ptid));
-  }
-
-  /* Increase the refcount.  */
-  void incref ()
-  {
-    gdb_assert (m_refcount >= 0);
-    m_refcount++;
-  }
-
-  /* Decrease the refcount.  */
-  void decref ()
-  {
-    m_refcount--;
-    gdb_assert (m_refcount >= 0);
+       relies on it existing (refcount > 0) we can't delete yet.  */
+    return (refcount () == 0 && !ptid_equal (ptid, inferior_ptid));
   }
 
   struct thread_info *next = NULL;
@@ -362,13 +367,6 @@ public:
      fields point to self.  */
   struct thread_info *step_over_prev = NULL;
   struct thread_info *step_over_next = NULL;
-
-private:
-
-  /* If this is > 0, then it means there's code out there that relies
-     on this thread being listed.  Don't delete it from the lists even
-     if we detect it exiting.  */
-  int m_refcount = 0;
 };
 
 /* Create an empty thread list, or empty the existing one.  */
@@ -496,10 +494,6 @@ extern struct thread_info *iterate_over_threads (thread_callback_func, void *);
 
 extern int thread_count (void);
 
-/* Switch from one thread to another.  Also sets the STOP_PC
-   global.  */
-extern void switch_to_thread (ptid_t ptid);
-
 /* Switch from one thread to another.  Does not read registers and
    sets STOP_PC to -1.  */
 extern void switch_to_thread_no_regs (struct thread_info *thread);
@@ -595,7 +589,27 @@ extern int print_thread_events;
 extern void print_thread_info (struct ui_out *uiout, char *requested_threads,
                               int pid);
 
-extern struct cleanup *make_cleanup_restore_current_thread (void);
+/* Save/restore current inferior/thread/frame.  */
+
+class scoped_restore_current_thread
+{
+public:
+  scoped_restore_current_thread ();
+  ~scoped_restore_current_thread ();
+
+  /* Disable copy.  */
+  scoped_restore_current_thread
+    (const scoped_restore_current_thread &) = delete;
+  void operator=
+    (const scoped_restore_current_thread &) = delete;
+
+private:
+  thread_info *m_thread;
+  inferior *m_inf;
+  frame_id m_selected_frame_id;
+  int m_selected_frame_level;
+  bool m_was_stopped;
+};
 
 /* Returns a pointer into the thread_info corresponding to
    INFERIOR_PTID.  INFERIOR_PTID *must* be in the thread list.  */
This page took 0.026378 seconds and 4 git commands to generate.