> Hello.
> 
> AS mentioned here, https://gcc.gnu.org/bugzilla/show_bug.cgi?id=97461#c25, I 
> like
> what Richard suggested. So instead of usage of malloc, we should use mmap 
> memory
> chunks that serve as a memory pool for struct gcov_kvp.
> 
> Malloc is used as a fallback when mmap is not available. I also drop 
> statically
> pre-allocated static pool, mmap solves the root problem.
> 
> Patch can bootstrap on x86_64-linux-gnu and survives regression tests.
> 
> Ready to be installed?
> Thanks,
> Martin
> 
> 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.
OK, thanks.
We should be ready to add support for non-mmap targets (especially
mingw).  

Honza
> ---
>  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 <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 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 b4a7e942a7e..e848811d89d 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;
>  }
> -- 
> 2.30.0
> 

Reply via email to