[PATCH] malloc: Simplify _int_free_chunk
Wilco Dijkstra
Wilco.Dijkstra@arm.com
Wed Apr 1 20:12:21 GMT 2026
Simplify _int_free_chunk() and always lock if needed. Use _int_free_merge_chunk()
for cases that assume the arena has been locked instead. Move the errno save/
restore to _int_free_maybe_trim().
Passes regress, OK for commit?
---
diff --git a/malloc/malloc-check.c b/malloc/malloc-check.c
index 49b623df12ffa7afe376b73b2ad222d357dc6612..d85986b23d1bb0beb5ccc29d380ca96daf8ef41a 100644
--- a/malloc/malloc-check.c
+++ b/malloc/malloc-check.c
@@ -233,10 +233,10 @@ free_check (void *mem)
}
else
{
+ __libc_lock_unlock (main_arena.mutex);
/* Mark the chunk as belonging to the library again. */
(void)tag_region (chunk2mem (p), memsize (p));
- _int_free_chunk (&main_arena, p, chunksize (p), 1);
- __libc_lock_unlock (main_arena.mutex);
+ _int_free_chunk (&main_arena, p, chunksize (p));
}
__set_errno (err);
}
diff --git a/malloc/malloc.c b/malloc/malloc.c
index 6a888b0eb7de53ae7b814275e86d2bd2f06b5e53..af2a902320b2f671524ba826fe828ee65bfa9cda 100644
--- a/malloc/malloc.c
+++ b/malloc/malloc.c
@@ -1024,7 +1024,7 @@ typedef struct malloc_chunk* mchunkptr;
/* Internal routines. */
static void* _int_malloc(mstate, size_t);
-static void _int_free_chunk (mstate, mchunkptr, INTERNAL_SIZE_T, int);
+static void _int_free_chunk (mstate, mchunkptr, INTERNAL_SIZE_T);
static void _int_free_merge_chunk (mstate, mchunkptr, INTERNAL_SIZE_T);
static INTERNAL_SIZE_T _int_free_create_chunk (mstate,
mchunkptr, INTERNAL_SIZE_T,
@@ -2403,7 +2403,7 @@ sysmalloc (INTERNAL_SIZE_T nb, mstate av)
CHUNK_HDR_SZ | PREV_INUSE);
set_foot (chunk_at_offset (old_top, old_size), CHUNK_HDR_SZ);
set_head (old_top, old_size | PREV_INUSE | NON_MAIN_ARENA);
- _int_free_chunk (av, old_top, chunksize (old_top), 1);
+ _int_free_merge_chunk (av, old_top, chunksize (old_top));
}
else
{
@@ -2674,7 +2674,7 @@ sysmalloc (INTERNAL_SIZE_T nb, mstate av)
/* If possible, release the rest. */
if (old_size >= MINSIZE)
{
- _int_free_chunk (av, old_top, chunksize (old_top), 1);
+ _int_free_merge_chunk (av, old_top, chunksize (old_top));
}
}
}
@@ -3171,12 +3171,12 @@ tcache_thread_shutdown (void)
tcache_tmp->entries[i] = REVEAL_PTR (e->next);
e->key = 0;
p = mem2chunk (e);
- _int_free_chunk (arena_for_chunk (p), p, chunksize (p), 0);
+ _int_free_chunk (arena_for_chunk (p), p, chunksize (p));
}
}
p = mem2chunk (tcache_tmp);
- _int_free_chunk (arena_for_chunk (p), p, chunksize (p), 0);
+ _int_free_chunk (arena_for_chunk (p), p, chunksize (p));
}
/* Initialize tcache. In the rare case there isn't any memory available,
@@ -3350,7 +3350,7 @@ __libc_free (void *mem)
size - MINSIZE)))
return malloc_printerr_tail ("free(): invalid size");
- _int_free_chunk (arena_for_chunk (p), p, size, 0);
+ _int_free_chunk (arena_for_chunk (p), p, size);
}
libc_hidden_def (__libc_free)
@@ -3472,7 +3472,7 @@ __libc_realloc (void *oldmem, size_t bytes)
size_t sz = memsize (oldp);
memcpy (newp, oldmem, sz);
(void) tag_region (chunk2mem (oldp), sz);
- _int_free_chunk (ar_ptr, oldp, chunksize (oldp), 0);
+ _int_free_chunk (ar_ptr, oldp, chunksize (oldp));
}
}
@@ -4253,11 +4253,10 @@ _int_malloc (mstate av, size_t bytes)
------------------------------ free ------------------------------
*/
-/* Free chunk P of SIZE bytes to the arena. HAVE_LOCK indicates where
- the arena for P has already been locked. Caller must ensure chunk
- and size are valid. */
+/* Free chunk P of SIZE bytes to the arena AV (which is not locked).
+ Caller must ensure chunk and size are valid. */
static void
-_int_free_chunk (mstate av, mchunkptr p, INTERNAL_SIZE_T size, int have_lock)
+_int_free_chunk (mstate av, mchunkptr p, INTERNAL_SIZE_T size)
{
/*
Consolidate other non-mmapped chunks as they arrive.
@@ -4265,22 +4264,14 @@ _int_free_chunk (mstate av, mchunkptr p, INTERNAL_SIZE_T size, int have_lock)
if (!chunk_is_mmapped(p)) {
- /* Preserve errno in case block merging results in munmap. */
- int err = errno;
-
- /* If we're single-threaded, don't lock the arena. */
if (SINGLE_THREAD_P)
- have_lock = true;
-
- if (!have_lock)
- __libc_lock_lock (av->mutex);
-
- _int_free_merge_chunk (av, p, size);
-
- if (!have_lock)
- __libc_lock_unlock (av->mutex);
-
- __set_errno (err);
+ _int_free_merge_chunk (av, p, size);
+ else
+ {
+ __libc_lock_lock (av->mutex);
+ _int_free_merge_chunk (av, p, size);
+ __libc_lock_unlock (av->mutex);
+ }
}
/*
If the chunk was allocated via mmap, release via munmap().
@@ -4309,8 +4300,8 @@ _int_free_chunk (mstate av, mchunkptr p, INTERNAL_SIZE_T size, int have_lock)
}
}
-/* Try to merge chunk P of SIZE bytes with its neighbors. Put the
- resulting chunk on the appropriate bin list. P must not be on a
+/* Try to merge chunk P of SIZE bytes from locked arena AV with its neighbors.
+ Put the resulting chunk on the appropriate bin list. P must not be on a
bin list yet, and it can be in use. */
static void
_int_free_merge_chunk (mstate av, mchunkptr p, INTERNAL_SIZE_T size)
@@ -4440,6 +4431,9 @@ _int_free_maybe_trim (mstate av, INTERNAL_SIZE_T size)
if ATTEMPT_TRIMMING_THRESHOLD is reached. */
if (size >= ATTEMPT_TRIMMING_THRESHOLD)
{
+ /* Preserve errno. */
+ int err = errno;
+
if (av == &main_arena)
{
#ifndef MORECORE_CANNOT_TRIM
@@ -4456,6 +4450,8 @@ _int_free_maybe_trim (mstate av, INTERNAL_SIZE_T size)
assert (heap->ar_ptr == av);
heap_trim (heap, mp_.top_pad);
}
+
+ __set_errno (err);
}
}
@@ -4549,7 +4545,7 @@ _int_realloc (mstate av, mchunkptr oldp, INTERNAL_SIZE_T oldsize,
(void) tag_region (oldmem, sz);
newmem = tag_new_usable (newmem);
memcpy (newmem, oldmem, sz);
- _int_free_chunk (av, oldp, chunksize (oldp), 1);
+ _int_free_merge_chunk (av, oldp, chunksize (oldp));
check_inuse_chunk (av, newp);
return newmem;
}
@@ -4577,7 +4573,7 @@ _int_realloc (mstate av, mchunkptr oldp, INTERNAL_SIZE_T oldsize,
(av != &main_arena ? NON_MAIN_ARENA : 0));
/* Mark remainder as inuse so free() won't complain */
set_inuse_bit_at_offset (remainder, remainder_size);
- _int_free_chunk (av, remainder, chunksize (remainder), 1);
+ _int_free_merge_chunk (av, remainder, chunksize (remainder));
}
check_inuse_chunk (av, newp);
More information about the Libc-alpha
mailing list