mirror of
https://sourceware.org/git/glibc.git
synced 2024-11-25 06:20:06 +00:00
0dc7fc1cf0
On the test workload (mpv --cache=yes with VP9 video decoding), the
bin scanning has a very poor success rate (less than 2%). The tcache
scanning has about 50% success rate, so keep that.
Update comments in malloc/tst-memalign-2 to indicate the purpose
of the tests. Even with the scanning removed, the additional
merging opportunities since commit 542b110585
("malloc: Enable merging of remainders in memalign (bug 30723)")
are sufficient to pass the existing large bins test.
Remove leftover variables from _int_free from refactoring in the
same commit.
Reviewed-by: DJ Delorie <dj@redhat.com>
164 lines
4.3 KiB
C
164 lines
4.3 KiB
C
/* 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
|
|
<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>
|