summaryrefslogtreecommitdiff
path: root/libgcc
diff options
context:
space:
mode:
authornathan <nathan@138bc75d-0d04-0410-961f-82ee72b054a4>2014-09-17 20:13:17 +0000
committernathan <nathan@138bc75d-0d04-0410-961f-82ee72b054a4>2014-09-17 20:13:17 +0000
commitbc587267bd85c2b30d8c0e8448ee6a5739271516 (patch)
treed63e4fa5645e26ab19e311988498d7daa883d937 /libgcc
parent4e9d716449178cb0f04ac33efe1039debc2bb18f (diff)
downloadgcc-bc587267bd85c2b30d8c0e8448ee6a5739271516.tar.gz
* 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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@215337 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'libgcc')
-rw-r--r--libgcc/ChangeLog18
-rw-r--r--libgcc/Makefile.in5
-rw-r--r--libgcc/libgcov-driver.c25
-rw-r--r--libgcc/libgcov-interface.c30
-rw-r--r--libgcc/libgcov.h14
5 files changed, 79 insertions, 13 deletions
diff --git a/libgcc/ChangeLog b/libgcc/ChangeLog
index 8922a3b3fa1..6c6e386b96e 100644
--- a/libgcc/ChangeLog
+++ b/libgcc/ChangeLog
@@ -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
diff --git a/libgcc/Makefile.in b/libgcc/Makefile.in
index 6a6cf66d698..de03c47b6d1 100644
--- a/libgcc/Makefile.in
+++ b/libgcc/Makefile.in
@@ -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))
diff --git a/libgcc/libgcov-driver.c b/libgcc/libgcov-driver.c
index 34c58cd5fec..7bde5261878 100644
--- a/libgcc/libgcov-driver.c
+++ b/libgcc/libgcov-driver.c
@@ -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 */
diff --git a/libgcc/libgcov-interface.c b/libgcc/libgcov-interface.c
index e40268991af..3e6ec20b999 100644
--- a/libgcc/libgcov-interface.c
+++ b/libgcc/libgcov-interface.c
@@ -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, ...)
diff --git a/libgcc/libgcov.h b/libgcc/libgcov.h
index 98a15d134a7..3816b6a7090 100644
--- a/libgcc/libgcov.h
+++ b/libgcc/libgcov.h
@@ -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;