[PATCH v3] malloc: Support hugepages in mremap_chunk

Carlos O'Donell carlos@redhat.com
Mon Aug 25 13:24:40 GMT 2025


On 8/20/25 3:46 PM, William Hunt wrote:
> Add mremap_chunk support for mmap()ed chunks using hugepages by accounting for
> their alignment, to prevent the mremap call failing in most cases where the
> size passed is not a hugepage size multiple. It also improves robustness for
> reallocating hugepages since mremap is much less likely to fail, so running
> out of memory when reallocating a larger size and having to copy the old
> contents after mremap fails is also less likely.
> 
> To track whether an mmap()ed chunk uses hugepages, have a flag in the lowest
> bit of the mchunk_prev_size field which is set after a call to sysmalloc_mmap,
> and accessed later in mremap_chunk. Create macros for getting and setting this
> bit, and for mapping the bit off when accessing the field for mmap()ed chunks.
> Since the alignment cannot be lower than 8 bits, this flag cannot affect the
> alignment data.
> 
> Add malloc/tst-tcfree4-malloc-check to the tests-exclude-malloc-check list as
> malloc-check prevents the tcache from being used to store chunks. This test
> caused failures due to a bug in mem2chunk_check to be fixed in a later patch.
> 
> Changes from v1:
> - Change macros to inlined functions.
> - Added malloc/tst-tcfree4 to tests-exclude-malloc-check as tcache is disabled.
> Changes from v2:
> - Removed a first mem2chunk_check fix, should be fully fixed in another patch.
> 
> Passed regress for THPs, neither and HPs using overcommit pages, OK for commit?

Thank you for all the work you've put into the patch!

This needs either DCO or copyright assignment.

Please review:
https://sourceware.org/glibc/wiki/Contribution%20checklist

Thank you!

> ---
>   malloc/Makefile       |  1 +
>   malloc/malloc-check.c |  4 ++--
>   malloc/malloc.c       | 41 +++++++++++++++++++++++++++++++++++------
>   3 files changed, 38 insertions(+), 8 deletions(-)
> 
> diff --git a/malloc/Makefile b/malloc/Makefile
> index 83f6c873e8..a9a0e87264 100644
> --- a/malloc/Makefile
> +++ b/malloc/Makefile
> @@ -114,6 +114,7 @@ tests-exclude-malloc-check = \
>     tst-memalign-3 \
>     tst-mxfast \
>     tst-safe-linking \
> +  tst-tcfree4 \
>   # tests-exclude-malloc-check
>   
>   # Run all tests with MALLOC_CHECK_=3
> diff --git a/malloc/malloc-check.c b/malloc/malloc-check.c
> index 9532316a29..7731eaeec5 100644
> --- a/malloc/malloc-check.c
> +++ b/malloc/malloc-check.c
> @@ -151,8 +151,8 @@ mem2chunk_check (void *mem, unsigned char **magic_p)
>              offset != 0x200 && offset != 0x400 && offset != 0x800 && offset != 0x1000 &&
>              offset < 0x2000) ||
>             !chunk_is_mmapped (p) || prev_inuse (p) ||
> -          ((((unsigned long) p - prev_size (p)) & page_mask) != 0) ||
> -          ((prev_size (p) + sz) & page_mask) != 0)
> +          ((((unsigned long) p - prev_size_mmap (p)) & page_mask) != 0) ||
> +          ((prev_size_mmap (p) + sz) & page_mask) != 0)
>           return NULL;
>   
>         for (sz = CHUNK_HDR_SZ + memsize (p) - 1;
> diff --git a/malloc/malloc.c b/malloc/malloc.c
> index e08873cad5..55688d4319 100644
> --- a/malloc/malloc.c
> +++ b/malloc/malloc.c
> @@ -1477,6 +1477,30 @@ tag_new_usable (void *ptr)
>     return ptr;
>   }
>   
> +/* HP page used for an mmap()'ed chunk. */
> +#define MMAP_HP 0x1
> +
> +/* Check for HP usage from an mmap()'ed chunk. */
> +static __always_inline bool
> +mmap_is_hp (mchunkptr p)
> +{
> +  return prev_size (p) & MMAP_HP;
> +}
> +
> +/* Set HP advised field for an mmap()'ed chunk. */
> +static __always_inline void
> +set_mmap_is_hp (mchunkptr p)
> +{
> +  prev_size (p) |= MMAP_HP;
> +}
> +
> +/* Get an mmap()ed chunk's offset, ignoring huge page bits. */
> +static __always_inline size_t
> +prev_size_mmap (mchunkptr p)
> +{
> +  return prev_size (p) & ~MMAP_HP;
> +}
> +
>   /*
>      -------------------- Internal data structures --------------------
>   
> @@ -2105,7 +2129,7 @@ do_check_chunk (mstate av, mchunkptr p)
>     else
>       {
>         /* chunk is page-aligned */
> -      assert (((prev_size (p) + sz) & (GLRO (dl_pagesize) - 1)) == 0);
> +      assert (((prev_size_mmap (p) + sz) & (GLRO (dl_pagesize) - 1)) == 0);
>         /* mem is aligned */
>         assert (!misaligned_chunk (p));
>       }
> @@ -2429,6 +2453,11 @@ sysmalloc_mmap (INTERNAL_SIZE_T nb, size_t pagesize, int extra_flags)
>     set_prev_size (p, padding);
>     set_head (p, (size - padding) | IS_MMAPPED);
>   
> +  /* Must also check whether huge pages were used in the mmap call
> +     and this is not the fallback call after using huge pages failed */
> +  if (__glibc_unlikely (extra_flags & mp_.hp_flags))
> +    set_mmap_is_hp (p);
> +
>     /* update statistics */
>     int new = atomic_fetch_add_relaxed (&mp_.n_mmaps, 1) + 1;
>     atomic_max (&mp_.max_n_mmaps, new);
> @@ -2982,8 +3011,8 @@ munmap_chunk (mchunkptr p)
>     assert (chunk_is_mmapped (p));
>   
>     uintptr_t mem = (uintptr_t) chunk2mem (p);
> -  uintptr_t block = (uintptr_t) p - prev_size (p);
> -  size_t total_size = prev_size (p) + size;
> +  uintptr_t block = (uintptr_t) p - prev_size_mmap (p);
> +  size_t total_size = prev_size_mmap (p) + size;
>     /* Unfortunately we have to do the compilers job by hand here.  Normally
>        we would test BLOCK and TOTAL-SIZE separately for compliance with the
>        page size.  But gcc does not recognize the optimization possibility
> @@ -3007,8 +3036,8 @@ munmap_chunk (mchunkptr p)
>   static mchunkptr
>   mremap_chunk (mchunkptr p, size_t new_size)
>   {
> -  size_t pagesize = GLRO (dl_pagesize);
> -  INTERNAL_SIZE_T offset = prev_size (p);
> +  size_t pagesize = mmap_is_hp (p) ? mp_.hp_pagesize : GLRO (dl_pagesize);
> +  INTERNAL_SIZE_T offset = prev_size_mmap (p);
>     INTERNAL_SIZE_T size = chunksize (p);
>     char *cp;
>   
> @@ -3040,7 +3069,7 @@ mremap_chunk (mchunkptr p, size_t new_size)
>   
>     assert (!misaligned_chunk (p));
>   
> -  assert (prev_size (p) == offset);
> +  assert (prev_size_mmap (p) == offset);
>     set_head (p, (new_size - offset) | IS_MMAPPED);
>   
>     INTERNAL_SIZE_T new;


-- 
Cheers,
Carlos.



More information about the Libc-alpha mailing list