coarray_43.f90: Add "-latomic" option if libatomic_available.
[gcc.git] / libgcc / libgcov-interface.c
index 5e23178b87e3b3038b007cb54c5fc2021736f291..61089e970064910fc91e8ab5d1b0019a16d0a3b6 100644 (file)
@@ -1,6 +1,6 @@
 /* Routines required for instrumenting a program.  */
 /* Compile this one with gcc.  */
-/* Copyright (C) 1989-2013 Free Software Foundation, Inc.
+/* Copyright (C) 1989-2017 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -23,20 +23,9 @@ a copy of the GCC Runtime Library Exception along with this program;
 see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
 <http://www.gnu.org/licenses/>.  */
 
-#include "tconfig.h"
-#include "tsystem.h"
-#include "coretypes.h"
-#include "tm.h"
-#include "libgcc_tm.h"
+#include "libgcov.h"
 #include "gthr.h"
 
-#if defined(inhibit_libc)
-#define IN_LIBGCOV (-1)
-#else
-#define IN_LIBGCOV 1
-#endif
-#include "gcov-io.h"
-
 #if defined(inhibit_libc)
 
 #ifdef L_gcov_flush
@@ -53,24 +42,31 @@ void __gcov_dump (void) {}
 
 #else
 
-extern void gcov_clear (void) ATTRIBUTE_HIDDEN;
-extern void gcov_exit (void) ATTRIBUTE_HIDDEN;
-extern void set_gcov_dump_complete (void) ATTRIBUTE_HIDDEN;
-extern void reset_gcov_dump_complete (void) ATTRIBUTE_HIDDEN;
+/* Some functions we want to bind in this dynamic object, but have an
+   overridable global alias.  Unfortunately not all targets support
+   aliases, so we just have a forwarding function.  That'll be tail
+   called, so the cost is a single jump instruction.*/
 
-#ifdef L_gcov_flush
+#define ALIAS_void_fn(src,dst) \
+  void dst (void)          \
+  { src (); }
 
+extern __gthread_mutex_t __gcov_flush_mx ATTRIBUTE_HIDDEN;
+extern __gthread_mutex_t __gcov_flush_mx ATTRIBUTE_HIDDEN;
+
+#ifdef L_gcov_flush
 #ifdef __GTHREAD_MUTEX_INIT
-ATTRIBUTE_HIDDEN __gthread_mutex_t __gcov_flush_mx = __GTHREAD_MUTEX_INIT;
+__gthread_mutex_t __gcov_flush_mx = __GTHREAD_MUTEX_INIT;
 #define init_mx_once()
 #else
-__gthread_mutex_t __gcov_flush_mx ATTRIBUTE_HIDDEN;
+__gthread_mutex_t __gcov_flush_mx;
 
 static void
 init_mx (void)
 {
   __GTHREAD_MUTEX_INIT_FUNCTION (&__gcov_flush_mx);
 }
+
 static void
 init_mx_once (void)
 {
@@ -89,8 +85,8 @@ __gcov_flush (void)
   init_mx_once ();
   __gthread_mutex_lock (&__gcov_flush_mx);
 
-  gcov_exit ();
-  gcov_clear ();
+  __gcov_dump_int ();
+  __gcov_reset_int ();
 
   __gthread_mutex_unlock (&__gcov_flush_mx);
 }
@@ -99,35 +95,78 @@ __gcov_flush (void)
 
 #ifdef L_gcov_reset
 
+/* Reset all counters to zero.  */
+
+static void
+gcov_clear (const struct gcov_info *list)
+{
+  const struct gcov_info *gi_ptr;
+
+  for (gi_ptr = 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++;
+            }
+        }
+    }
+}
+
 /* 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_reset_int (void)
 {
-  gcov_clear ();
-  /* Re-enable dumping to support collecting profile in multiple regions
-     of interest.  */
-  reset_gcov_dump_complete ();
+  struct gcov_root *root;
+
+  /* If we're compatible with the master, iterate over everything,
+     otherise just do us.  */
+  for (root = __gcov_master.version == GCOV_VERSION
+        ? __gcov_master.root : &__gcov_root; root; root = root->next)
+    {
+      gcov_clear (root->list);
+      root->dumped = 0;
+    }
 }
 
