From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: loqs Date: Mon, 7 Aug 2023 21:56:26 Subject: [PATCH 1/6] Revert "aligned_alloc: conform to C17" This reverts commit d1417176a35d27ffb8da0ffb1e33154163b6eeb2. --- malloc/Makefile | 6 +-- malloc/malloc-debug.c | 9 +--- malloc/malloc.c | 26 ++-------- malloc/tst-aligned-alloc-static.c | 1 - malloc/tst-aligned-alloc.c | 80 ------------------------------- manual/memory.texi | 2 +- 6 files changed, 7 insertions(+), 117 deletions(-) delete mode 100644 malloc/tst-aligned-alloc-static.c delete mode 100644 malloc/tst-aligned-alloc.c diff --git a/malloc/Makefile b/malloc/Makefile index c1db3347d8..8dcc0ff1b1 100644 --- a/malloc/Makefile +++ b/malloc/Makefile @@ -44,13 +44,11 @@ tests := mallocbug tst-malloc tst-valloc tst-calloc tst-obstack \ tst-safe-linking \ tst-mallocalign1 \ tst-memalign-2 \ - tst-memalign-3 \ - tst-aligned-alloc + tst-memalign-3 tests-static := \ tst-interpose-static-nothread \ - tst-interpose-static-thread \ - tst-aligned-alloc-static + tst-interpose-static-thread # Test for the malloc_set_state symbol removed in glibc 2.25. ifeq ($(have-GLIBC_2.23)$(build-shared),yesyes) diff --git a/malloc/malloc-debug.c b/malloc/malloc-debug.c index f9d131d22f..12fe9bf995 100644 --- a/malloc/malloc-debug.c +++ b/malloc/malloc-debug.c @@ -299,14 +299,7 @@ __debug_memalign (size_t alignment, size_t bytes) return _debug_mid_memalign (alignment, bytes, RETURN_ADDRESS (0)); } strong_alias (__debug_memalign, memalign) -static void * -__debug_aligned_alloc (size_t alignment, size_t bytes) -{ - if (!powerof2 (alignment) || alignment == 0) - return NULL; - return _debug_mid_memalign (alignment, bytes, RETURN_ADDRESS (0)); -} -strong_alias (__debug_aligned_alloc, aligned_alloc) +strong_alias (__debug_memalign, aligned_alloc) static void * __debug_pvalloc (size_t bytes) diff --git a/malloc/malloc.c b/malloc/malloc.c index e2f1a615a4..bd4881280c 100644 --- a/malloc/malloc.c +++ b/malloc/malloc.c @@ -3535,29 +3535,6 @@ __libc_memalign (size_t alignment, size_t bytes) void *address = RETURN_ADDRESS (0); return _mid_memalign (alignment, bytes, address); } -libc_hidden_def (__libc_memalign) - -/* For ISO C17. */ -void * -weak_function -aligned_alloc (size_t alignment, size_t bytes) -{ - if (!__malloc_initialized) - ptmalloc_init (); - -/* Similar to memalign, but starting with ISO C17 the standard - requires an error for alignments that are not supported by the - implementation. Valid alignments for the current implementation - are non-negative powers of two. */ - if (!powerof2 (alignment) || alignment == 0) - { - __set_errno (EINVAL); - return 0; - } - - void *address = RETURN_ADDRESS (0); - return _mid_memalign (alignment, bytes, address); -} static void * _mid_memalign (size_t alignment, size_t bytes, void *address) @@ -3648,6 +3625,9 @@ _mid_memalign (size_t alignment, size_t bytes, void *address) ar_ptr == arena_for_chunk (mem2chunk (p))); return tag_new_usable (p); } +/* For ISO C11. */ +weak_alias (__libc_memalign, aligned_alloc) +libc_hidden_def (__libc_memalign) void * __libc_valloc (size_t bytes) diff --git a/malloc/tst-aligned-alloc-static.c b/malloc/tst-aligned-alloc-static.c deleted file mode 100644 index d504473094..0000000000 --- a/malloc/tst-aligned-alloc-static.c +++ /dev/null @@ -1 +0,0 @@ -#include "tst-aligned-alloc.c" diff --git a/malloc/tst-aligned-alloc.c b/malloc/tst-aligned-alloc.c deleted file mode 100644 index 8bd6527147..0000000000 --- a/malloc/tst-aligned-alloc.c +++ /dev/null @@ -1,80 +0,0 @@ -/* Test for C17 alignment requirements. - Copyright (C) 2023 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - . */ - -#include -#include -#include -#include -#include -#include -#include -#include - -static int -do_test (void) -{ - void *p1; - void *p2; - void *p3; - void *p4; - void *p5; - - errno = 0; - - /* The implementation supports alignments that are non-negative powers of 2. - We test 5 distinct conditions here: - - A non-negative power of 2 alignment e.g. 64. - - A degenerate zero power of 2 alignment e.g. 1. - - A non-power-of-2 alignment e.g. 65. - - A zero alignment. - - A corner case SIZE_MAX / 2 + 1 alignment. - */ - - p1 = aligned_alloc (64, 64); - - if (p1 == NULL) - FAIL_EXIT1 ("aligned_alloc(64, 64) failed"); - - p2 = aligned_alloc (1, 64); - - if (p2 == NULL) - FAIL_EXIT1 ("aligned_alloc(1, 64) failed"); - - p3 = aligned_alloc (65, 64); - - if (p3 != NULL) - FAIL_EXIT1 ("aligned_alloc(65, 64) did not fail"); - - p4 = aligned_alloc (0, 64); - - if (p4 != NULL) - FAIL_EXIT1 ("aligned_alloc(0, 64) did not fail"); - - /* This is an alignment like 0x80000000...UL */ - p5 = aligned_alloc (SIZE_MAX / 2 + 1, 64); - - if (p5 != NULL) - FAIL_EXIT1 ("aligned_alloc(SIZE_MAX/2+1, 64) did not fail"); - - free (p1); - free (p2); - return 0; -} - -#define TEST_FUNCTION do_test () -#include "../test-skeleton.c" diff --git a/manual/memory.texi b/manual/memory.texi index 5781a64f35..f29898d69b 100644 --- a/manual/memory.texi +++ b/manual/memory.texi @@ -995,7 +995,7 @@ power of two than that, use @code{aligned_alloc} or @code{posix_memalign}. @c Alias to memalign. The @code{aligned_alloc} function allocates a block of @var{size} bytes whose address is a multiple of @var{alignment}. The @var{alignment} must be a -power of two. +power of two and @var{size} must be a multiple of @var{alignment}. The @code{aligned_alloc} function returns a null pointer on error and sets @code{errno} to one of the following values: -- 2.41.0 From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: loqs Date: Mon, 7 Aug 2023 21:57:16 Subject: [PATCH 2/6] Revert "malloc: Really fix tst-memalign-3 link against threads" This reverts commit f2cabe04dc2630754e1583c56282920ea146c6d8. --- malloc/Makefile | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/malloc/Makefile b/malloc/Makefile index 8dcc0ff1b1..f920257a38 100644 --- a/malloc/Makefile +++ b/malloc/Makefile @@ -194,6 +194,7 @@ $(objpfx)tst-malloc-thread-exit-malloc-hugetlb2: $(shared-thread-library) $(objpfx)tst-malloc-thread-fail-malloc-hugetlb2: $(shared-thread-library) $(objpfx)tst-malloc-fork-deadlock-malloc-hugetlb2: $(shared-thread-library) $(objpfx)tst-malloc-stats-cancellation-malloc-hugetlb2: $(shared-thread-library) +$(objpfx)tst-memalign-3: $(shared-thread-library) # These should be removed by `make clean'. extra-objs = mcheck-init.o libmcheck.a @@ -352,8 +353,6 @@ $(objpfx)tst-mallocfork2-malloc-check: $(shared-thread-library) $(objpfx)tst-malloc_info-malloc-hugetlb1: $(shared-thread-library) $(objpfx)tst-malloc_info-malloc-hugetlb2: $(shared-thread-library) $(objpfx)tst-memalign-3: $(shared-thread-library) -$(objpfx)tst-memalign-3-malloc-hugetlb1: $(shared-thread-library) -$(objpfx)tst-memalign-3-malloc-hugetlb2: $(shared-thread-library) tst-compathooks-on-ENV = LD_PRELOAD=$(objpfx)libc_malloc_debug.so tst-compathooks-on-mcheck-ENV = LD_PRELOAD=$(objpfx)libc_malloc_debug.so -- 2.41.0 From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: loqs Date: Mon, 7 Aug 2023 21:58:00 Subject: [PATCH 3/6] Revert "malloc: Fix tst-memalign-3 link against threads" This reverts commit c999c38f6fe3626a8e58df15aae929c5348724e1. --- malloc/Makefile | 1 - 1 file changed, 1 deletion(-) diff --git a/malloc/Makefile b/malloc/Makefile index f920257a38..e26d934100 100644 --- a/malloc/Makefile +++ b/malloc/Makefile @@ -194,7 +194,6 @@ $(objpfx)tst-malloc-thread-exit-malloc-hugetlb2: $(shared-thread-library) $(objpfx)tst-malloc-thread-fail-malloc-hugetlb2: $(shared-thread-library) $(objpfx)tst-malloc-fork-deadlock-malloc-hugetlb2: $(shared-thread-library) $(objpfx)tst-malloc-stats-cancellation-malloc-hugetlb2: $(shared-thread-library) -$(objpfx)tst-memalign-3: $(shared-thread-library) # These should be removed by `make clean'. extra-objs = mcheck-init.o libmcheck.a -- 2.41.0 From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: loqs Date: Mon, 7 Aug 2023 21:58:30 Subject: [PATCH 4/6] Revert "malloc: Add missing shared thread library flags" This reverts commit 0f61cd4b9c5175c128311769df932c8d7694d6b6. --- malloc/Makefile | 1 - 1 file changed, 1 deletion(-) diff --git a/malloc/Makefile b/malloc/Makefile index e26d934100..2fd5ba50c7 100644 --- a/malloc/Makefile +++ b/malloc/Makefile @@ -351,7 +351,6 @@ $(objpfx)tst-malloc_info-malloc-check: $(shared-thread-library) $(objpfx)tst-mallocfork2-malloc-check: $(shared-thread-library) $(objpfx)tst-malloc_info-malloc-hugetlb1: $(shared-thread-library) $(objpfx)tst-malloc_info-malloc-hugetlb2: $(shared-thread-library) -$(objpfx)tst-memalign-3: $(shared-thread-library) tst-compathooks-on-ENV = LD_PRELOAD=$(objpfx)libc_malloc_debug.so tst-compathooks-on-mcheck-ENV = LD_PRELOAD=$(objpfx)libc_malloc_debug.so -- 2.41.0 From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: loqs Date: Mon, 7 Aug 2023 22:15:49 Subject: [PATCH 5/6] Revert "malloc: set NON_MAIN_ARENA flag for reclaimed memalign chunk (BZ #30101)" This reverts commit e5524ef335dc8e28d64cc376d57c219e566fcf53. Conflicts: malloc/Makefile --- malloc/Makefile | 7 +- malloc/malloc.c | 157 ++++++++++++++++++------------------ malloc/tst-memalign-2.c | 13 +-- malloc/tst-memalign-3.c | 173 ---------------------------------------- 4 files changed, 82 insertions(+), 268 deletions(-) delete mode 100644 malloc/tst-memalign-3.c diff --git a/malloc/Makefile b/malloc/Makefile index 2fd5ba50c7..6aeab66704 100644 --- a/malloc/Makefile +++ b/malloc/Makefile @@ -43,8 +43,7 @@ tests := mallocbug tst-malloc tst-valloc tst-calloc tst-obstack \ tst-tcfree1 tst-tcfree2 tst-tcfree3 \ tst-safe-linking \ tst-mallocalign1 \ - tst-memalign-2 \ - tst-memalign-3 + tst-memalign-2 tests-static := \ tst-interpose-static-nothread \ @@ -72,7 +71,7 @@ test-srcs = tst-mtrace # with MALLOC_CHECK_=3 because they expect a specific failure. tests-exclude-malloc-check = tst-malloc-check tst-malloc-usable \ tst-mxfast tst-safe-linking \ - tst-compathooks-off tst-compathooks-on tst-memalign-2 tst-memalign-3 \ + tst-compathooks-off tst-compathooks-on tst-memalign-2 \ tst-mallocfork2 \ tst-mallocfork3 \ tst-malloc-tcache-leak @@ -123,8 +122,6 @@ tests-exclude-mcheck = tst-mallocstate \ tst-malloc-usable-tunables \ tst-malloc_info \ tst-compathooks-off tst-compathooks-on \ - tst-memalign-2 \ - tst-memalign-3 \ tst-mxfast \ tst-mallocfork2 \ tst-mallocfork3 diff --git a/malloc/malloc.c b/malloc/malloc.c index bd4881280c..e3fa3e1edf 100644 --- a/malloc/malloc.c +++ b/malloc/malloc.c @@ -4981,13 +4981,13 @@ _int_realloc (mstate av, mchunkptr oldp, INTERNAL_SIZE_T oldsize, /* Returns 0 if the chunk is not and does not contain the requested aligned sub-chunk, else returns the amount of "waste" from - trimming. NB is the *chunk* byte size, not the user byte + trimming. BYTES is the *user* byte size, not the chunk byte size. */ static size_t -chunk_ok_for_memalign (mchunkptr p, size_t alignment, size_t nb) +chunk_ok_for_memalign (mchunkptr p, size_t alignment, size_t bytes) { void *m = chunk2mem (p); - INTERNAL_SIZE_T size = chunksize (p); + INTERNAL_SIZE_T size = memsize (p); void *aligned_m = m; if (__glibc_unlikely (misaligned_chunk (p))) @@ -5004,12 +5004,12 @@ chunk_ok_for_memalign (mchunkptr p, size_t alignment, size_t nb) /* If it's a perfect fit, it's an exception to the return value rule (we would return zero waste, which looks like "not usable"), so handle it here by returning a small non-zero value instead. */ - if (size == nb && front_extra == 0) + if (size == bytes && front_extra == 0) return 1; /* If the block we need fits in the chunk, calculate total waste. */ - if (size > nb + front_extra) - return size - nb; + if (size > bytes + front_extra) + return size - bytes; /* Can't use this chunk. */ return 0; @@ -5055,98 +5055,95 @@ _int_memalign (mstate av, size_t alignment, size_t bytes) and unlikely to meet our alignment requirements. We have not done any experimentation with searching for aligned fastbins. */ - if (av != NULL) - { - int first_bin_index; - int first_largebin_index; - int last_bin_index; - - if (in_smallbin_range (nb)) - first_bin_index = smallbin_index (nb); - else - first_bin_index = largebin_index (nb); - - if (in_smallbin_range (nb * 2)) - last_bin_index = smallbin_index (nb * 2); - else - last_bin_index = largebin_index (nb * 2); + int first_bin_index; + int first_largebin_index; + int last_bin_index; - first_largebin_index = largebin_index (MIN_LARGE_SIZE); + if (in_smallbin_range (nb)) + first_bin_index = smallbin_index (nb); + else + first_bin_index = largebin_index (nb); - int victim_index; /* its bin index */ + if (in_smallbin_range (nb * 2)) + last_bin_index = smallbin_index (nb * 2); + else + last_bin_index = largebin_index (nb * 2); - for (victim_index = first_bin_index; - victim_index < last_bin_index; - victim_index ++) - { - victim = NULL; + first_largebin_index = largebin_index (MIN_LARGE_SIZE); - if (victim_index < first_largebin_index) - { - /* Check small bins. Small bin chunks are doubly-linked despite - being the same size. */ + int victim_index; /* its bin index */ - mchunkptr fwd; /* misc temp for linking */ - mchunkptr bck; /* misc temp for linking */ + for (victim_index = first_bin_index; + victim_index < last_bin_index; + victim_index ++) + { + victim = NULL; - bck = bin_at (av, victim_index); - fwd = bck->fd; - while (fwd != bck) - { - if (chunk_ok_for_memalign (fwd, alignment, nb) > 0) - { - victim = fwd; + if (victim_index < first_largebin_index) + { + /* Check small bins. Small bin chunks are doubly-linked despite + being the same size. */ - /* Unlink it */ - victim->fd->bk = victim->bk; - victim->bk->fd = victim->fd; - break; - } + mchunkptr fwd; /* misc temp for linking */ + mchunkptr bck; /* misc temp for linking */ - fwd = fwd->fd; - } - } - else + bck = bin_at (av, victim_index); + fwd = bck->fd; + while (fwd != bck) + { + if (chunk_ok_for_memalign (fwd, alignment, bytes) > 0) { - /* Check large bins. */ - mchunkptr fwd; /* misc temp for linking */ - mchunkptr bck; /* misc temp for linking */ - mchunkptr best = NULL; - size_t best_size = 0; + victim = fwd; - bck = bin_at (av, victim_index); - fwd = bck->fd; + /* Unlink it */ + victim->fd->bk = victim->bk; + victim->bk->fd = victim->fd; + break; + } - while (fwd != bck) - { - int extra; + fwd = fwd->fd; + } + } + else + { + /* Check large bins. */ + mchunkptr fwd; /* misc temp for linking */ + mchunkptr bck; /* misc temp for linking */ + mchunkptr best = NULL; + size_t best_size = 0; - if (chunksize (fwd) < nb) - break; - extra = chunk_ok_for_memalign (fwd, alignment, nb); - if (extra > 0 - && (extra <= best_size || best == NULL)) - { - best = fwd; - best_size = extra; - } + bck = bin_at (av, victim_index); + fwd = bck->fd; - fwd = fwd->fd; - } - victim = best; + while (fwd != bck) + { + int extra; - if (victim != NULL) - { - unlink_chunk (av, victim); - break; - } + if (chunksize (fwd) < nb) + break; + extra = chunk_ok_for_memalign (fwd, alignment, bytes); + if (extra > 0 + && (extra <= best_size || best == NULL)) + { + best = fwd; + best_size = extra; } - if (victim != NULL) - break; + fwd = fwd->fd; + } + victim = best; + + if (victim != NULL) + { + unlink_chunk (av, victim); + break; } } + if (victim != NULL) + break; + } + /* Strategy: find a spot within that chunk that meets the alignment request, and then possibly free the leading and trailing space. This strategy is incredibly costly and can lead to external @@ -5157,8 +5154,6 @@ _int_memalign (mstate av, size_t alignment, size_t bytes) p = victim; m = chunk2mem (p); set_inuse (p); - if (av != &main_arena) - set_non_main_arena (p); } else { diff --git a/malloc/tst-memalign-2.c b/malloc/tst-memalign-2.c index f229283dbf..4996578e9f 100644 --- a/malloc/tst-memalign-2.c +++ b/malloc/tst-memalign-2.c @@ -33,10 +33,9 @@ typedef struct TestCase { } TestCase; static TestCase tcache_allocs[] = { - { 24, 32, NULL, NULL }, - { 24, 64, NULL, NULL }, - { 128, 128, NULL, NULL }, - { 500, 128, NULL, NULL } + { 24, 8, NULL, NULL }, + { 24, 16, NULL, NULL }, + { 128, 32, NULL, NULL } }; #define TN array_length (tcache_allocs) @@ -71,15 +70,11 @@ do_test (void) for (i = 0; i < TN; ++ i) { - size_t sz2; - tcache_allocs[i].ptr1 = memalign (tcache_allocs[i].alignment, tcache_allocs[i].size); CHECK (tcache_allocs[i].ptr1, tcache_allocs[i].alignment); - sz2 = malloc_usable_size (tcache_allocs[i].ptr1); free (tcache_allocs[i].ptr1); - /* This should return the same chunk as was just free'd. */ - tcache_allocs[i].ptr2 = memalign (tcache_allocs[i].alignment, sz2); + tcache_allocs[i].ptr2 = memalign (tcache_allocs[i].alignment, tcache_allocs[i].size); CHECK (tcache_allocs[i].ptr2, tcache_allocs[i].alignment); free (tcache_allocs[i].ptr2); diff --git a/malloc/tst-memalign-3.c b/malloc/tst-memalign-3.c deleted file mode 100644 index ab90d6ca9b..0000000000 --- a/malloc/tst-memalign-3.c +++ /dev/null @@ -1,173 +0,0 @@ -/* Test for memalign chunk reuse. - Copyright (C) 2022 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - . */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -typedef struct TestCase { - size_t size; - size_t alignment; - void *ptr1; - void *ptr2; -} TestCase; - -static TestCase tcache_allocs[] = { - { 24, 32, NULL, NULL }, - { 24, 64, NULL, NULL }, - { 128, 128, NULL, NULL }, - { 500, 128, NULL, NULL } -}; -#define TN array_length (tcache_allocs) - -static TestCase large_allocs[] = { - { 23450, 64, NULL, NULL }, - { 23450, 64, NULL, NULL }, - { 23550, 64, NULL, NULL }, - { 23550, 64, NULL, NULL }, - { 23650, 64, NULL, NULL }, - { 23650, 64, NULL, NULL }, - { 33650, 64, NULL, NULL }, - { 33650, 64, NULL, NULL } -}; -#define LN array_length (large_allocs) - -void *p; - -/* Sanity checks, ancillary to the actual test. */ -#define CHECK(p,a) \ - if (p == NULL || !PTR_IS_ALIGNED (p, a)) \ - FAIL_EXIT1 ("NULL or misaligned memory detected.\n"); - -static void * -mem_test (void *closure) -{ - int i; - int j; - int count; - void *ptr[10]; - void *p; - - /* TCache test. */ - for (i = 0; i < TN; ++ i) - { - size_t sz2; - - tcache_allocs[i].ptr1 = memalign (tcache_allocs[i].alignment, tcache_allocs[i].size); - CHECK (tcache_allocs[i].ptr1, tcache_allocs[i].alignment); - sz2 = malloc_usable_size (tcache_allocs[i].ptr1); - free (tcache_allocs[i].ptr1); - - /* This should return the same chunk as was just free'd. */ - tcache_allocs[i].ptr2 = memalign (tcache_allocs[i].alignment, sz2); - CHECK (tcache_allocs[i].ptr2, tcache_allocs[i].alignment); - free (tcache_allocs[i].ptr2); - - TEST_VERIFY (tcache_allocs[i].ptr1 == tcache_allocs[i].ptr2); - } - - /* Test for non-head tcache hits. */ - for (i = 0; i < array_length (ptr); ++ i) - { - if (i == 4) - { - ptr[i] = memalign (64, 256); - CHECK (ptr[i], 64); - } - else - { - ptr[i] = malloc (256); - CHECK (ptr[i], 4); - } - } - for (i = 0; i < array_length (ptr); ++ i) - free (ptr[i]); - - p = memalign (64, 256); - CHECK (p, 64); - - count = 0; - for (i = 0; i < 10; ++ i) - if (ptr[i] == p) - ++ count; - free (p); - TEST_VERIFY (count > 0); - - /* Large bins test. */ - - for (i = 0; i < LN; ++ i) - { - large_allocs[i].ptr1 = memalign (large_allocs[i].alignment, large_allocs[i].size); - CHECK (large_allocs[i].ptr1, large_allocs[i].alignment); - /* Keep chunks from combining by fragmenting the heap. */ - p = malloc (512); - CHECK (p, 4); - } - - for (i = 0; i < LN; ++ i) - free (large_allocs[i].ptr1); - - /* Force the unsorted bins to be scanned and moved to small/large - bins. */ - p = malloc (60000); - - for (i = 0; i < LN; ++ i) - { - large_allocs[i].ptr2 = memalign (large_allocs[i].alignment, large_allocs[i].size); - CHECK (large_allocs[i].ptr2, large_allocs[i].alignment); - } - - count = 0; - for (i = 0; i < LN; ++ i) - { - int ok = 0; - for (j = 0; j < LN; ++ j) - if (large_allocs[i].ptr1 == large_allocs[j].ptr2) - ok = 1; - if (ok == 1) - count ++; - } - - /* The allocation algorithm is complicated outside of the memalign - logic, so just make sure it's working for most of the - allocations. This avoids possible boundary conditions with - empty/full heaps. */ - TEST_VERIFY (count > LN / 2); - - return 0; -} - -static int -do_test (void) -{ - pthread_t p; - - p = xpthread_create (NULL, mem_test, NULL); - xpthread_join (p); - return 0; -} - -#include -- 2.41.0 From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: loqs Date: Mon, 7 Aug 2023 22:20:35 Subject: [PATCH 6/6] Revert "memalign: Support scanning for aligned chunks." This reverts commit 24cdd6c71debfd10a9f7cb217fe2a2c4c486ed6f. Conflicts: malloc/Makefile --- malloc/Makefile | 3 +- malloc/malloc.c | 260 +++++----------------------------------- malloc/tst-memalign-2.c | 155 ------------------------ 3 files changed, 28 insertions(+), 390 deletions(-) delete mode 100644 malloc/tst-memalign-2.c diff --git a/malloc/Makefile b/malloc/Makefile index 6aeab66704..84dfa94d0f 100644 --- a/malloc/Makefile +++ b/malloc/Makefile @@ -43,7 +43,6 @@ tests := mallocbug tst-malloc tst-valloc tst-calloc tst-obstack \ tst-tcfree1 tst-tcfree2 tst-tcfree3 \ tst-safe-linking \ tst-mallocalign1 \ - tst-memalign-2 tests-static := \ tst-interpose-static-nothread \ @@ -71,7 +70,7 @@ test-srcs = tst-mtrace # with MALLOC_CHECK_=3 because they expect a specific failure. tests-exclude-malloc-check = tst-malloc-check tst-malloc-usable \ tst-mxfast tst-safe-linking \ - tst-compathooks-off tst-compathooks-on tst-memalign-2 \ + tst-compathooks-off tst-compathooks-on \ tst-mallocfork2 \ tst-mallocfork3 \ tst-malloc-tcache-leak diff --git a/malloc/malloc.c b/malloc/malloc.c index e3fa3e1edf..44c3e6c4db 100644 --- a/malloc/malloc.c +++ b/malloc/malloc.c @@ -3156,44 +3156,19 @@ tcache_put (mchunkptr chunk, size_t tc_idx) } /* Caller must ensure that we know tc_idx is valid and there's - available chunks to remove. Removes chunk from the middle of the - list. */ + available chunks to remove. */ static __always_inline void * -tcache_get_n (size_t tc_idx, tcache_entry **ep) +tcache_get (size_t tc_idx) { - tcache_entry *e; - if (ep == &(tcache->entries[tc_idx])) - e = *ep; - else - e = REVEAL_PTR (*ep); - + tcache_entry *e = tcache->entries[tc_idx]; if (__glibc_unlikely (!aligned_OK (e))) malloc_printerr ("malloc(): unaligned tcache chunk detected"); - - if (ep == &(tcache->entries[tc_idx])) - *ep = REVEAL_PTR (e->next); - else - *ep = PROTECT_PTR (ep, REVEAL_PTR (e->next)); - + tcache->entries[tc_idx] = REVEAL_PTR (e->next); --(tcache->counts[tc_idx]); e->key = 0; return (void *) e; } -/* Like the above, but removes from the head of the list. */ -static __always_inline void * -tcache_get (size_t tc_idx) -{ - return tcache_get_n (tc_idx, & tcache->entries[tc_idx]); -} - -/* Iterates through the tcache linked list. */ -static __always_inline tcache_entry * -tcache_next (tcache_entry *e) -{ - return (tcache_entry *) REVEAL_PTR (e->next); -} - static void tcache_thread_shutdown (void) { @@ -3302,7 +3277,7 @@ __libc_malloc (size_t bytes) DIAG_PUSH_NEEDS_COMMENT; if (tc_idx < mp_.tcache_bins - && tcache != NULL + && tcache && tcache->counts[tc_idx] > 0) { victim = tcache_get (tc_idx); @@ -3568,38 +3543,6 @@ _mid_memalign (size_t alignment, size_t bytes, void *address) alignment = a; } -#if USE_TCACHE - { - size_t tbytes; - tbytes = checked_request2size (bytes); - if (tbytes == 0) - { - __set_errno (ENOMEM); - return NULL; - } - size_t tc_idx = csize2tidx (tbytes); - - if (tc_idx < mp_.tcache_bins - && tcache != NULL - && tcache->counts[tc_idx] > 0) - { - /* The tcache itself isn't encoded, but the chain is. */ - tcache_entry **tep = & tcache->entries[tc_idx]; - tcache_entry *te = *tep; - while (te != NULL && !PTR_IS_ALIGNED (te, alignment)) - { - tep = & (te->next); - te = tcache_next (te); - } - if (te != NULL) - { - void *victim = tcache_get_n (tc_idx, tep); - return tag_new_usable (victim); - } - } - } -#endif - if (SINGLE_THREAD_P) { p = _int_memalign (&main_arena, alignment, bytes); @@ -3905,7 +3848,7 @@ _int_malloc (mstate av, size_t bytes) /* While we're here, if we see other chunks of the same size, stash them in the tcache. */ size_t tc_idx = csize2tidx (nb); - if (tcache != NULL && tc_idx < mp_.tcache_bins) + if (tcache && tc_idx < mp_.tcache_bins) { mchunkptr tc_victim; @@ -3963,7 +3906,7 @@ _int_malloc (mstate av, size_t bytes) /* While we're here, if we see other chunks of the same size, stash them in the tcache. */ size_t tc_idx = csize2tidx (nb); - if (tcache != NULL && tc_idx < mp_.tcache_bins) + if (tcache && tc_idx < mp_.tcache_bins) { mchunkptr tc_victim; @@ -4025,7 +3968,7 @@ _int_malloc (mstate av, size_t bytes) #if USE_TCACHE INTERNAL_SIZE_T tcache_nb = 0; size_t tc_idx = csize2tidx (nb); - if (tcache != NULL && tc_idx < mp_.tcache_bins) + if (tcache && tc_idx < mp_.tcache_bins) tcache_nb = nb; int return_cached = 0; @@ -4105,7 +4048,7 @@ _int_malloc (mstate av, size_t bytes) #if USE_TCACHE /* Fill cache first, return to user only if cache fills. We may return one of these chunks later. */ - if (tcache_nb > 0 + if (tcache_nb && tcache->counts[tc_idx] < mp_.tcache_count) { tcache_put (victim, tc_idx); @@ -4979,43 +4922,6 @@ _int_realloc (mstate av, mchunkptr oldp, INTERNAL_SIZE_T oldsize, ------------------------------ memalign ------------------------------ */ -/* Returns 0 if the chunk is not and does not contain the requested - aligned sub-chunk, else returns the amount of "waste" from - trimming. BYTES is the *user* byte size, not the chunk byte - size. */ -static size_t -chunk_ok_for_memalign (mchunkptr p, size_t alignment, size_t bytes) -{ - void *m = chunk2mem (p); - INTERNAL_SIZE_T size = memsize (p); - void *aligned_m = m; - - if (__glibc_unlikely (misaligned_chunk (p))) - malloc_printerr ("_int_memalign(): unaligned chunk detected"); - - aligned_m = PTR_ALIGN_UP (m, alignment); - - INTERNAL_SIZE_T front_extra = (intptr_t) aligned_m - (intptr_t) m; - - /* We can't trim off the front as it's too small. */ - if (front_extra > 0 && front_extra < MINSIZE) - return 0; - - /* If it's a perfect fit, it's an exception to the return value rule - (we would return zero waste, which looks like "not usable"), so - handle it here by returning a small non-zero value instead. */ - if (size == bytes && front_extra == 0) - return 1; - - /* If the block we need fits in the chunk, calculate total waste. */ - if (size > bytes + front_extra) - return size - bytes; - - /* Can't use this chunk. */ - return 0; -} - -/* BYTES is user requested bytes, not requested chunksize bytes. */ static void * _int_memalign (mstate av, size_t alignment, size_t bytes) { @@ -5029,7 +4935,8 @@ _int_memalign (mstate av, size_t alignment, size_t bytes) mchunkptr remainder; /* spare room at end to split off */ unsigned long remainder_size; /* its size */ INTERNAL_SIZE_T size; - mchunkptr victim; + + nb = checked_request2size (bytes); if (nb == 0) @@ -5038,142 +4945,29 @@ _int_memalign (mstate av, size_t alignment, size_t bytes) return NULL; } - /* We can't check tcache here because we hold the arena lock, which - tcache doesn't expect. We expect it has been checked - earlier. */ - - /* Strategy: search the bins looking for an existing block that - meets our needs. We scan a range of bins from "exact size" to - "just under 2x", spanning the small/large barrier if needed. If - we don't find anything in those bins, the common malloc code will - scan starting at 2x. */ - - /* This will be set if we found a candidate chunk. */ - victim = NULL; - - /* Fast bins are singly-linked, hard to remove a chunk from the middle - and unlikely to meet our alignment requirements. We have not done - any experimentation with searching for aligned fastbins. */ - - int first_bin_index; - int first_largebin_index; - int last_bin_index; - - if (in_smallbin_range (nb)) - first_bin_index = smallbin_index (nb); - else - first_bin_index = largebin_index (nb); - - if (in_smallbin_range (nb * 2)) - last_bin_index = smallbin_index (nb * 2); - else - last_bin_index = largebin_index (nb * 2); - - first_largebin_index = largebin_index (MIN_LARGE_SIZE); - - int victim_index; /* its bin index */ - - for (victim_index = first_bin_index; - victim_index < last_bin_index; - victim_index ++) - { - victim = NULL; - - if (victim_index < first_largebin_index) - { - /* Check small bins. Small bin chunks are doubly-linked despite - being the same size. */ - - mchunkptr fwd; /* misc temp for linking */ - mchunkptr bck; /* misc temp for linking */ - - bck = bin_at (av, victim_index); - fwd = bck->fd; - while (fwd != bck) - { - if (chunk_ok_for_memalign (fwd, alignment, bytes) > 0) - { - victim = fwd; - - /* Unlink it */ - victim->fd->bk = victim->bk; - victim->bk->fd = victim->fd; - break; - } - - fwd = fwd->fd; - } - } - else - { - /* Check large bins. */ - mchunkptr fwd; /* misc temp for linking */ - mchunkptr bck; /* misc temp for linking */ - mchunkptr best = NULL; - size_t best_size = 0; - - bck = bin_at (av, victim_index); - fwd = bck->fd; - - while (fwd != bck) - { - int extra; - - if (chunksize (fwd) < nb) - break; - extra = chunk_ok_for_memalign (fwd, alignment, bytes); - if (extra > 0 - && (extra <= best_size || best == NULL)) - { - best = fwd; - best_size = extra; - } - - fwd = fwd->fd; - } - victim = best; - - if (victim != NULL) - { - unlink_chunk (av, victim); - break; - } - } - - if (victim != NULL) - break; - } - - /* Strategy: find a spot within that chunk that meets the alignment + /* + Strategy: find a spot within that chunk that meets the alignment request, and then possibly free the leading and trailing space. - This strategy is incredibly costly and can lead to external - fragmentation if header and footer chunks are unused. */ + */ - if (victim != NULL) - { - p = victim; - m = chunk2mem (p); - set_inuse (p); - } - else - { - /* Call malloc with worst case padding to hit alignment. */ + /* Call malloc with worst case padding to hit alignment. */ - m = (char *) (_int_malloc (av, nb + alignment + MINSIZE)); + m = (char *) (_int_malloc (av, nb + alignment + MINSIZE)); - if (m == 0) - return 0; /* propagate failure */ + if (m == 0) + return 0; /* propagate failure */ - p = mem2chunk (m); - } + p = mem2chunk (m); if ((((unsigned long) (m)) % alignment) != 0) /* misaligned */ - { - /* Find an aligned spot inside chunk. Since we need to give back - leading space in a chunk of at least MINSIZE, if the first - calculation places us at a spot with less than MINSIZE leader, - we can move to the next aligned spot -- we've allocated enough - total room so that this is always possible. */ + + { /* + Find an aligned spot inside chunk. Since we need to give back + leading space in a chunk of at least MINSIZE, if the first + calculation places us at a spot with less than MINSIZE leader, + we can move to the next aligned spot -- we've allocated enough + total room so that this is always possible. + */ brk = (char *) mem2chunk (((unsigned long) (m + alignment - 1)) & - ((signed long) alignment)); if ((unsigned long) (brk - (char *) (p)) < MINSIZE) diff --git a/malloc/tst-memalign-2.c b/malloc/tst-memalign-2.c deleted file mode 100644 index 4996578e9f..0000000000 --- a/malloc/tst-memalign-2.c +++ /dev/null @@ -1,155 +0,0 @@ -/* Test for memalign chunk reuse. - Copyright (C) 2022 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - . */ - -#include -#include -#include -#include -#include -#include -#include -#include - -typedef struct TestCase { - size_t size; - size_t alignment; - void *ptr1; - void *ptr2; -} TestCase; - -static TestCase tcache_allocs[] = { - { 24, 8, NULL, NULL }, - { 24, 16, NULL, NULL }, - { 128, 32, NULL, NULL } -}; -#define TN array_length (tcache_allocs) - -static TestCase large_allocs[] = { - { 23450, 64, NULL, NULL }, - { 23450, 64, NULL, NULL }, - { 23550, 64, NULL, NULL }, - { 23550, 64, NULL, NULL }, - { 23650, 64, NULL, NULL }, - { 23650, 64, NULL, NULL }, - { 33650, 64, NULL, NULL }, - { 33650, 64, NULL, NULL } -}; -#define LN array_length (large_allocs) - -void *p; - -/* Sanity checks, ancillary to the actual test. */ -#define CHECK(p,a) \ - if (p == NULL || !PTR_IS_ALIGNED (p, a)) \ - FAIL_EXIT1 ("NULL or misaligned memory detected.\n"); - -static int -do_test (void) -{ - int i, j; - int count; - void *ptr[10]; - void *p; - - /* TCache test. */ - - for (i = 0; i < TN; ++ i) - { - tcache_allocs[i].ptr1 = memalign (tcache_allocs[i].alignment, tcache_allocs[i].size); - CHECK (tcache_allocs[i].ptr1, tcache_allocs[i].alignment); - free (tcache_allocs[i].ptr1); - /* This should return the same chunk as was just free'd. */ - tcache_allocs[i].ptr2 = memalign (tcache_allocs[i].alignment, tcache_allocs[i].size); - CHECK (tcache_allocs[i].ptr2, tcache_allocs[i].alignment); - free (tcache_allocs[i].ptr2); - - TEST_VERIFY (tcache_allocs[i].ptr1 == tcache_allocs[i].ptr2); - } - - /* Test for non-head tcache hits. */ - for (i = 0; i < array_length (ptr); ++ i) - { - if (i == 4) - { - ptr[i] = memalign (64, 256); - CHECK (ptr[i], 64); - } - else - { - ptr[i] = malloc (256); - CHECK (ptr[i], 4); - } - } - for (i = 0; i < array_length (ptr); ++ i) - free (ptr[i]); - - p = memalign (64, 256); - CHECK (p, 64); - - count = 0; - for (i = 0; i < 10; ++ i) - if (ptr[i] == p) - ++ count; - free (p); - TEST_VERIFY (count > 0); - - /* Large bins test. */ - - for (i = 0; i < LN; ++ i) - { - large_allocs[i].ptr1 = memalign (large_allocs[i].alignment, large_allocs[i].size); - CHECK (large_allocs[i].ptr1, large_allocs[i].alignment); - /* Keep chunks from combining by fragmenting the heap. */ - p = malloc (512); - CHECK (p, 4); - } - - for (i = 0; i < LN; ++ i) - free (large_allocs[i].ptr1); - - /* Force the unsorted bins to be scanned and moved to small/large - bins. */ - p = malloc (60000); - - for (i = 0; i < LN; ++ i) - { - large_allocs[i].ptr2 = memalign (large_allocs[i].alignment, large_allocs[i].size); - CHECK (large_allocs[i].ptr2, large_allocs[i].alignment); - } - - count = 0; - for (i = 0; i < LN; ++ i) - { - int ok = 0; - for (j = 0; j < LN; ++ j) - if (large_allocs[i].ptr1 == large_allocs[j].ptr2) - ok = 1; - if (ok == 1) - count ++; - } - - /* The allocation algorithm is complicated outside of the memalign - logic, so just make sure it's working for most of the - allocations. This avoids possible boundary conditions with - empty/full heaps. */ - TEST_VERIFY (count > LN / 2); - - return 0; -} - -#include -- 2.41.0