+Honza and Nathan. David
On Thu, May 3, 2012 at 10:52 AM, Teresa Johnson <tejohn...@google.com> wrote: > 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. > > Bootstrapped and tested on x86_64-unknown-linux-gnu. Is this ok for trunk? > > Thanks, > Teresa > > 2012-05-03 Teresa Johnson <tejohn...@google.com> > > * libgcc/libgcov.c (gcov_clear, __gcov_reset): New functions. > (__gcov_dump): Ditto. > (gcov_dump_complete): New global variable. > (__gcov_flush): Outline functionality now in gcov_clear. > * gcc/gcov-io.h (__gcov_reset, __gcov_dump): Declare. > > Index: libgcc/libgcov.c > =================================================================== > --- libgcc/libgcov.c (revision 187048) > +++ libgcc/libgcov.c (working copy) > @@ -48,6 +48,8 @@ see the files COPYING3 and COPYING.RUNTIME respect > #ifdef L_gcov > void __gcov_init (struct gcov_info *p __attribute__ ((unused))) {} > void __gcov_flush (void) {} > +void __gcov_reset (void) {} > +void __gcov_dump (void) {} > #endif > > #ifdef L_gcov_merge_add > @@ -91,6 +93,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(). */ > +static 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. */ > @@ -286,6 +291,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 +689,37 @@ gcov_exit (void) > } > } > > +/* Reset all counters to zero. */ > + > +static 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,38 +771,38 @@ 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; > + gcov_clear (); > > - 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]; > + __gthread_mutex_unlock (&__gcov_flush_mx); > +} > > - 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++; > - } > - } > - } > +/* Function that can be called from application to reset counters to zero, > + in order to collect profile in region of interest. */ > > - __gthread_mutex_unlock (&__gcov_flush_mx); > +void > +__gcov_reset (void) > +{ > + gcov_clear (); > + /* Re-enable dumping to support collecting profile in multiple regions > + of interest. */ > + gcov_dump_complete = 0; > } > > +/* 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 */ > > #ifdef L_gcov_merge_add > Index: gcc/gcov-io.h > =================================================================== > --- gcc/gcov-io.h (revision 187048) > +++ gcc/gcov-io.h (working copy) > @@ -458,6 +458,12 @@ extern void __gcov_init (struct gcov_info *) ATTRI > /* Called before fork, to avoid double counting. */ > extern void __gcov_flush (void) ATTRIBUTE_HIDDEN; > > +/* Function to reset all counters to 0. */ > +extern void __gcov_reset (void); > + > +/* Function to enable early write of profile information so far. */ > +extern void __gcov_dump (void); > + > /* The merge function that just sums the counters. */ > extern void __gcov_merge_add (gcov_type *, unsigned) ATTRIBUTE_HIDDEN; > > > -- > This patch is available for review at http://codereview.appspot.com/6186044