This is the mail archive of the gdb-patches@sources.redhat.com 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]

[patch/rfa:doc] Make gdbarch_data() on-demand


Hello,

At present each per-architecture data-pointer is inititalized during 
architecture creation.  Unfortunatly, due to inter-module dependencies, 
the initialization sequence has to be carefully ordered (by tweaking 
Makefile.in or other code).

The attached patch alters the behavour of the function gdbarch_data() so 
that it, instead, inititalizes the per-architecture data-pointer on-demand.

[Eli, I revised the doco to match this behavour]

Comments?  I'll look to check it in, in a few days.
Andrew

PS: This is the start of the merge of the ``struct regcache'' branch.
2002-05-31  Andrew Cagney  <ac131313@redhat.com>

	* gdbarch.sh (struct gdbarch_data): Add field init_p.
	(register_gdbarch_data): Initialize init_p.
	(gdbarch_data): Initialize data pointer using the init function.
	(init_gdbarch_data): Delete function.
	(gdbarch_update_p): Update.
	(initialize_non_multiarch): Update.
	(struct gdbarch): Add field initialized_p.
	* gdbarch.h, gdbarch.c: Re-generate.

Index: doc/ChangeLog
2002-05-31  Andrew Cagney  <ac131313@redhat.com>

	* gdbint.texinfo (Coding): Add section ``Per-architecture module
	data''.

Index: gdbarch.sh
===================================================================
RCS file: /cvs/src/src/gdb/gdbarch.sh,v
retrieving revision 1.140
diff -u -r1.140 gdbarch.sh
--- gdbarch.sh	29 May 2002 16:39:55 -0000	1.140
+++ gdbarch.sh	1 Jun 2002 19:13:37 -0000
@@ -1082,20 +1082,15 @@
    for the reserved data-pointer is returned.  That identifer should
    be saved in a local static variable.
 
-   The per-architecture data-pointer can be initialized in one of two
-   ways: The value can be set explicitly using a call to
-   set_gdbarch_data(); the value can be set implicitly using the value
-   returned by a non-NULL INIT() callback.  INIT(), when non-NULL is
-   called after the basic architecture vector has been created.
+   The per-architecture data-pointer is either initialized explicitly
+   (set_gdbarch_data()) or implicitly (by INIT() via a call to
+   gdbarch_data()).  FREE() is called to delete either an existing
+   data-poitner overridden by set_gdbarch_data() or when the
+   architecture object is being deleted.
 
    When a previously created architecture is re-selected, the
    per-architecture data-pointer for that previous architecture is
-   restored.  INIT() is not called.
-
-   During initialization, multiple assignments of the data-pointer are
-   allowed, non-NULL values are deleted by calling FREE().  If the
-   architecture is deleted using gdbarch_free() all non-NULL data
-   pointers are also deleted using FREE().
+   restored.  INIT() is not re-called.
 
    Multiple registrarants for any architecture are allowed (and
    strongly encouraged).  */
@@ -1249,7 +1244,6 @@
 
 static void verify_gdbarch (struct gdbarch *gdbarch);
 static void alloc_gdbarch_data (struct gdbarch *);
-static void init_gdbarch_data (struct gdbarch *);
 static void free_gdbarch_data (struct gdbarch *);
 static void init_gdbarch_swap (struct gdbarch *);
 static void clear_gdbarch_swap (struct gdbarch *);
@@ -1271,6 +1265,8 @@
 printf "\n"
 printf "struct gdbarch\n"
 printf "{\n"
+printf "  /* Has this architecture been fully initialized?  */\n"
+printf "  int initialized_p;\n"
 printf "  /* basic architectural information */\n"
 function_list | while do_read
 do
@@ -1343,6 +1339,7 @@
 printf "\n"
 printf "struct gdbarch startup_gdbarch =\n"
 printf "{\n"
+printf "  1, /* Always initialized.  */\n"
 printf "  /* basic architecture information */\n"
 function_list | while do_read
 do
@@ -1381,7 +1378,6 @@
      they are starting from scratch.  */
   clear_gdbarch_swap (&startup_gdbarch);
   init_gdbarch_swap (&startup_gdbarch);
