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))) {}
#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"
/* 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. */
in two separate programs, and we must keep the two program
summaries separate. */
-static void
+void
gcov_exit (void)
{
struct gcov_info *gi_ptr;
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));
}
}
+/* 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. */
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