Fetch registers from correct thread in ravenscar-thread.c
authorTom Tromey <tromey@adacore.com>
Fri, 7 Aug 2020 16:26:45 +0000 (10:26 -0600)
committerTom Tromey <tromey@adacore.com>
Fri, 7 Aug 2020 16:26:47 +0000 (10:26 -0600)
Fabien also noticed that gdb would not report a stop correctly when
using Ravenscar.  This patch fixes the bug by making a few changes:

* ravenscar_thread_target::wait now updates the inferior ptid before
  updating the thread list.  This ensures that a new thread is
  correctly associated with the underlying CPU.

* The fetch_registers, store_registers, and prepare_to_store methods
  now save and restore the regcache's ptid before doing the operation
  on the underlying live thread.  This ensures that gdb informs the
  remote of a thread it knows about, as opposed to using a Ravenscar
  thread, which probably will not be recognized.

gdb/ChangeLog
2020-08-07  Tom Tromey  <tromey@adacore.com>

* ravenscar-thread.c (ravenscar_thread_target::wait): Call
update_inferior_ptid before update_thread_list.
(temporarily_change_regcache_ptid): New class.
(ravenscar_thread_target::fetch_registers)
(ravenscar_thread_target::store_registers)
(ravenscar_thread_target::prepare_to_store): Use base thread when
forwarding operation.

gdb/ChangeLog
gdb/ravenscar-thread.c

index 0d443a8f72dacefb1ad2b9d9876503b27acd844c..640fb397a7d51ae1b3b290b35f147cb695b53963 100644 (file)
@@ -1,3 +1,13 @@
+2020-08-07  Tom Tromey  <tromey@adacore.com>
+
+       * ravenscar-thread.c (ravenscar_thread_target::wait): Call
+       update_inferior_ptid before update_thread_list.
+       (temporarily_change_regcache_ptid): New class.
+       (ravenscar_thread_target::fetch_registers)
+       (ravenscar_thread_target::store_registers)
+       (ravenscar_thread_target::prepare_to_store): Use base thread when
+       forwarding operation.
+
 2020-08-07  Tom Tromey  <tromey@adacore.com>
 
        * ravenscar-thread.c (ravenscar_thread_target::resume): Handle
index 91f09209bbce36e9405b9230f1741647c60994d4..459e5ea3ed3822342806a429fca9f4f41c90bca2 100644 (file)
@@ -457,20 +457,55 @@ ravenscar_thread_target::pid_to_str (ptid_t ptid)
   return string_printf ("Ravenscar Thread %#x", (int) ptid.tid ());
 }
 
+/* Temporarily set the ptid of a regcache to some other value.  When
+   this object is destroyed, the regcache's original ptid is
+   restored.  */
+
+class temporarily_change_regcache_ptid
+{
+public:
+
+  temporarily_change_regcache_ptid (struct regcache *regcache, ptid_t new_ptid)
+    : m_regcache (regcache),
+      m_save_ptid (regcache->ptid ())
+  {
+    m_regcache->set_ptid (new_ptid);
+  }
+
+  ~temporarily_change_regcache_ptid ()
+  {
+    m_regcache->set_ptid (m_save_ptid);
+  }
+
+private:
+
+  /* The regcache.  */
+  struct regcache *m_regcache;
+  /* The saved ptid.  */
+  ptid_t m_save_ptid;
+};
+
 void
 ravenscar_thread_target::fetch_registers (struct regcache *regcache, int regnum)
 {
   ptid_t ptid = regcache->ptid ();
 
-  if (runtime_initialized ()
-      && is_ravenscar_task (ptid)
-      && !task_is_currently_active (ptid))
+  if (runtime_initialized () && is_ravenscar_task (ptid))
     {
-      struct gdbarch *gdbarch = regcache->arch ();
-      struct ravenscar_arch_ops *arch_ops
-       = gdbarch_ravenscar_ops (gdbarch);
+      if (task_is_currently_active (ptid))
+       {
+         ptid_t base = get_base_thread_from_ravenscar_task (ptid);
+         temporarily_change_regcache_ptid changer (regcache, base);
+         beneath ()->fetch_registers (regcache, regnum);
+       }
+      else
+       {
+         struct gdbarch *gdbarch = regcache->arch ();
+         struct ravenscar_arch_ops *arch_ops
+           = gdbarch_ravenscar_ops (gdbarch);
 
-      arch_ops->fetch_registers (regcache, regnum);
+         arch_ops->fetch_registers (regcache, regnum);
+       }
     }
   else
     beneath ()->fetch_registers (regcache, regnum);
@@ -482,15 +517,22 @@ ravenscar_thread_target::store_registers (struct regcache *regcache,
 {
   ptid_t ptid = regcache->ptid ();
 
-  if (runtime_initialized ()
-      && is_ravenscar_task (ptid)
-      && !task_is_currently_active (ptid))
+  if (runtime_initialized () && is_ravenscar_task (ptid))
     {
-      struct gdbarch *gdbarch = regcache->arch ();
-      struct ravenscar_arch_ops *arch_ops
-       = gdbarch_ravenscar_ops (gdbarch);
+      if (task_is_currently_active (ptid))
+       {
+         ptid_t base = get_base_thread_from_ravenscar_task (ptid);
+         temporarily_change_regcache_ptid changer (regcache, base);
+         beneath ()->store_registers (regcache, regnum);
+       }
+      else
+       {
+         struct gdbarch *gdbarch = regcache->arch ();
+         struct ravenscar_arch_ops *arch_ops
+           = gdbarch_ravenscar_ops (gdbarch);
 
-      arch_ops->store_registers (regcache, regnum);
+         arch_ops->store_registers (regcache, regnum);
+       }
     }
   else
     beneath ()->store_registers (regcache, regnum);
@@ -501,11 +543,18 @@ ravenscar_thread_target::prepare_to_store (struct regcache *regcache)
 {
   ptid_t ptid = regcache->ptid ();
 
-  if (runtime_initialized ()
-      && is_ravenscar_task (ptid)
-      && !task_is_currently_active (ptid))
+  if (runtime_initialized () && is_ravenscar_task (ptid))
     {
-      /* Nothing.  */
+      if (task_is_currently_active (ptid))
+       {
+         ptid_t base = get_base_thread_from_ravenscar_task (ptid);
+         temporarily_change_regcache_ptid changer (regcache, base);
+         beneath ()->prepare_to_store (regcache);
+       }
+      else
+       {
+         /* Nothing.  */
+       }
     }
   else
     beneath ()->prepare_to_store (regcache);