-  init_gdbarch_data (&startup_gdbarch);
 }
 EOF
 
@@ -1747,6 +1743,7 @@
 struct gdbarch_data
 {
   unsigned index;
+  int init_p;
   gdbarch_data_init_ftype *init;
   gdbarch_data_free_ftype *free;
 };
@@ -1773,6 +1770,7 @@
                        gdbarch_data_free_ftype *free)
 {
   struct gdbarch_data_registration **curr;
+  /* Append the new registraration.  */
   for (curr = &gdbarch_data_registry.registrations;
        (*curr) != NULL;
        curr = &(*curr)->next);
@@ -1781,31 +1779,12 @@
   (*curr)->data = XMALLOC (struct gdbarch_data);
   (*curr)->data->index = gdbarch_data_registry.nr++;
   (*curr)->data->init = init;
+  (*curr)->data->init_p = 1;
   (*curr)->data->free = free;
   return (*curr)->data;
 }
 
 
-/* Walk through all the registered users initializing each in turn. */
-
-static void
-init_gdbarch_data (struct gdbarch *gdbarch)
-{
-  struct gdbarch_data_registration *rego;
-  for (rego = gdbarch_data_registry.registrations;
-       rego != NULL;
-       rego = rego->next)
-    {
-      struct gdbarch_data *data = rego->data;
-      gdb_assert (data->index < gdbarch->nr_data);
-      if (data->init != NULL)
-        {
-          void *pointer = data->init (gdbarch);
-          set_gdbarch_data (gdbarch, data, pointer);
-        }
-    }
-}
-
 /* Create/delete the gdbarch data vector. */
 
 static void
@@ -1838,7 +1817,7 @@
 }
 
 
-/* Initialize the current value of thee specified per-architecture
+/* Initialize the current value of the specified per-architecture
    data-pointer. */
 
 void
@@ -1847,8 +1826,11 @@
                   void *pointer)
 {
   gdb_assert (data->index < gdbarch->nr_data);
-  if (data->free != NULL && gdbarch->data[data->index] != NULL)
-    data->free (gdbarch, gdbarch->data[data->index]);
+  if (gdbarch->data[data->index] != NULL)
+    {
+      gdb_assert (data->free != NULL);
+      data->free (gdbarch, gdbarch->data[data->index]);
+    }
   gdbarch->data[data->index] = pointer;
 }
 
@@ -1859,6 +1841,20 @@
 gdbarch_data (struct gdbarch *gdbarch, struct gdbarch_data *data)
 {
   gdb_assert (data->index < gdbarch->nr_data);
+  /* The data-pointer isn't initialized, call init() to get a value but
+     only if the architecture initializaiton has completed.  Otherwise
+     punt - hope that the caller knows what they are doing.  */
+  if (gdbarch->data[data->index] == NULL
+      && gdbarch->initialized_p)
+    {
+      /* Be careful to detect an initialization cycle.  */
+      gdb_assert (data->init_p);
+      data->init_p = 0;
+      gdb_assert (data->init != NULL);
+      gdbarch->data[data->index] = data->init (gdbarch);
+      data->init_p = 1;
+      gdb_assert (gdbarch->data[data->index] != NULL);
+    }
   return gdbarch->data[data->index];
 }
 
@@ -2252,8 +2248,9 @@
     rego->arches = this;
   }    
 
-  /* Switch to this new architecture.  Dump it out. */
+  /* Switch to this new architecture marking it initialized.  */
   current_gdbarch = new_gdbarch;
