diff options
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 |