diff options
author | nathan <nathan@138bc75d-0d04-0410-961f-82ee72b054a4> | 2014-09-17 20:13:17 +0000 |
---|---|---|
committer | nathan <nathan@138bc75d-0d04-0410-961f-82ee72b054a4> | 2014-09-17 20:13:17 +0000 |
commit | bc587267bd85c2b30d8c0e8448ee6a5739271516 (patch) | |
tree | d63e4fa5645e26ab19e311988498d7daa883d937 /libgcc | |
parent | 4e9d716449178cb0f04ac33efe1039debc2bb18f (diff) | |
download | gcc-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/ChangeLog | 18 | ||||
-rw-r--r-- | libgcc/Makefile.in | 5 | ||||
-rw-r--r-- | libgcc/libgcov-driver.c | 25 | ||||
-rw-r--r-- | libgcc/libgcov-interface.c | 30 | ||||
-rw-r--r-- | libgcc/libgcov.h | 14 |
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; |