This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[RFC/RFA] Adding support for GNAT Ravenscar run-time lib


Hello,

The following patch implements a thread stratum for GNAT's Ravenscar
run-time lib; we would be interested in having your feedback about
it, and maybe integrate it to the public tree if that makes sense.

This target (GNAT Ravenscar) is a run-time lib with minimal tasking
functionalities, based on Ada 2005's Ravenscar profile and targeted to
bareboard environment. So far, this run-time lib is only available on
sparc-elf targets; so this patch only implements the stratum for sparc.
This implementation should be modular enough to add new processors later
if need be.

The patch depends on another patch submitted previously which has not been
integrated yet (it uses iterate_over_live_ada_tasks):
http://sourceware.org/ml/gdb-patches/2010-04/msg00839.html

2010-04-25  Jerome Guitton  <guitton@adacore.com>

	* ravenscar-thread.c, ravenscar-thread.h, ravenscar-sparc-thread.c:
	New function.
	* configure.tgt: Add ravenscar-thread.o and ravenscar-sparc-thread.o
	to the target objects for sparc-elf.
---
 gdb/configure.tgt            |    3 +-
 gdb/ravenscar-sparc-thread.c |  184 +++++++++++++++++++
 gdb/ravenscar-thread.c       |  409 ++++++++++++++++++++++++++++++++++++++++++
 gdb/ravenscar-thread.h       |   41 +++++
 4 files changed, 636 insertions(+), 1 deletions(-)
 create mode 100644 gdb/ravenscar-sparc-thread.c
 create mode 100644 gdb/ravenscar-thread.c
 create mode 100644 gdb/ravenscar-thread.h

diff --git a/gdb/configure.tgt b/gdb/configure.tgt
index ce063ef..500decd 100644
--- a/gdb/configure.tgt
+++ b/gdb/configure.tgt
@@ -519,7 +519,8 @@ sparc-*-rtems*)
 	;;
 sparc-*-*)
 	# Target: SPARC
-	gdb_target_obs="sparc-tdep.o"
+	gdb_target_obs="sparc-tdep.o ravenscar-thread.o \
+			ravenscar-sparc-thread.o"
 	;;
 sparc64-*-*)
 	# Target: UltraSPARC
