From 00d79dc4be0b86ec564cfa2b32c47de6c07449e6 Mon Sep 17 00:00:00 2001 From: Martin Liska Date: Wed, 13 Jan 2021 11:17:03 +0100 Subject: [PATCH] gcov: use mmap pools for KVP. gcc/ChangeLog: PR gcov-profile/97461 * gcov-io.h (GCOV_PREALLOCATED_KVP): Remove. libgcc/ChangeLog: PR gcov-profile/97461 * config.in: Regenerate. * configure: Likewise. * configure.ac: Check sys/mman.h header file * libgcov-driver.c (struct gcov_kvp): Remove static pre-allocated pool and use a dynamic one. * libgcov.h (MMAP_CHUNK_SIZE): New. (gcov_counter_add): Use mmap to allocate pool for struct gcov_kvp. --- gcc/gcov-io.h | 3 --- libgcc/config.in | 3 +++ libgcc/configure | 4 ++-- libgcc/configure.ac | 2 +- libgcc/libgcov-driver.c | 11 +++++++---- libgcc/libgcov.h | 42 ++++++++++++++++++++++++++++++++--------- 6 files changed, 46 insertions(+), 19 deletions(-) diff --git a/gcc/gcov-io.h b/gcc/gcov-io.h index baed67609e2..75f16a274c7 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 5be5321d258..f93c64a00c3 100644 --- a/libgcc/config.in +++ b/libgcc/config.in @@ -49,6 +49,9 @@ /* Define to 1 if you have the header file. */ #undef HAVE_SYS_AUXV_H +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_MMAN_H + /* Define to 1 if you have the header file. */ #undef HAVE_SYS_STAT_H diff --git a/libgcc/configure b/libgcc/configure index 78fc22a5784..dd3afb2c957 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 ed50c0e9b49..10ffb046415 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 e474e032b54..91462350132 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 ddc688509bd..9c5fcfba4ad 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 +#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); -#if !defined(IN_GCOV_TOOL) && !defined(L_gcov_merge_topn) - if (__gcov_kvp_pool_index < GCOV_PREALLOCATED_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 (__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; }