[PATCH] malloc: Cleanup macros, asserts and sysmalloc_mmap_fallback.

William Hunt william.hunt@arm.com
Wed Aug 27 08:53:10 GMT 2025


Refactor malloc.c to remove dead code, create macros to abstract duplicated 
code, and cleanup sysmalloc_mmap_fallback to remove logic not related to the 
mmap call.

Cleanup sysmalloc_mmap_fallback. Remove unused parameters nb, oldsize 
and av. Remove redundant overflow check and instead use size_t for all 
parameters except extra_flags to prevent overflows. Move logic not concerned 
with the mmap call itself outside the function after both calls to 
sysmalloc_mmap_fallback are made; this means move code for naming the VMA 
and marking the arena being extended as non-contiguous to the calling code to 
be handled in the case that the mmap is successful. Calculate the fallback 
size from nb to avoid modifying size after it has been set for MORECORE. 

Create mmap_base and mmap_size inline functions to avoid repeated code in 
munmap_chunk and mremap_chunk. 

Remove unused noncontiguous macro. 

Remove redundant assert for checking unreachable option for global_max_fast. 

Passed regress, OK for commit?

Covered by Arm's copyright assignment. 
---
 malloc/malloc.c | 75 +++++++++++++++++++++++++------------------------
 1 file changed, 38 insertions(+), 37 deletions(-)

diff --git a/malloc/malloc.c b/malloc/malloc.c
index e08873cad5..adb22da04c 100644
--- a/malloc/malloc.c
+++ b/malloc/malloc.c
@@ -1453,6 +1453,19 @@ checked_request2size (size_t req) __nonnull (1)
 #pragma GCC poison mchunk_size
 #pragma GCC poison mchunk_prev_size
 
+/* Get the start of the mmap()'ed region of an mmap()'ed chunk.  */
+static __always_inline uintptr_t
+mmap_base (mchunkptr p)
+{
+  return (uintptr_t) p - prev_size (p);
+}
+
+static __always_inline size_t
+mmap_size (mchunkptr p)
+{
+  return prev_size (p) + chunksize (p);
+}
+
 /* This is the size of the real usable data in the chunk.  Not valid for
    dumped heap chunks.  */
 #define memsize(p)                                                    \
@@ -1771,7 +1784,6 @@ typedef struct malloc_chunk *mfastbinptr;
 #define NONCONTIGUOUS_BIT     (2U)
 
 #define contiguous(M)          (((M)->flags & NONCONTIGUOUS_BIT) == 0)
-#define noncontiguous(M)       (((M)->flags & NONCONTIGUOUS_BIT) != 0)
 #define set_noncontiguous(M)   ((M)->flags |= NONCONTIGUOUS_BIT)
 #define set_contiguous(M)      ((M)->flags &= ~NONCONTIGUOUS_BIT)
 
@@ -2286,9 +2298,6 @@ do_check_malloc_state (mstate av)
 
   /* properties of fastbins */
 
-  /* max_fast is in allowed range */
-  assert ((get_max_fast () & ~1) <= request2size (MAX_FAST_SIZE));
-
   max_fast_bin = fastbin_index (get_max_fast ());
 
   for (i = 0; i < NFASTBINS; ++i)
@@ -2449,24 +2458,15 @@ sysmalloc_mmap (INTERNAL_SIZE_T nb, size_t pagesize, int extra_flags)
    if MORECORE fails.
  */
 static void *