+  current_gdbarch->initialized_p = 1;
   if (gdbarch_debug)
     {
       fprintf_unfiltered (gdb_stdlog,
@@ -2272,10 +2269,8 @@
      called. */
   init_gdbarch_swap (new_gdbarch);
   
-  /* Initialize the per-architecture data-pointer of all parties that
-     registered an interest in this architecture.  CURRENT_GDBARCH
+  /* Initialize the per-architecture data.  CURRENT_GDBARCH
      must be updated before these modules are called. */
-  init_gdbarch_data (new_gdbarch);
   architecture_changed_event ();
 
   if (gdbarch_debug)
Index: doc/gdbint.texinfo
===================================================================
RCS file: /cvs/src/src/gdb/doc/gdbint.texinfo,v
retrieving revision 1.86
diff -u -r1.86 gdbint.texinfo
--- doc/gdbint.texinfo	31 May 2002 01:36:16 -0000	1.86
+++ doc/gdbint.texinfo	1 Jun 2002 19:13:56 -0000
@@ -4446,6 +4446,107 @@
 functions, since they might never return to your code (they
 @samp{longjmp} instead).
 
+@section Per-architecture module data
+@cindex per-architecture module data
+@cindex multi-arch data
+@cindex data-pointer, per-architecture/per-module
+
+The multi-arch framework includes a mechanism for adding module specific
+per-architecture data-pointers to the @code{struct gdbarch} architecture
+object.
+
+A module registers one or more per-architecture data-pointers using the
+function @code{register_gdbarch_data}:
+
+@deftypefun struct gdbarch_data *register_gdbarch_data (gdbarch_data_init_ftype *@var{init}, gdbarch_data_free_ftype *@var{free})
+
+The @var{init} function is used to obtain an initial value for a
+per-architecture data-pointer.  The function is called, after the
+architecture has been created, when the data-pointer is still
+uninitialized (@code{NULL}) and its value has been requested via a call
+to @code{gdbarch_data}.  A data-pointer can also be initialize
+explicitly using @code{set_gdbarch_data}.
+
+The @var{free} function is called when a data-pointer needs to be
+destroyed.  This occurs when either the corresponding @code{struct
+gdbarch} object is being destroyed or when @code{set_gdbarch_data} is
+overriding a non-@code{NULL} data-pointer value.
+
+The function @code{register_gdbarch_data} returns a @code{struct
+gdbarch_data} that is used to identify the data-pointer that was added
+to the module.
+
+@end deftypefun
+
+A typical module has @code{init} and @code{free} functions of the form:
+
+@smallexample
+static struct gdbarch_data *nozle_data_handle;
+static void *
+nozel_data_init (struct gdbarch *gdbarch)
+@{
+  struct nozel_data *data = XMALLOC (struct nozel_data);
+  @dots{}
+  return data;
+@}
+@dots{}
+static void
+nozel_data_free (struct gdbarch *gdbarch, void *data)
+@{
+  xfree (data);
+@}
+@end smallexample
+
+Since uninitialized (@code{NULL}) data-pointers are initialized
+on-demand, an @code{init} function is free to call other modules that
+use data-pointers.  Those modules data-pointers will be initialized as
+needed.  Care should be taken to ensure that the @code{init} call graph
+does not contain cycles.
+
+The data-pointer is registered with the call:
+
+@smallexample
+void
+_initialize_nozel (void)
+@{
+  nozel_data_handle =
+    register_gdbarch_data (nozel_data_init, nozel_data_free);
+@dots{}
+@end smallexample
+
+The per-architecture data-pointer is accessed using the function:
+
+@deftypefun void *gdbarch_data (struct gdbarch *@var{gdbarch}, struct gdbarch_data *@var{data_handle})
+Given the architecture @var{arch} and module data handle
+@var{data_handle} (returned by @code{register_gdbarch_data}, this
+function returns the current value of the per-architecture data-pointer.
+@end deftypefun
+
+The non-@code{NULL} data-pointer returned by @code{gdbarch_data} should
+be saved in a local variable and then used directly:
+
+@smallexample
+int
+nozel_total (struct gdbarch *gdbarch)
+@{
+  int total;
+  struct nozel_data *data = gdbarch_data (gdbarch, nozel_data_handle);
+  @dots{}
+  return total;
+@}
+@end smallexample
+
+It is also possible to explicitly initialize the data-pointer using:
+
+@deftypefun void set_gdbarch_data (struct gdbarch *@var{gdbarch}, struct gdbarch_data *handle, void *@var{pointer})
+Update the data-pointer corresponding to @var{handle} with the value of
+@var{pointer}.  If the previous data-pointer value is non-NULL, then it
+is freed using data-pointers @var{free} function.
+@end deftypefun
+
+This function is used by modules that need to save explicitly selected
+per-architecture configuration information during architecture creation.
+
 @section Wrapping Output Lines
 @cindex line wrap in output
 

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