aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/gcov-io.h3
-rw-r--r--libgcc/config.in3
-rwxr-xr-xlibgcc/configure4
-rw-r--r--libgcc/configure.ac2
-rw-r--r--libgcc/libgcov-driver.c11
-rw-r--r--libgcc/libgcov.h42
6 files changed, 46 insertions, 19 deletions
diff --git a/gcc/gcov-io.h b/gcc/gcov-io.h
index baed676..75f16a2 100644
--- a/gcc/gcov-io.h
+++ b/gcc/gcov-io.h
@@ -292,9 +292,6 @@ GCOV_COUNTERS
/* Maximum number of tracked TOP N value profiles. */
#define GCOV_TOPN_MAXIMUM_TRACKED_VALUES 32
-/* Number of pre-allocated gcov_kvp structures. */
-#define GCOV_PREALLOCATED_KVP 64
-
/* Convert a counter index to a tag. */
#define GCOV_TAG_FOR_COUNTER(COUNT) \
(GCOV_TAG_COUNTER_BASE + ((gcov_unsigned_t)(COUNT) << 17))
diff --git a/libgcc/config.in b/libgcc/config.in
index 5be5321..f93c64a 100644
--- a/libgcc/config.in
+++ b/libgcc/config.in
@@ -49,6 +49,9 @@
/* Define to 1 if you have the <sys/auxv.h> header file. */
#undef HAVE_SYS_AUXV_H
+/* Define to 1 if you have the <sys/mman.h> header file. */
+#undef HAVE_SYS_MMAN_H
+
/* Define to 1 if you have the <sys/stat.h> header file. */
#undef HAVE_SYS_STAT_H
diff --git a/libgcc/configure b/libgcc/configure
index 78fc22a..dd3afb2 100755
--- a/libgcc/configure
+++ b/libgcc/configure
@@ -4458,7 +4458,7 @@ as_fn_arith $ac_cv_sizeof_long_double \* 8 && long_double_type_size=$as_val
for ac_header in inttypes.h stdint.h stdlib.h ftw.h \
unistd.h sys/stat.h sys/types.h \
- string.h strings.h memory.h sys/auxv.h
+ string.h strings.h memory.h sys/auxv.h sys/mman.h
do :
as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
ac_fn_c_check_header_preproc "$LINENO" "$ac_header" "$as_ac_Header"
@@ -4913,7 +4913,7 @@ case "$host" in
case "$enable_cet" in
auto)
# Check if target supports multi-byte NOPs
- # and if assembler supports CET insn.
+ # and if compiler and assembler support CET insn.
cet_save_CFLAGS="$CFLAGS"
CFLAGS="$CFLAGS -fcf-protection"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
diff --git a/libgcc/configure.ac b/libgcc/configure.ac
index ed50c0e..10ffb04 100644
--- a/libgcc/configure.ac
+++ b/libgcc/configure.ac
@@ -224,7 +224,7 @@ AC_SUBST(long_double_type_size)
AC_CHECK_HEADERS(inttypes.h stdint.h stdlib.h ftw.h \
unistd.h sys/stat.h sys/types.h \
- string.h strings.h memory.h sys/auxv.h)
+ string.h strings.h memory.h sys/auxv.h sys/mman.h)
AC_HEADER_STDC
# Check for decimal float support.
diff --git a/libgcc/libgcov-driver.c b/libgcc/libgcov-driver.c
index e474e03..9146235 100644
--- a/libgcc/libgcov-driver.c
+++ b/libgcc/libgcov-driver.c
@@ -588,11 +588,14 @@ struct gcov_root __gcov_root;
struct gcov_master __gcov_master =
{GCOV_VERSION, 0};
-/* Pool of pre-allocated gcov_kvp strutures. */
-struct gcov_kvp __gcov_kvp_pool[GCOV_PREALLOCATED_KVP];
+/* Dynamic pool for gcov_kvp structures. */
+struct gcov_kvp *__gcov_kvp_dynamic_pool;
-/* Index to first free gcov_kvp in the pool. */
-unsigned __gcov_kvp_pool_index;
+/* Index into __gcov_kvp_dynamic_pool array. */
+unsigned __gcov_kvp_dynamic_pool_index;
+
+/* Size of _gcov_kvp_dynamic_pool array. */
+unsigned __gcov_kvp_dynamic_pool_size;
void
__gcov_exit (void)
diff --git a/libgcc/libgcov.h b/libgcc/libgcov.h
index ddc6885..9c5fcfb 100644
--- a/libgcc/libgcov.h
+++ b/libgcc/libgcov.h
@@ -45,6 +45,10 @@
#include "libgcc_tm.h"
#include "gcov.h"
+#if HAVE_SYS_MMAN_H
+#include <sys/mman.h>
+#endif
+
#if __CHAR_BIT__ == 8
typedef unsigned gcov_unsigned_t __attribute__ ((mode (SI)));
typedef unsigned gcov_position_t __attribute__ ((mode (SI)));
@@ -250,8 +254,9 @@ struct indirect_call_tuple
/* Exactly one of these will be active in the process. */
extern struct gcov_master __gcov_master;
-extern struct gcov_kvp __gcov_kvp_pool[GCOV_PREALLOCATED_KVP];
-extern unsigned __gcov_kvp_pool_index;
+extern struct gcov_kvp *__gcov_kvp_dynamic_pool;
+extern unsigned __gcov_kvp_dynamic_pool_index;
+extern unsigned __gcov_kvp_dynamic_pool_size;
/* Dump a set of gcov objects. */
extern void __gcov_dump_one (struct gcov_root *) ATTRIBUTE_HIDDEN;
@@ -410,25 +415,44 @@ gcov_counter_add (gcov_type *counter, gcov_type value,
static inline struct gcov_kvp *
allocate_gcov_kvp (void)
{
+#define MMAP_CHUNK_SIZE (128 * 1024)
struct gcov_kvp *new_node = NULL;
+ unsigned kvp_sizeof = sizeof(struct gcov_kvp);
+
+ /* Try mmaped pool if available. */
+#if !defined(IN_GCOV_TOOL) && !defined(L_gcov_merge_topn) && HAVE_SYS_MMAN_H
+ if (__gcov_kvp_dynamic_pool == NULL
+ || __gcov_kvp_dynamic_pool_index >= __gcov_kvp_dynamic_pool_size)
+ {
+ void *ptr = mmap (NULL, MMAP_CHUNK_SIZE,
+ PROT_READ | PROT_WRITE,
+ MAP_PRIVATE | MAP_ANONYMOUS, 0, 0);
+ if (ptr != MAP_FAILED)
+ {
+ __gcov_kvp_dynamic_pool = ptr;
+ __gcov_kvp_dynamic_pool_size = MMAP_CHUNK_SIZE / kvp_sizeof;
+ __gcov_kvp_dynamic_pool_index = 0;
+ }
+ }
-#if !defined(IN_GCOV_TOOL) && !defined(L_gcov_merge_topn)
- if (__gcov_kvp_pool_index < GCOV_PREALLOCATED_KVP)
+ if (__gcov_kvp_dynamic_pool != NULL)
{
unsigned index;
#if GCOV_SUPPORTS_ATOMIC
index
- = __atomic_fetch_add (&__gcov_kvp_pool_index, 1, __ATOMIC_RELAXED);
+ = __atomic_fetch_add (&__gcov_kvp_dynamic_pool_index, 1,
+ __ATOMIC_RELAXED);
#else
- index = __gcov_kvp_pool_index++;
+ index = __gcov_kvp_dynamic_pool_index++;
#endif
- if (index < GCOV_PREALLOCATED_KVP)
- new_node = &__gcov_kvp_pool[index];
+ if (index < __gcov_kvp_dynamic_pool_size)
+ new_node = __gcov_kvp_dynamic_pool + index;
}
#endif
+ /* Fallback to malloc. */
if (new_node == NULL)
- new_node = (struct gcov_kvp *)xcalloc (1, sizeof (struct gcov_kvp));
+ new_node = (struct gcov_kvp *)xcalloc (1, kvp_sizeof);
return new_node;
}