Makefile.in (LIBGCOV_INTERFACE): Add _gcov_dump from ...
authorNathan Sidwell <nathan@acm.org>
Wed, 17 Sep 2014 20:13:17 +0000 (20:13 +0000)
committerNathan Sidwell <nathan@gcc.gnu.org>
Wed, 17 Sep 2014 20:13:17 +0000 (20:13 +0000)
* Makefile.in (LIBGCOV_INTERFACE): Add _gcov_dump from ...
(LIBGCOV_DRIVER): ... here.
* libgcov-driver.c (gcov_master): New.
(gcov_exit): Remove from master chain.
(__gcov_init): Add to master chain if version compatible.  Don't
clear the version.
* libgcov_interface (__gcov_flust): Call gcov_dump_int.
(gcov_reset_int): Clear master chain, if compatible.
(gcov_dump_int): New internal interface.  Dump master chain, if
compatible.
(gcov_dump): Alias for gcov_dump_int.
* libgcov.h (struct gcov_root): Add next and prev fields.
(struct gcov_master): New struct.
(__gcov_master): New.
(gcov_dump_int): Declare.

From-SVN: r215337

libgcc/ChangeLog
libgcc/Makefile.in
libgcc/libgcov-driver.c
libgcc/libgcov-interface.c
libgcc/libgcov.h

index 8922a3b3fa1e1174b386ed3f027bba6f9e67c9d0..6c6e386b96eab473650fc035c8cc31049b6591e6 100644 (file)
@@ -1,3 +1,21 @@
+2014-09-17  Nathan sidwell  <nathan@acm.org>
+
+       * Makefile.in (LIBGCOV_INTERFACE): Add _gcov_dump from ...
+       (LIBGCOV_DRIVER): ... here.
+       * libgcov-driver.c (gcov_master): New.
+       (gcov_exit): Remove from master chain.
+       (__gcov_init): Add to master chain if version compatible.  Don't
+       clear the version.
+       * libgcov_interface (__gcov_flust): Call gcov_dump_int.
+       (gcov_reset_int): Clear master chain, if compatible.
+       (gcov_dump_int): New internal interface.  Dump master chain, if
+       compatible.
+       (gcov_dump): Alias for gcov_dump_int.
+       * libgcov.h (struct gcov_root): Add next and prev fields.
+       (struct gcov_master): New struct.
+       (__gcov_master): New.
+       (gcov_dump_int): Declare.
+
 2014-09-17  Olivier Hainque  <hainque@adacore.com>
 
        * config.host (x86_64-*-mingw*): Add i386/t-cygming to tmake_file
index 6a6cf66d6989f73daf2bf7c64b6859e1e75fc551..de03c47b6d14febcfd2a370e3d2dcc7b1be66e6d 100644 (file)
@@ -858,9 +858,10 @@ LIBGCOV_PROFILER = _gcov_interval_profiler _gcov_pow2_profiler             \
        _gcov_one_value_profiler _gcov_indirect_call_profiler           \
        _gcov_average_profiler _gcov_ior_profiler                       \
        _gcov_indirect_call_profiler_v2 _gcov_time_profiler
-LIBGCOV_INTERFACE = _gcov_flush _gcov_fork _gcov_execl _gcov_execlp    \
+LIBGCOV_INTERFACE = _gcov_dump _gcov_flush _gcov_fork                  \
+       _gcov_execl _gcov_execlp                                        \
        _gcov_execle _gcov_execv _gcov_execvp _gcov_execve _gcov_reset
-LIBGCOV_DRIVER = _gcov _gcov_dump
+LIBGCOV_DRIVER = _gcov
 
 libgcov-merge-objects = $(patsubst %,%$(objext),$(LIBGCOV_MERGE))
 libgcov-profiler-objects = $(patsubst %,%$(objext),$(LIBGCOV_PROFILER))
index 34c58cd5feca5c6db06c14c8f8c691f9d780bca2..7bde5261878a2ccab36e8fb3c65dc9879b4364eb 100644 (file)
@@ -777,13 +777,23 @@ __gcov_dump_one (struct gcov_root *root)
   root->run_counted = 1;
 }
 
-/* Per-program/shared-object gcov state.  */
+/* Per-dynamic-object gcov state.  */
 struct gcov_root __gcov_root;
 
