[PATCH] Support hugepages in mremap_chunk

Adhemerval Zanella Netto adhemerval.zanella@linaro.org
Wed Aug 20 11:28:21 GMT 2025



On 18/08/25 07:30, 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. 
> 
> Update mem2chunk in malloc-check.c to check whether the memory is from a top 
> chunk, to prevent later checks from triggering a SEGSEGV by attempting to 
> access the mchunk_prev_size field of the next chunk. This prevents the 
> malloc/tst-tcfree4-malloc-check test from failing when ran using hugepages and 
> glibc.malloc.hugetlb=2, since the main arena is marked non-contiguous and the 
> previous checks that would cause NULL to be returned do not run before the 
> next chunk is attempted to be accessed.
> 
> Passed regress for THPs, neither and HPs using overcommit pages, OK for commit?
> ---
>  malloc/malloc-check.c |  6 +++---
>  malloc/malloc.c       | 29 +++++++++++++++++++++++------
>  2 files changed, 26 insertions(+), 9 deletions(-)
> 
> diff --git a/malloc/malloc-check.c b/malloc/malloc-check.c
> index 9532316a29..350086e58c 100644
> --- a/malloc/malloc-check.c
> +++ b/malloc/malloc-check.c
> @@ -121,7 +121,7 @@ mem2chunk_check (void *mem, unsigned char **magic_p)
>      {
>        /* Must be a chunk in conventional heap memory. */
>        int contig = contiguous (&main_arena);
> -      if ((contig &&
> +      if (((contig || p == main_arena.top) &&
>             ((char *) p < mp_.sbrk_base ||
>              ((char *) p + sz) >= (mp_.sbrk_base + main_arena.system_mem))) ||
>            sz < MINSIZE || sz & MALLOC_ALIGN_MASK || !inuse (p) ||
> @@ -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..1a7035da30 100644
> --- a/malloc/malloc.c
> +++ b/malloc/malloc.c
> @@ -1477,6 +1477,18 @@ 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. */
> +#define mmap_is_hp(p) (prev_size (p) & MMAP_HP)
> +
> +/* Set HP advised field for an mmap()'ed chunk. */
> +#define set_mmap_is_hp(p) (prev_size (p) |= MMAP_HP)
> +
> +/* Get an mmap()ed chunk's offset, ignoring huge page bits. */
> +#define prev_size_mmap(p) (prev_size (p) & ~MMAP_HP)

The patch looks good, the only thing I would ask is to move away from
macros and used static inline function in new code (even though the
practice for this old implementation is to use macros).

> +
>  /*
>     -------------------- Internal data structures --------------------
>  
> @@ -2105,7 +2117,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 +2441,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 +2999,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 +3024,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 +3057,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;



More information about the Libc-alpha mailing list