aboutsummaryrefslogtreecommitdiff
path: root/libgcc
diff options
context:
space:
mode:
Diffstat (limited to 'libgcc')
-rw-r--r--libgcc/ChangeLog9
-rw-r--r--libgcc/Makefile.in2
-rw-r--r--libgcc/libgcov.c109
3 files changed, 94 insertions, 26 deletions
diff --git a/libgcc/ChangeLog b/libgcc/ChangeLog
index 2d60c3f..9b5c53a 100644
--- a/libgcc/ChangeLog
+++ b/libgcc/ChangeLog
@@ -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.
diff --git a/libgcc/Makefile.in b/libgcc/Makefile.in
index 23b72b9..e9ea2e9 100644
--- a/libgcc/Makefile.in
+++ b/libgcc/Makefile.in
@@ -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
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