diff options
author | Teresa Johnson <tejohnson@google.com> | 2012-05-08 21:22:28 +0000 |
---|---|---|
committer | Teresa Johnson <tejohnson@gcc.gnu.org> | 2012-05-08 21:22:28 +0000 |
commit | 4e8ee9cbf7895df0147627c88a682d3e4d789779 (patch) | |
tree | e8169275509aad912d8d4b57d59a52610ef8bcc8 /libgcc/libgcov.c | |
parent | 564fe867d8a1abfaa30303b3eca98e9b782fcdc9 (diff) | |
download | gcc-4e8ee9cbf7895df0147627c88a682d3e4d789779.zip gcc-4e8ee9cbf7895df0147627c88a682d3e4d789779.tar.gz gcc-4e8ee9cbf7895df0147627c88a682d3e4d789779.tar.bz2 |
This patch adds functionality to libgcov to enable user applications to collect...
This patch adds functionality to libgcov to enable user applications to
collect profile data only in regions of interest. This is useful, for
example, to collect profile data from a long-running server only
during the time when it is serving requests.
Specifically, the new routines __gcov_reset will clear all profile counters
to zero and __gcov_dump will write out the profile information collected so
far. A global variable is used to prevent writing out the profile a
second time during exit.
2012-05-08 Teresa Johnson <tejohnson@google.com>
* libgcc/libgcov.c (gcov_clear, __gcov_reset): New functions.
(__gcov_dump): Ditto.
(gcov_dump_complete): New global variable.
(gcov_exit): Export hidden to enable use in L_gcov_dump.
(__gcov_flush): Outline functionality now in gcov_clear.
* libgcc/Makefile.in (L_gcov_reset, L_gcov_dump): Define.
* gcc/gcov-io.h (__gcov_reset, __gcov_dump): Declare.
* gcc/doc/gcov.texi: Add note on using __gcov_reset and __gcov_dump.
From-SVN: r187297
Diffstat (limited to 'libgcc/libgcov.c')
-rw-r--r-- | libgcc/libgcov.c | 109 |
1 files changed, 84 insertions, 25 deletions
diff --git a/libgcc/libgcov.c b/libgcc/libgcov.c index ee7fda4..8ed8971 100644 --- a/libgcc/libgcov.c +++ b/libgcc/libgcov.c @@ -50,6 +50,14 @@ void __gcov_init (struct gcov_info *p __attribute__ ((unused))) {} void __gcov_flush (void) {} #endif +#ifdef L_gcov_reset +void __gcov_reset (void) {} +#endif + +#ifdef L_gcov_dump +void __gcov_dump (void) {} +#endif + #ifdef L_gcov_merge_add void __gcov_merge_add (gcov_type *counters __attribute__ ((unused)), unsigned n_counters __attribute__ ((unused))) {} @@ -74,6 +82,10 @@ void __gcov_merge_delta (gcov_type *counters __attribute__ ((unused)), #include <sys/stat.h> #endif +extern void gcov_clear (void) ATTRIBUTE_HIDDEN; +extern void gcov_exit (void) ATTRIBUTE_HIDDEN; +extern int gcov_dump_complete ATTRIBUTE_HIDDEN; + #ifdef L_gcov #include "gcov-io.c" @@ -91,6 +103,9 @@ static struct gcov_info *gcov_list; /* Size of the longest file name. */ static size_t gcov_max_filename = 0; +/* Flag when the profile has already been dumped via __gcov_dump(). */ +int gcov_dump_complete = 0; + /* Make sure path component of the given FILENAME exists, create missing directories. FILENAME must be writable. Returns zero on success, or -1 if an error occurred. */ @@ -268,7 +283,7 @@ gcov_version (struct gcov_info *ptr, gcov_unsigned_t version, in two separate programs, and we must keep the two program summaries separate. */ -static void +void gcov_exit (void) { struct gcov_info *gi_ptr; @@ -286,6 +301,11 @@ gcov_exit (void) char *gi_filename, *gi_filename_up; gcov_unsigned_t crc32 = 0; + /* Prevent the counters from being dumped a second time on exit when the + application already wrote out the profile using __gcov_dump(). */ + if (gcov_dump_complete) + return; + memset (&all_prg, 0, sizeof (all_prg)); /* Find the totals for this execution. */ memset (&this_prg, 0, sizeof (this_prg)); @@ -679,6 +699,37 @@ gcov_exit (void) } } +/* Reset all counters to zero. */ + +void +gcov_clear (void) +{ + const struct gcov_info *gi_ptr; + + for (gi_ptr = gcov_list; gi_ptr; gi_ptr = gi_ptr->next) + { + unsigned f_ix; + + for (f_ix = 0; f_ix < gi_ptr->n_functions; f_ix++) + { + unsigned t_ix; + const struct gcov_fn_info *gfi_ptr = gi_ptr->functions[f_ix]; + + if (!gfi_ptr || gfi_ptr->key != gi_ptr) + continue; + const struct gcov_ctr_info *ci_ptr = gfi_ptr->ctrs; + for (t_ix = 0; t_ix != GCOV_COUNTERS; t_ix++) + { + if (!gi_ptr->merge[t_ix]) + continue; + + memset (ci_ptr->values, 0, sizeof (gcov_type) * ci_ptr->num); + ci_ptr++; + } + } + } +} + /* Add a new object file onto the bb chain. Invoked automatically when running an object file's global ctors. */ @@ -730,40 +781,48 @@ init_mx_once (void) void __gcov_flush (void) { - const struct gcov_info *gi_ptr; - init_mx_once (); __gthread_mutex_lock (&__gcov_flush_mx); gcov_exit (); - for (gi_ptr = gcov_list; gi_ptr; gi_ptr = gi_ptr->next) - { - unsigned f_ix; - - for (f_ix = 0; f_ix < gi_ptr->n_functions; f_ix++) - { - unsigned t_ix; - const struct gcov_fn_info *gfi_ptr = gi_ptr->functions[f_ix]; - - if (!gfi_ptr || gfi_ptr->key != gi_ptr) - continue; - const struct gcov_ctr_info *ci_ptr = gfi_ptr->ctrs; - for (t_ix = 0; t_ix != GCOV_COUNTERS; t_ix++) - { - if (!gi_ptr->merge[t_ix]) - continue; - - memset (ci_ptr->values, 0, sizeof (gcov_type) * ci_ptr->num); - ci_ptr++; - } - } - } + gcov_clear (); __gthread_mutex_unlock (&__gcov_flush_mx); } #endif /* L_gcov */ +#ifdef L_gcov_reset + +/* Function that can be called from application to reset counters to zero, + in order to collect profile in region of interest. */ + +void +__gcov_reset (void) +{ + gcov_clear (); + /* Re-enable dumping to support collecting profile in multiple regions + of interest. */ + gcov_dump_complete = 0; +} + +#endif /* L_gcov_reset */ + +#ifdef L_gcov_dump + +/* Function that can be called from application to write profile collected + so far, in order to collect profile in region of interest. */ + +void +__gcov_dump (void) +{ + gcov_exit (); + /* Prevent profile from being dumped a second time on application exit. */ + gcov_dump_complete = 1; +} + +#endif /* L_gcov_dump */ + #ifdef L_gcov_merge_add /* The profile merging function that just adds the counters. It is given an array COUNTERS of N_COUNTERS old counters and it reads the same number |