-sysmalloc_mmap_fallback (long int *s, INTERNAL_SIZE_T nb,
-			 INTERNAL_SIZE_T old_size, size_t minsize,
-			 size_t pagesize, int extra_flags, mstate av)
+sysmalloc_mmap_fallback (size_t *s, size_t size, size_t minsize,
+			  size_t pagesize, int extra_flags)
 {
-  long int size = *s;
-
-  /* Cannot merge with old top, so add its size back in */
-  if (contiguous (av))
-    size = ALIGN_UP (size + old_size, pagesize);
+  size = ALIGN_UP (size, pagesize);
 
   /* If we are relying on mmap as backup, then use larger units */
-  if ((unsigned long) (size) < minsize)
+  if (size < minsize)
     size = minsize;
 
-  /* Don't try if size wraps around 0 */
-  if ((unsigned long) (size) <= (unsigned long) (nb))
-    return MORECORE_FAILURE;
-
   char *mbrk = (char *) (MMAP (NULL, size,
 			       mtag_mmap_flags | PROT_READ | PROT_WRITE,
 			       extra_flags));
@@ -2476,13 +2476,6 @@ sysmalloc_mmap_fallback (long int *s, INTERNAL_SIZE_T nb,
   if (extra_flags == 0)
     madvise_thp (mbrk, size);
 
-  __set_vma_name (mbrk, size, " glibc: malloc");
-
-  /* Record that we no longer have a contiguous sbrk region.  After the first
-     time mmap is used as backup, we do not ever rely on contiguous space
-     since this could incorrectly bridge regions.  */
-  set_noncontiguous (av);
-
   *s = size;
   return mbrk;
 }
@@ -2494,7 +2487,7 @@ sysmalloc (INTERNAL_SIZE_T nb, mstate av)
   INTERNAL_SIZE_T old_size;       /* its size */
   char *old_end;                  /* its end address */
 
-  long size;                      /* arg to first MORECORE or mmap call */
+  size_t size;                      /* arg to first MORECORE or mmap call */
   char *brk;                      /* return value from MORECORE */
 
   long correction;                /* arg to 2nd MORECORE call */
@@ -2660,9 +2653,9 @@ sysmalloc (INTERNAL_SIZE_T nb, mstate av)
          below even if we cannot call MORECORE.
        */
 
-      if (size > 0)
+      if ((long) size > 0)
         {
-          brk = (char *) (MORECORE (size));
+          brk = (char *) (MORECORE ((long) size));
 	  if (brk != (char *) (MORECORE_FAILURE))
 	    madvise_thp (brk, size);
           LIBC_PROBE (memory_sbrk_more, 2, brk, size);
@@ -2679,16 +2672,25 @@ sysmalloc (INTERNAL_SIZE_T nb, mstate av)
              segregated mmap region.
            */
 
+	  size_t fallback_size = nb + mp_.top_pad + MINSIZE;
 	  char *mbrk = MAP_FAILED;
 	  if (mp_.hp_pagesize > 0)
-	    mbrk = sysmalloc_mmap_fallback (&size, nb, old_size,
-					    mp_.hp_pagesize, mp_.hp_pagesize,
-					    mp_.hp_flags, av);
+	    mbrk = sysmalloc_mmap_fallback (&size, fallback_size,
+					    mp_.hp_pagesize,
+					    mp_.hp_pagesize, mp_.hp_flags);
 	  if (mbrk == MAP_FAILED)
-	    mbrk = sysmalloc_mmap_fallback (&size, nb, old_size, MMAP_AS_MORECORE_SIZE,
-					    pagesize, 0, av);
+	    mbrk = sysmalloc_mmap_fallback (&size, fallback_size,
+	                                    MMAP_AS_MORECORE_SIZE,
+	                                    pagesize, 0);
 	  if (mbrk != MAP_FAILED)
 	    {
+	      __set_vma_name (mbrk, fallback_size, " glibc: malloc");
+
+	      /* Record that we no longer have a contiguous sbrk region.  After the first
+		 time mmap is used as backup, we do not ever rely on contiguous space
+		 since this could incorrectly bridge regions.  */
+	      set_noncontiguous (av);
+
 	      /* We do not need, and cannot use, another sbrk call to find end */
 	      brk = mbrk;
 	      snd_brk = brk + size;
@@ -2977,13 +2979,12 @@ static void
 munmap_chunk (mchunkptr p)
 {
   size_t pagesize = GLRO (dl_pagesize);
-  INTERNAL_SIZE_T size = chunksize (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 = mmap_base (p);
+  size_t total_size = mmap_size (p);
   /* 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
@@ -3014,9 +3015,9 @@ mremap_chunk (mchunkptr p, size_t new_size)
 
   assert (chunk_is_mmapped (p));
 
-  uintptr_t block = (uintptr_t) p - offset;
+  uintptr_t block = mmap_base (p);
   uintptr_t mem = (uintptr_t) chunk2mem(p);
-  size_t total_size = offset + size;
+  size_t total_size = mmap_size (p);
   if (__glibc_unlikely ((block | total_size) & (pagesize - 1)) != 0
       || __glibc_unlikely (!powerof2 (mem & (pagesize - 1))))
     malloc_printerr("mremap_chunk(): invalid pointer");
-- 
2.43.0



More information about the Libc-alpha mailing list