This patch adds functionality to libgcov to enable user applications to collect...
authorTeresa Johnson <tejohnson@google.com>
Tue, 8 May 2012 21:22:28 +0000 (21:22 +0000)
committerTeresa Johnson <tejohnson@gcc.gnu.org>
Tue, 8 May 2012 21:22:28 +0000 (21:22 +0000)
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

gcc/ChangeLog
gcc/doc/gcov.texi
gcc/gcov-io.h
libgcc/ChangeLog
libgcc/Makefile.in
libgcc/libgcov.c

index 27072e60909a6f33bc886f34e14affa82a95ed2f..a3f5a8fd9d6c4f64d1968b3c6a67c3f1ab046824 100644 (file)
@@ -1,3 +1,8 @@
+2012-05-08   Teresa Johnson  <tejohnson@google.com>
+
+       * gcov-io.h (__gcov_reset, __gcov_dump): Declare.
+       * doc/gcov.texi: Add note on using __gcov_reset and __gcov_dump.
+
 2012-05-08  Jan Hubicka  <jh@suse.cz>
 
        * cgraph.c (cgraph_call_edge_duplication_hooks): Export.
index e771f72e4027dbcb05a3f2942235105bd6b44872..7256664c0ee9ecb7951f6f2cf941721186ab84a4 100644 (file)
@@ -538,6 +538,12 @@ now be calculable at compile time in some instances.  Because the
 coverage of all the uses of the inline function will be shown for the
 same source lines, the line counts themselves might seem inconsistent.
 
+Long-running applications can use the @code{_gcov_reset} and @code{_gcov_dump}
+facilities to restrict profile collection to the program region of
+interest. Calling @code{_gcov_reset(void)} will clear all profile counters
+to zero, and calling @code{_gcov_dump(void)} will cause the profile information
+collected at that point to be dumped to @file{.gcda} output files.
+
 @c man end
 
 @node Gcov Data Files
index b80f70696207ead8ccb42050103088bdb0ed2ab7..c15e64b197b64762770726259c3edd683c4f5dd0 100644 (file)
@@ -458,6 +458,12 @@ extern void __gcov_init (struct gcov_info *) ATTRIBUTE_HIDDEN;
 /* 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;
 
index 2d60c3f97f1e9613faa8a68eb316f54297c75054..9b5c53a126aea1483c341b7b8a08bcab5610dc60 100644 (file)
@@ -1,3 +1,12 @@
+2012-05-08   Teresa Johnson  <tejohnson@google.com>
+
+       * 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.
+       * Makefile.in (L_gcov_reset, L_gcov_dump): Define.
+
 2012-04-28  Aurelien Jarno  <aurelien@aurel32.net>
 
        * config.host (mips64*-*-linux*, mipsisa64*-*-linux*): Remove. 
index 23b72b92475e60e6ffb54463bbc650aed44a9247..e9ea2e9c90d800d308e164aaa7a3f941decdb4a7 100644 (file)
@@ -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 ee7fda4eac9447874409dc02b685d9d67274548f..8ed897117f723f2ab4f4f0b6be31414ca8b829d7 100644 (file)
@@ -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