[PATCH] libgcov support for profile collection in region of interest (issue6186044)

2012-05-08 Thread Teresa Johnson
Hi Honza,

I added L_gcov_reset and L_gcov_dump for the new interfaces, and also
added a description into the gcov man page. Let me know if it looks
ok now.

Bootstrapped and tested on x86_64-unknown-linux-gnu.

Thanks,
Teresa

2012-05-08   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.
* libgcc/Makefile.in (L_gcov_reset, L_gcov_dump): Define.
* gcc/doc/gcov.texi: Add note on using __gcov_reset and __gcov_dump.

Index: libgcc/Makefile.in
===
--- libgcc/Makefile.in  (revision 187048)
+++ libgcc/Makefile.in  (working copy)
@@ -849,7 +849,7 @@ include $(iterator)
 # Defined in libgcov.c, included only in gcov library
 LIBGCOV = _gcov _gcov_merge_add _gcov_merge_single _gcov_merge_delta \
 _gcov_fork _gcov_execl _gcov_execlp _gcov_execle \
-_gcov_execv _gcov_execvp _gcov_execve \
+_gcov_execv _gcov_execvp _gcov_execve _gcov_reset _gcov_dump \
 _gcov_interval_profiler _gcov_pow2_profiler _gcov_one_value_profiler \
 _gcov_indirect_call_profiler _gcov_average_profiler _gcov_ior_profiler \
 _gcov_merge_ior
Index: libgcc/libgcov.c
===
--- libgcc/libgcov.c(revision 187048)
+++ libgcc/libgcov.c(working copy)
@@ -50,6 +50,14 @@ void __gcov_init (struct gcov_info *p __attribute_
 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,7 +82,7 @@ void __gcov_merge_delta (gcov_type *counters  __at
 #include sys/stat.h
 #endif
 
-#ifdef L_gcov
+#if defined(L_gcov) || defined(L_gcov_reset) || defined(L_gcov_dump)
 #include gcov-io.c
 
 struct gcov_fn_buffer
@@ -91,6 +99,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 +297,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 +695,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,40 +777,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;
+  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];
-
- 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++;
-   }
-   }
-}
-
   __gthread_mutex_unlock (__gcov_flush_mx);
 }
 
 #endif /* L_gcov */
 
+#ifdef L_gcov_reset
+
+/* Function that can be called from 

Re: [PATCH] libgcov support for profile collection in region of interest (issue6186044)

2012-05-08 Thread Teresa Johnson
On Tue, May 8, 2012 at 10:37 AM, Jan Hubicka hubi...@ucw.cz wrote:

  Hi Honza,
 
  I added L_gcov_reset and L_gcov_dump for the new interfaces, and also
  added a description into the gcov man page. Let me know if it looks
  ok now.
 
  Bootstrapped and tested on x86_64-unknown-linux-gnu.
 
  Thanks,
  Teresa
 
  2012-05-08   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.
        * libgcc/Makefile.in (L_gcov_reset, L_gcov_dump): Define.
        * gcc/doc/gcov.texi: Add note on using __gcov_reset and __gcov_dump.

 It seems OK now, though gcov_clear will end up being in both gcov_reset and 
 gcov_flush,
 but I suppose it is short enough to make this issue mood
 (otherwise we could make it hidden exported from gcov_flush psection)

 Honza

The same issue is going to exist with gcov_exit and gcov_dump/gcov_flush, and
with gcov_dump_complete. I agree that it seems cleaner to export them hidden
so I have done that. Bootstrapped and re-testing is in progress. Ok for trunk
assuming regression tests pass? New patch is below.

Thanks,
Teresa

2012-05-08   Teresa Johnson  tejohn...@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.
* gcc/gcov-io.h (__gcov_reset, __gcov_dump): Declare.
* libgcc/Makefile.in (L_gcov_reset, L_gcov_dump): Define.
* gcc/doc/gcov.texi: Add note on using __gcov_reset and __gcov_dump.

Index: libgcc/Makefile.in
===
--- libgcc/Makefile.in  (revision 187048)
+++ libgcc/Makefile.in  (working copy)
@@ -849,7 +849,7 @@ include $(iterator)
 # Defined in libgcov.c, included only in gcov library
 LIBGCOV = _gcov _gcov_merge_add _gcov_merge_single _gcov_merge_delta \
 _gcov_fork _gcov_execl _gcov_execlp _gcov_execle \
-_gcov_execv _gcov_execvp _gcov_execve \
+_gcov_execv _gcov_execvp _gcov_execve _gcov_reset _gcov_dump \
 _gcov_interval_profiler _gcov_pow2_profiler _gcov_one_value_profiler \
 _gcov_indirect_call_profiler _gcov_average_profiler _gcov_ior_profiler \
 _gcov_merge_ior
Index: libgcc/libgcov.c
===
--- libgcc/libgcov.c(revision 187048)
+++ libgcc/libgcov.c(working copy)
@@ -50,6 +50,14 @@ void __gcov_init (struct gcov_info *p __attribute_
 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  __at
 #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
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 = 

Re: [PATCH] libgcov support for profile collection in region of interest (issue6186044)

2012-05-08 Thread Jan Hubicka
 On Tue, May 8, 2012 at 10:37 AM, Jan Hubicka hubi...@ucw.cz wrote:
 
   Hi Honza,
  
   I added L_gcov_reset and L_gcov_dump for the new interfaces, and also
   added a description into the gcov man page. Let me know if it looks
   ok now.
  
   Bootstrapped and tested on x86_64-unknown-linux-gnu.
  
   Thanks,
   Teresa
  
   2012-05-08   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.
         * libgcc/Makefile.in (L_gcov_reset, L_gcov_dump): Define.
         * gcc/doc/gcov.texi: Add note on using __gcov_reset and __gcov_dump.
 
  It seems OK now, though gcov_clear will end up being in both gcov_reset and 
  gcov_flush,
  but I suppose it is short enough to make this issue mood
  (otherwise we could make it hidden exported from gcov_flush psection)
 
  Honza
 
 The same issue is going to exist with gcov_exit and gcov_dump/gcov_flush, and
 with gcov_dump_complete. I agree that it seems cleaner to export them hidden
 so I have done that. Bootstrapped and re-testing is in progress. Ok for trunk
 assuming regression tests pass? New patch is below.
OK,
thanks
Honza


Re: [PATCH] libgcov support for profile collection in region of interest (issue6186044)

2012-05-07 Thread Xinliang David Li
+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
 

Re: [PATCH] libgcov support for profile collection in region of interest (issue6186044)

2012-05-07 Thread Jan Hubicka
 +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?

This seems resonable things to do.  You need to add an documentation and make 
sure they
go new L_* section, since not every app using libgcov needs necesarily those 
two.

Honza
 
  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 

[PATCH] libgcov support for profile collection in region of interest (issue6186044)

2012-05-03 Thread Teresa Johnson
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 @@