+ALIAS_void_fn (__gcov_reset_int, __gcov_reset);
+
 #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_dump_int (void)
 {
-  gcov_exit ();
-  /* Prevent profile from being dumped a second time on application exit.  */
-  set_gcov_dump_complete ();
+  struct gcov_root *root;
+
+  /* If we're compatible with the master, iterate over everything,
+     otherise just do us.  */
+  for (root = __gcov_master.version == GCOV_VERSION
+        ? __gcov_master.root : &__gcov_root; root; root = root->next)
+    __gcov_dump_one (root);
 }
 
-#endif /* L_gcov_dump */
+ALIAS_void_fn (__gcov_dump_int, __gcov_dump);
 
+#endif /* L_gcov_dump */
 
 #ifdef L_gcov_fork
 /* A wrapper for the fork function.  Flushes the accumulated profiling data, so
@@ -137,7 +176,6 @@ pid_t
 __gcov_fork (void)
 {
   pid_t pid;
-  extern __gthread_mutex_t __gcov_flush_mx;
   __gcov_flush ();
   pid = fork ();
   if (pid == 0)
@@ -147,8 +185,8 @@ __gcov_fork (void)
 #endif
 
 #ifdef L_gcov_execl
-/* A wrapper for the execl function.  Flushes the accumulated profiling data, so
-   that they are not lost.  */
+/* A wrapper for the execl function.  Flushes the accumulated
+   profiling data, so that they are not lost.  */
 
 int
 __gcov_execl (const char *path, char *arg, ...)
@@ -178,8 +216,8 @@ __gcov_execl (const char *path, char *arg, ...)
 #endif
 
 #ifdef L_gcov_execlp
-/* A wrapper for the execlp function.  Flushes the accumulated profiling data, so
-   that they are not lost.  */
+/* A wrapper for the execlp function.  Flushes the accumulated
+   profiling data, so that they are not lost.  */
 
 int
 __gcov_execlp (const char *path, char *arg, ...)
@@ -209,8 +247,8 @@ __gcov_execlp (const char *path, char *arg, ...)
 #endif
 
 #ifdef L_gcov_execle
-/* A wrapper for the execle function.  Flushes the accumulated profiling data, so
-   that they are not lost.  */
+/* A wrapper for the execle function.  Flushes the accumulated
+   profiling data, so that they are not lost.  */
 
 int
 __gcov_execle (const char *path, char *arg, ...)
@@ -242,8 +280,8 @@ __gcov_execle (const char *path, char *arg, ...)
 #endif
 
 #ifdef L_gcov_execv
-/* A wrapper for the execv function.  Flushes the accumulated profiling data, so
-   that they are not lost.  */
+/* A wrapper for the execv function.  Flushes the accumulated
+   profiling data, so that they are not lost.  */
 
 int
 __gcov_execv (const char *path, char *const argv[])
@@ -254,8 +292,8 @@ __gcov_execv (const char *path, char *const argv[])
 #endif
 
 #ifdef L_gcov_execvp
-/* A wrapper for the execvp function.  Flushes the accumulated profiling data, so
-   that they are not lost.  */
+/* A wrapper for the execvp function.  Flushes the accumulated
+   profiling data, so that they are not lost.  */
 
 int
 __gcov_execvp (const char *path, char *const argv[])
@@ -266,8 +304,8 @@ __gcov_execvp (const char *path, char *const argv[])
 #endif
 
 #ifdef L_gcov_execve
-/* A wrapper for the execve function.  Flushes the accumulated profiling data, so
-   that they are not lost.  */
+/* A wrapper for the execve function.  Flushes the accumulated
+   profiling data, so that they are not lost.  */
 
 int
 __gcov_execve (const char *path, char *const argv[], char *const envp[])