| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163 |
- /* Test for memalign chunk reuse.
- Copyright (C) 2022-2026 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
- <https://www.gnu.org/licenses/>. */
- #include <errno.h>
- #include <malloc.h>
- #include <stdio.h>
- #include <string.h>
- #include <unistd.h>
- #include <array_length.h>
- #include <libc-pointer-arith.h>
- #include <support/check.h>
- 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 int
- do_test (void)
- {
- int i, 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. This exercises the memalign
- scanning code to find matching allocations. */
- 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. This verifies that the over-allocated parts
- that memalign releases for future allocations can be reused by
- memalign itself at least in some cases. */
- 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 <support/test-driver.c>
|