diff --git a/gdb/ravenscar-sparc-thread.c b/gdb/ravenscar-sparc-thread.c
new file mode 100644
index 0000000..cb12a35
--- /dev/null
+++ b/gdb/ravenscar-sparc-thread.c
@@ -0,0 +1,184 @@
+/* Ravenscar ERC32 target support.
+
+   Copyright 2004, 2010 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/>.  */
+
+#include "defs.h"
+#include "gdbcore.h"
+#include "regcache.h"
+#include "sparc-tdep.h"
+#include "inferior.h"
+#include "ravenscar-thread.h"
+
+static struct ravenscar_arch_ops ravenscar_erc32_ops;
+
+static void ravenscar_erc32_fetch_registers (struct regcache *regcache,
+                                             int regnum);
+static void ravenscar_erc32_store_registers (struct regcache *regcache,
+                                             int regnum);
+static void ravenscar_erc32_prepare_to_store (struct regcache *regcache);
+
+/* Register offsets from a referenced address (exempli gratia the
+   Thread_Descriptor). The referenced address depends on the register
+   number. The Thread_Descriptor layout and the stack layout are documented
+   in the GNAT sources, in sparc-bb.h.  */
+
+static const int erc32_register_offsets[] =
+{
+  /* G0 - G7 */
+  -1,   0x24, 0x28, 0x2C, 0x30, 0x34, 0x38, 0x3C,
+  /* O0 - O7 */
+  0x00, 0x04, 0x08, 0x0C, 0x10, 0x14, 0x18, 0x1C,
+  /* L0 - L7 */
+  0x00, 0x04, 0x08, 0x0C, 0x10, 0x14, 0x18, 0x1C,
+  /* I0 - I7 */
+  0x20, 0x24, 0x28, 0x2C, 0x30, 0x34, 0x38, 0x3C,
+  /* F0 - F31 */
+  0x50, 0x54, 0x58, 0x5C, 0x60, 0x64, 0x68, 0x6C,
+  0x70, 0x74, 0x78, 0x7C, 0x80, 0x84, 0x88, 0x8C, 
+  0x90, 0x94, 0x99, 0x9C, 0xA0, 0xA4, 0xA8, 0xAC,
+  0xB0, 0xB4, 0xBB, 0xBC, 0xC0, 0xC4, 0xC8, 0xCC,
+  /* Y  PSR   WIM   TBR   PC    NPC   FPSR  CPSR */
+  0x40, 0x20, 0x44, -1,   0x1C, -1,   0x4C, -1
+};
+
+/* supply register REGNUM, which has been saved on REGISTER_ADDR, to the
+   regcache.  */
+
+static void
+supply_register_at_address (struct regcache *regcache, int regnum,
+                            CORE_ADDR register_addr)
+{
+  struct gdbarch *gdbarch = get_regcache_arch (regcache);
+  int buf_size = register_size (gdbarch, regnum);
+  char buf [buf_size];
+
+  read_memory (register_addr, buf, buf_size);
+  regcache_raw_supply (regcache, regnum, &buf);
+}
+
+/* Return true if, for a non-running thread, REGNUM has been saved on the
+   stack.  */
+
+static int
+register_on_stack_p (int regnum)
+{
+  return (regnum >= SPARC_L0_REGNUM && regnum <= SPARC_L7_REGNUM)
+    || (regnum >= SPARC_I0_REGNUM && regnum <= SPARC_I7_REGNUM);
+}
+
+/* Return true if, for a non-running thread, REGNUM has been saved on the
+   Thread_Descriptor.  */
+
+static int
+register_in_thread_descriptor_p (int regnum)
+{
+  return (regnum >= SPARC_O0_REGNUM && regnum <= SPARC_O7_REGNUM)
+    || (regnum == SPARC32_PSR_REGNUM)
+    || (regnum >= SPARC_G1_REGNUM && regnum <= SPARC_G7_REGNUM)
+    || (regnum == SPARC32_Y_REGNUM)
+    || (regnum == SPARC32_WIM_REGNUM)
+    || (regnum == SPARC32_FSR_REGNUM)
+    || (regnum >= SPARC_F0_REGNUM && regnum <= SPARC_F0_REGNUM + 31)
+    || (regnum == SPARC32_PC_REGNUM);
+}
+
+/* to_fetch_registers when inferior_ptid is different from the running
+   thread.  */
+
+static void
+ravenscar_erc32_fetch_registers (struct regcache *regcache, int regnum)
+{
+  struct gdbarch *gdbarch = get_regcache_arch (regcache);
+  const int sp_regnum = gdbarch_sp_regnum (gdbarch);
+  const int num_regs = gdbarch_num_regs (gdbarch);
+  int current_regnum;
+  CORE_ADDR current_address;
+  CORE_ADDR thread_descriptor_address;
+  ULONGEST stack_address;
+
+  thread_descriptor_address = (CORE_ADDR) ptid_get_tid (inferior_ptid);
+  current_address = thread_descriptor_address
+    + erc32_register_offsets [sp_regnum];
+  supply_register_at_address (regcache, sp_regnum, current_address);
+  regcache_cooked_read_unsigned (regcache, sp_regnum, &stack_address);
+
+  for (current_regnum = 0; current_regnum < num_regs; current_regnum ++)
+    {
+      if (register_in_thread_descriptor_p (current_regnum))
+        {
+          current_address = thread_descriptor_address
+            + erc32_register_offsets [current_regnum];
+          supply_register_at_address (regcache, current_regnum,
+                                      current_address);
+        }
+      else if (register_on_stack_p (current_regnum))
+        {
+          current_address = stack_address
+            + erc32_register_offsets [current_regnum];
+          supply_register_at_address (regcache, current_regnum,
+                                      current_address);
+        }
+    }
+}
+
+/* to_prepare_to_store when inferior_ptid is different from the running
+   thread.  */
+
+static void
+ravenscar_erc32_prepare_to_store (struct regcache *regcache)
+{
+  /* Nothing to do.  */
+}
+
+/* to_store_registers when inferior_ptid is different from the running
+   thread.  */
+
+static void
+ravenscar_erc32_store_registers (struct regcache *regcache, int regnum)
+{
+  struct gdbarch *gdbarch = get_regcache_arch (regcache);
+  int buf_size = register_size (gdbarch, regnum);
+  char buf [buf_size];
+  ULONGEST register_address;
+
+  if (register_in_thread_descriptor_p (regnum))
+    register_address =
+      ptid_get_tid (inferior_ptid) + erc32_register_offsets [regnum];
+  else if (register_on_stack_p (regnum))
+    {
+      regcache_cooked_read_unsigned (regcache, SPARC_SP_REGNUM,
+                                     &register_address);
+      register_address += erc32_register_offsets [regnum];
+    }
+  else
+    return;
+     
+  regcache_raw_collect (regcache, regnum, buf);
+  write_memory (register_address,
+                buf,
+                buf_size);
+}
+
+void
+_initialize_ravenscar_erc32 (void)
+{
+  ravenscar_erc32_ops.to_fetch_registers = ravenscar_erc32_fetch_registers;
+  ravenscar_erc32_ops.to_store_registers = ravenscar_erc32_store_registers;
+  ravenscar_erc32_ops.to_prepare_to_store = ravenscar_erc32_prepare_to_store;
+  ravenscar_register_arch_ops (&ravenscar_erc32_ops);
+}
diff --git a/gdb/ravenscar-thread.c b/gdb/ravenscar-thread.c
new file mode 100644
index 0000000..55f8a93
--- /dev/null
+++ b/gdb/ravenscar-thread.c
@@ -0,0 +1,409 @@
+/* Ada Ravenscar thread support.
+
+   Copyright 2004, 2009, 2010 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/>.  */
+
+#include "defs.h"
+#include "gdbcore.h"
+#include "gdbthread.h"
+#include "ada-lang.h"
+#include "target.h"
+#include "inferior.h"
+#include "command.h"
+#include "ravenscar-thread.h"
+#include "observer.h"
+#include "gdb_string.h"
+#include "gdbcmd.h"
+#include "top.h"
+#include "regcache.h"
+
+/* If non-null, ravenscar task support is enabled.  */
+static int ravenscar_task_support = 1;
+
+/* This module's target-specific operations.  */
+static struct target_ops ravenscar_ops;
+
+/* Some base target uses a special value for the null PID (exempli gratia
+   remote).  */
+static ptid_t base_magic_null_ptid;
+
+/* Ptid of the inferior as seen by the process stratum.  */
+static ptid_t base_ptid;
+
+static const char *running_thread_name = "running_thread";
+
+static const char *known_tasks_name = "system__tasking__debug__known_tasks";
+
+static const char *ravenscar_runtime_initializer =
+"system__bb__threads__initialize";
+
+static struct observer *update_target_observer = NULL;
+
+/* Architecture-specific hooks.  */
+static struct ravenscar_arch_ops* current_arch_ops;
+
+static CORE_ADDR read_thread_id (const char* symbol_name);
+
+static void ravenscar_find_new_threads (struct target_ops *ops);
+static ptid_t ravenscar_running_thread (void);
+static char * ravenscar_extra_thread_info (struct thread_info *tp);
+static int ravenscar_thread_alive (struct target_ops *ops, ptid_t ptid);
+static void ravenscar_fetch_registers (struct target_ops *ops,
+                                       struct regcache *regcache, int regnum);
+static void ravenscar_store_registers (struct target_ops *ops,
+                                       struct regcache *regcache, int regnum);
+static void ravenscar_prepare_to_store (struct regcache *regcache);
+static void ravenscar_initialize  (char *name, int from_tty);
+static void ravenscar_resume (struct target_ops *ops, ptid_t ptid, int step,
+			      enum target_signal siggnal);
+static void ravenscar_mourn_inferior (struct target_ops *ops);
+static void ravenscar_update_inferior_ptid (void);
+static int has_ravenscar_runtime (void);
+static int ravenscar_runtime_initialized (void);
+static void ravenscar_inferior_created (struct target_ops *target,
+					int from_tty);
+
+/* Fetch the ravenscar running thread from target memory and
+   update inferior_ptid accordingly.  */
+
+static void
+ravenscar_update_inferior_ptid (void)
+{
+  base_ptid = inferior_ptid;
+
+  /* If the runtime has not been initialized yet, the inferior_ptid is
+     the only ptid that there is.  */
+  if (!ravenscar_runtime_initialized ())
+    return;
+
+  /* Make sure we set base_ptid before calling ravenscar_running_thread
+     as the latter relies on it.  */
+  inferior_ptid = ravenscar_running_thread ();
+  gdb_assert (!ptid_equal (inferior_ptid, null_ptid));
+
+  /* The running thread may not have been added to
+     system.tasking.debug's list yet; so ravenscar_find_new_threads
+     may not always add it to the thread list.  Add it here.  */
+  if (!find_thread_ptid (inferior_ptid))
+    add_thread (inferior_ptid);
+}
+
+/* Return True if the Ada Ravenscar run-time can be found in the
+   application.  */
+
+static int
+has_ravenscar_runtime (void)
+{
+  struct minimal_symbol *msym_ravenscar_runtime_initializer =
+    lookup_minimal_symbol (ravenscar_runtime_initializer, NULL, NULL);
+  struct minimal_symbol *msym_known_tasks =
+    lookup_minimal_symbol (known_tasks_name, NULL, NULL);
+  struct minimal_symbol *msym_running_thread =
+    lookup_minimal_symbol (running_thread_name, NULL, NULL);
+
+  return (msym_ravenscar_runtime_initializer
+	  && msym_known_tasks
+	  && msym_running_thread);
+}
+
+/* Return True if the Ada Ravenscar run-time can be found in the
+   application, and if it has been initialized on target.  */
+
+static int
+ravenscar_runtime_initialized (void)
+{
+  return (!(ptid_equal (ravenscar_running_thread (), null_ptid)));
+}
+
+/* Read the thread ID whose symbol name is SYMBOL_NAME.  */
+
+static CORE_ADDR
+read_thread_id (const char* symbol_name)
+{
+  const struct minimal_symbol *object_msym =
+    lookup_minimal_symbol (symbol_name, NULL, NULL);
+  int object_size;
+  int buf_size;
+  char* buf;
+  CORE_ADDR object_addr;
+  struct type *builtin_type_void_data_ptr =
+    builtin_type (target_gdbarch)->builtin_data_ptr;
+
+  if (!object_msym)
+    return 0;
+
+  object_addr = SYMBOL_VALUE_ADDRESS (object_msym);
+  object_size = TYPE_LENGTH (builtin_type_void_data_ptr);
+  buf_size = object_size;
+  buf = alloca (buf_size);
+  read_memory (object_addr, buf, buf_size);
+  return extract_typed_address (buf, builtin_type_void_data_ptr);
+}
+
+static ptid_t
+ravenscar_wait (struct target_ops *ops, ptid_t ptid,
+                struct target_waitstatus *status,
+                int options)
+{
+  struct target_ops *beneath = find_target_beneath (ops);
+
+  inferior_ptid = base_ptid;
+  beneath->to_wait (ops, base_ptid, status, 0);
+  ravenscar_find_new_threads (ops);
+  ravenscar_update_inferior_ptid ();
+  return inferior_ptid;
+}
+
+static void
+ravenscar_resume (struct target_ops *ops, ptid_t ptid, int step,
+		  enum target_signal siggnal)
+{
+  struct target_ops *beneath = find_target_beneath (ops);
+
+  inferior_ptid = base_ptid;
+  beneath->to_resume (ops, base_ptid, step, siggnal);
+}
+
+/* Add the thread associated to the given TASK to the thread list
+   (if the thread has already been added, this is a no-op).  */
+
+static void
+ravenscar_add_thread (struct ada_task_info *task)
+{
+  if (find_thread_ptid (task->ptid) == NULL)
+    add_thread (task->ptid);
+}
+
+static void
+ravenscar_find_new_threads (struct target_ops *ops)
+{
+  ada_build_task_list (0);
+
+  /* Do not clear the thread list before adding the Ada task, to keep
+     the thread that the process stratum has included into it
+     (base_ptid) and the running thread, that may not have been included
+     to system.tasking.debug's list yet.  */
+
+  iterate_over_live_ada_tasks (ravenscar_add_thread);
+}
+
+static ptid_t
+ravenscar_running_thread (void)
+{
+  CORE_ADDR tid = read_thread_id (running_thread_name);
+
+  if (tid == 0)
+    return null_ptid;
+  else
+    return ptid_build (ptid_get_pid (base_ptid), 0, tid);
+}
+
+static char *
+ravenscar_extra_thread_info (struct thread_info *tp)
+{
+  return "Ravenscar task";
+}
+
+static int
+ravenscar_thread_alive (struct target_ops *ops, ptid_t ptid)
+{
+  /* Ravenscar tasks are non-terminating.  */
+  return 1;
+}
+
+static char *
+ravenscar_pid_to_str (struct target_ops *ops, ptid_t ptid)
+{
+  static char buf[30];
+
+  snprintf (buf, sizeof (buf), "Thread %#x", (int) ptid_get_tid (ptid));
+  return buf;
+}
+
+static void
+ravenscar_fetch_registers (struct target_ops *ops, 
+                           struct regcache *regcache, int regnum)
+{
+  struct target_ops *beneath = find_target_beneath (ops);
+
+  if (!ravenscar_runtime_initialized ()
+      || ptid_equal (inferior_ptid, base_magic_null_ptid)
+      || ptid_equal (inferior_ptid, ravenscar_running_thread ()))
+    beneath->to_fetch_registers (ops, regcache, regnum);
+  else
+    current_arch_ops->to_fetch_registers (regcache, regnum);
+}
+
+static void
+ravenscar_store_registers (struct target_ops *ops, 
+                           struct regcache *regcache, int regnum)
+{
+  struct target_ops *beneath = find_target_beneath (ops);
+
+  if (!ravenscar_runtime_initialized ()
+      || ptid_equal (inferior_ptid, base_magic_null_ptid)
+      || ptid_equal (inferior_ptid, ravenscar_running_thread ()))
+    beneath->to_store_registers (ops, regcache, regnum);
+  else
+    current_arch_ops->to_store_registers (regcache, regnum);
+}
+
+static void
+ravenscar_prepare_to_store (struct regcache *regcache)
+{
+  struct target_ops *beneath = find_target_beneath (&ravenscar_ops);
+
+  if (!ravenscar_runtime_initialized ()
+      || ptid_equal (inferior_ptid, base_magic_null_ptid)
+      || ptid_equal (inferior_ptid, ravenscar_running_thread ()))
+    beneath->to_prepare_to_store (regcache);
+  else
+    current_arch_ops->to_prepare_to_store (regcache);
+}
+
+static void
+ravenscar_mourn_inferior (struct target_ops *ops)
+{
+  struct target_ops *beneath = find_target_beneath (&ravenscar_ops);
+
+  base_ptid = null_ptid;
+  beneath->to_mourn_inferior (beneath);
+  unpush_target (&ravenscar_ops);
+}
+
+/* Observer on inferior_created: push ravenscar thread stratum if needed.  */
+
+static void
+ravenscar_inferior_created (struct target_ops *target, int from_tty)
+{
+  if (ravenscar_task_support
+      && has_ravenscar_runtime ()
+      && strcmp (target_shortname, ravenscar_ops.to_shortname) != 0)
+    ravenscar_initialize (NULL, 0);
+}
+
+void
+ravenscar_register_arch_ops (struct ravenscar_arch_ops *ops)
+{
+  /* FIXME: To be clean, we would need to handle a list of
+     architectures, just like in remote-wtx-hw.c.  However, for now the
+     only Ravenscar run-time for bare board that is implemented in
+     GNAT is for only one architecture: erc32-elf.  So no need to care about
+     that for now...*/
+  current_arch_ops = ops;
+}
+
+/* Initialize Ravenscar support.  */
+
+static void
+ravenscar_initialize (char *name, int from_tty)
+{
+  base_magic_null_ptid = inferior_ptid;
+  ravenscar_update_inferior_ptid ();
+  push_target (&ravenscar_ops);
+}
+
+static ptid_t
+ravenscar_get_ada_task_ptid (long lwp, long thread)
+{
+  return ptid_build (ptid_get_pid (base_ptid), 0, thread);
+}
+
+static void
+init_ravenscar_thread_ops (void)
+{
+  ravenscar_ops.to_shortname         = "ravenscar";
+  ravenscar_ops.to_longname          = "Ravenscar tasks.";
+  ravenscar_ops.to_doc               = "Ravenscar tasks support.";
+  ravenscar_ops.to_wait              = ravenscar_wait;
+  ravenscar_ops.to_resume            = ravenscar_resume;
+  ravenscar_ops.to_fetch_registers   = ravenscar_fetch_registers;
+  ravenscar_ops.to_store_registers   = ravenscar_store_registers;
+  ravenscar_ops.to_prepare_to_store  = ravenscar_prepare_to_store;
+  ravenscar_ops.to_thread_alive      = ravenscar_thread_alive;
+  ravenscar_ops.to_find_new_threads  = ravenscar_find_new_threads;
+  ravenscar_ops.to_pid_to_str        = ravenscar_pid_to_str;
+  ravenscar_ops.to_extra_thread_info = ravenscar_extra_thread_info;
+  ravenscar_ops.to_get_ada_task_ptid = ravenscar_get_ada_task_ptid;
+  ravenscar_ops.to_mourn_inferior    = ravenscar_mourn_inferior;
+  ravenscar_ops.to_has_all_memory    = default_child_has_all_memory;
+  ravenscar_ops.to_has_memory        = default_child_has_memory;
+  ravenscar_ops.to_has_stack         = default_child_has_stack;
+  ravenscar_ops.to_has_registers     = default_child_has_registers;
+  ravenscar_ops.to_has_execution     = default_child_has_execution;
+  ravenscar_ops.to_stratum           = thread_stratum;
+  ravenscar_ops.to_magic             = OPS_MAGIC;
+}
+
+
+/* Command-list for the "set/show ravenscar" prefix command.  */
+static struct cmd_list_element *set_ravenscar_list;
+static struct cmd_list_element *show_ravenscar_list;
+
+/* Implement the "set ravenscar" prefix command.  */
+
+static void
+set_ravenscar_command (char *arg, int from_tty)
+{
+  printf_unfiltered (_(\
+"\"set ravenscar\" must be followed by the name of a setting.\n"));
+  help_list (set_ravenscar_list, "set ravenscar ", -1, gdb_stdout);
+}
+
+/* Implement the "show ravenscar" prefix command.  */
+
+static void
+show_ravenscar_command (char *args, int from_tty)
+{
+  cmd_show_list (show_ravenscar_list, from_tty, "");
+}
+
+/* Module startup initialization function, automagically called by
+   init.c.  */
+
+void
+_initialize_ravenscar (void)
+{
+  extern struct cmd_list_element *cmdlist;
+
+  init_ravenscar_thread_ops ();
+  base_ptid = null_ptid;
+
+  /* Notice when the inferior is created in order to push the
+     ravenscar ops if needed.  */
+  observer_attach_inferior_created (ravenscar_inferior_created);
+
+  add_target (&ravenscar_ops);
+
+  add_prefix_cmd ("ravenscar", no_class, set_ravenscar_command,
+                  _("Prefix command for changing Ravenscar-specific settings"),
+                  &set_ravenscar_list, "set ravenscar ", 0, &setlist);
+
+  add_prefix_cmd ("ravenscar", no_class, show_ravenscar_command,
+                  _("Prefix command for showing Ravenscar-specific settings"),
+                  &show_ravenscar_list, "set ravenscar ", 0, &showlist);
+
+  add_setshow_boolean_cmd ("task-switching", class_obscure,
+                           &ravenscar_task_support, _("\
+Enable or disable support for GNAT Ravenscar tasks"), _("\
+Show whether supported for GNAT Ravenscar tasks is enabled"),
+                           _("\
+Enable or disable support for task/thread switching\n\
+with the GNAT Ravenscar run-time lib for bareboard configuration."),
+                            NULL, NULL, &set_ravenscar_list,
+			   &show_ravenscar_list);
+}
diff --git a/gdb/ravenscar-thread.h b/gdb/ravenscar-thread.h
new file mode 100644
index 0000000..c8844e3
--- /dev/null
+++ b/gdb/ravenscar-thread.h
@@ -0,0 +1,41 @@
+/* Ada Ravenscar thread support.
+
+   Copyright 2004, 2010 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 RAVENSCAR_THREAD_H
+#define RAVENSCAR_THREAD_H
+
+/* Architecture-specific hooks.  */
+
+struct ravenscar_arch_ops
+{
+  void (*to_fetch_registers) (struct regcache *, int);
+  void (*to_store_registers) (struct regcache *, int);
+  void (*to_prepare_to_store) (struct regcache *);
+};
+
+/* Register implementations for target ops to_store_registers,
+   to_prepare_to_store and to_fetch_registers when the inferior_ptid
+   is different from the running thread.  In that case, the registers
+   are saved in a architecture-specific location.  */
+/* FIXME: only one architecture can be registered for now. See
+   implementation.  */
+
+extern void ravenscar_register_arch_ops (struct ravenscar_arch_ops *ops);
+
+#endif /* !defined (RAVENSCAR_THREAD_H) */
-- 
1.6.5.rc2


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]