* 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
+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
_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))
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
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 */
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);
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);
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
#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, ...)
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;
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;