+/* Exactly one of these will be live in the process image.  */
+struct gcov_master __gcov_master = 
+  {GCOV_VERSION, 0};
+
 static void
 gcov_exit (void)
 {
   __gcov_dump_one (&__gcov_root);
+  if (__gcov_root.next)
+    __gcov_root.next->prev = __gcov_root.prev;
+  if (__gcov_root.prev)
+    __gcov_root.prev->next = __gcov_root.next;
+  else
+    __gcov_master.root = __gcov_root.next;
 }
 
 /* Add a new object file onto the bb chain.  Invoked automatically
@@ -797,12 +807,21 @@ __gcov_init (struct gcov_info *info)
   if (gcov_version (info, info->version, 0))
     {
       if (!__gcov_root.list)
-        atexit (gcov_exit);
+       {
+         /* Add to master list and at exit function.  */
+         if (gcov_version (NULL, __gcov_master.version, "<master>"))
+           {
+             __gcov_root.next = __gcov_master.root;
+             if (__gcov_master.root)
+               __gcov_master.root->prev = &__gcov_root;
+             __gcov_master.root = &__gcov_root;
+           }
+         atexit (gcov_exit);
+       }
 
       info->next = __gcov_root.list;
       __gcov_root.list = info;
     }
-  info->version = 0;
 }
 #endif /* !IN_GCOV_TOOL */
 #endif /* L_gcov */
index e40268991af57de16e1539fcd99f4e936d05ae24..3e6ec20b99950731cedd4cfd42f15b953d69984d 100644 (file)
@@ -85,7 +85,7 @@ __gcov_flush (void)
   init_mx_once ();
   __gthread_mutex_lock (&__gcov_flush_mx);
 
-  __gcov_dump_one (&__gcov_root);
+  __gcov_dump_int ();
   __gcov_reset_int ();
 
   __gthread_mutex_unlock (&__gcov_flush_mx);
@@ -132,8 +132,16 @@ gcov_clear (const struct gcov_info *list)
 void
 __gcov_reset_int (void)
 {
-  gcov_clear (__gcov_root.list);
-  __gcov_root.dumped = 0;
+  struct gcov_root *root;
+
+  /* If we're compatible with the master, iterate over everything,
+     otherise just do us.  */
+  for (root = __gcov_master.version == GCOV_VERSION
+        ? __gcov_master.root : &__gcov_root; root; root = root->next)
+    {
+      gcov_clear (root->list);
+      root->dumped = 0;
+    }
 }
 
 ALIAS_void_fn (__gcov_reset_int, __gcov_reset);
@@ -145,11 +153,19 @@ ALIAS_void_fn (__gcov_reset_int, __gcov_reset);
    so far, in order to collect profile in region of interest.  */
 
 void
-__gcov_dump (void)
+__gcov_dump_int (void)
 {
-  __gcov_dump_one (&__gcov_root);
+  struct gcov_root *root;
+
+  /* If we're compatible with the master, iterate over everything,
+     otherise just do us.  */
+  for (root = __gcov_master.version == GCOV_VERSION
+        ? __gcov_master.root : &__gcov_root; root; root = root->next)
+    __gcov_dump_one (root);
 }
 
+ALIAS_void_fn (__gcov_dump_int, __gcov_dump);
+
 #endif /* L_gcov_dump */
 
 #ifdef L_gcov_fork
@@ -169,8 +185,8 @@ __gcov_fork (void)
 #endif
 
 #ifdef L_gcov_execl
-/* A wrapper for the execl function.  Flushes the accumulated profiling data, so
-   that they are not lost.  */
+/* A wrapper for the execl function.  Flushes the accumulated
+   profiling data, so that they are not lost.  */
 
 int
 __gcov_execl (const char *path, char *arg, ...)
index 98a15d134a7adcaa2c0da09e7c4dd4ba474fd9b5..3816b6a7090ec62c430812619f1e994cb009910d 100644 (file)
@@ -212,10 +212,21 @@ struct gcov_root
   struct gcov_info *list;
   unsigned dumped : 1; /* counts have been dumped.  */
   unsigned run_counted : 1;  /* run has been accounted for.  */
+  struct gcov_root *next;
+  struct gcov_root *prev;
 };
 
 extern struct gcov_root __gcov_root ATTRIBUTE_HIDDEN;
 
+struct gcov_master
+{
+  gcov_unsigned_t version;
+  struct gcov_root *root;
+};
+  
+/* Exactly one of these will be active in the process.  */
+extern struct gcov_master __gcov_master;
+
 /* Dump a set of gcov objects.  */
 extern void __gcov_dump_one (struct gcov_root *) ATTRIBUTE_HIDDEN;
 
@@ -230,8 +241,9 @@ extern void __gcov_flush (void) ATTRIBUTE_HIDDEN;
 extern void __gcov_reset (void);
 extern void __gcov_reset_int (void) ATTRIBUTE_HIDDEN;
 
-/* Function to enable early write of profile information so far.  */
+/* User function to enable early write of profile information so far.  */
 extern void __gcov_dump (void);
+extern void __gcov_dump_int (void) ATTRIBUTE_HIDDEN;
 
 /* The merge function that just sums the counters.  */
 extern void __gcov_merge_add (gcov_type *, unsigned) ATTRIBUTE_HIDDEN;