Large alloc fix (#178)
* Improved malloc style tests Added comprehensive testing of realloc, and other minor improvements to reporting errors. * Fix realloc resizing for large sizeclasses. The rounding by sizeclass was incorrect for large allocation. This fixes that. * Ensure alloc_size is committed There is an awkward interaction between alloc_size and committing only what is requested. If the user assumes everything up to alloc_size is available, then we need to either store the more precise size for alloc_size to return or commit the whole 2^n range, so that alloc_size stays simple. This changes to just make the whole range committed. In the future, we might want to store a more precise size, so that the allocation can be sized more precisely. * Reduce size of objects.
This commit is contained in:
committed by
GitHub
parent
79ca9bdd9d
commit
c899ee7ab2
@@ -366,8 +366,7 @@ namespace snmalloc
|
||||
p = memory_provider.template reserve<false>(large_class);
|
||||
if (p == nullptr)
|
||||
return nullptr;
|
||||
memory_provider.template notify_using<zero_mem>(
|
||||
p, bits::align_up(size, OS_PAGE_SIZE));
|
||||
memory_provider.template notify_using<zero_mem>(p, rsize);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -390,8 +389,7 @@ namespace snmalloc
|
||||
// Passing zero_mem ensures the PAL provides zeroed pages if
|
||||
// required.
|
||||
memory_provider.template notify_using<zero_mem>(
|
||||
pointer_offset(p, OS_PAGE_SIZE),
|
||||
bits::align_up(size, OS_PAGE_SIZE) - OS_PAGE_SIZE);
|
||||
pointer_offset(p, OS_PAGE_SIZE), rsize - OS_PAGE_SIZE);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -399,6 +397,8 @@ namespace snmalloc
|
||||
if constexpr (zero_mem == YesZero)
|
||||
memory_provider.template zero<true>(
|
||||
p, bits::align_up(size, OS_PAGE_SIZE));
|
||||
else
|
||||
UNUSED(size);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -185,4 +185,13 @@ namespace snmalloc
|
||||
|
||||
return ((alignment - 1) | (size - 1)) + 1;
|
||||
}
|
||||
|
||||
SNMALLOC_FAST_PATH static size_t round_size(size_t size)
|
||||
{
|
||||
if (size > size_to_sizeclass(NUM_SIZECLASSES - 1))
|
||||
{
|
||||
return bits::next_pow2(size);
|
||||
}
|
||||
return sizeclass_to_size(size_to_sizeclass(size));
|
||||
}
|
||||
} // namespace snmalloc
|
||||
|
||||
@@ -86,7 +86,7 @@ extern "C"
|
||||
#endif
|
||||
size_t sz = Alloc::alloc_size(ptr);
|
||||
// Keep the current allocation if the given size is in the same sizeclass.
|
||||
if (sz == sizeclass_to_size(size_to_sizeclass(size)))
|
||||
if (sz == round_size(size))
|
||||
return ptr;
|
||||
|
||||
void* p = SNMALLOC_NAME_MANGLE(malloc)(size);
|
||||
|
||||
@@ -18,8 +18,13 @@ void check_result(size_t size, size_t align, void* p, int err, bool null)
|
||||
}
|
||||
else
|
||||
{
|
||||
if (our_malloc_usable_size(p) < size)
|
||||
auto asize = our_malloc_usable_size(p);
|
||||
if (asize < size)
|
||||
{
|
||||
printf(
|
||||
"Usable size is %zu, but required to be at least %zu.\n", asize, size);
|
||||
abort();
|
||||
}
|
||||
|
||||
if (static_cast<size_t>(reinterpret_cast<uintptr_t>(p) % align) != 0)
|
||||
abort();
|
||||
@@ -30,7 +35,7 @@ void check_result(size_t size, size_t align, void* p, int err, bool null)
|
||||
|
||||
void test_calloc(size_t nmemb, size_t size, int err, bool null)
|
||||
{
|
||||
fprintf(stderr, "calloc(%d, %d)\n", (int)nmemb, (int)size);
|
||||
fprintf(stderr, "calloc(%zu, %zu)\n", nmemb, size);
|
||||
errno = 0;
|
||||
void* p = our_calloc(nmemb, size);
|
||||
|
||||
@@ -47,7 +52,11 @@ void test_calloc(size_t nmemb, size_t size, int err, bool null)
|
||||
|
||||
void test_realloc(void* p, size_t size, int err, bool null)
|
||||
{
|
||||
fprintf(stderr, "realloc(%p(%d), %d)\n", p, int(size), (int)size);
|
||||
size_t old_size = 0;
|
||||
if (p != nullptr)
|
||||
old_size = our_malloc_usable_size(p);
|
||||
|
||||
fprintf(stderr, "realloc(%p(%zu), %zu)\n", p, old_size, size);
|
||||
errno = 0;
|
||||
auto new_p = our_realloc(p, size);
|
||||
// Realloc failure case, deallocate original block
|
||||
@@ -58,7 +67,7 @@ void test_realloc(void* p, size_t size, int err, bool null)
|
||||
|
||||
void test_posix_memalign(size_t size, size_t align, int err, bool null)
|
||||
{
|
||||
fprintf(stderr, "posix_memalign(&p, %d, %d)\n", (int)align, (int)size);
|
||||
fprintf(stderr, "posix_memalign(&p, %zu, %zu)\n", align, size);
|
||||
void* p = nullptr;
|
||||
errno = our_posix_memalign(&p, align, size);
|
||||
check_result(size, align, p, err, null);
|
||||
@@ -66,7 +75,7 @@ void test_posix_memalign(size_t size, size_t align, int err, bool null)
|
||||
|
||||
void test_memalign(size_t size, size_t align, int err, bool null)
|
||||
{
|
||||
fprintf(stderr, "memalign(%d, %d)\n", (int)align, (int)size);
|
||||
fprintf(stderr, "memalign(%zu, %zu)\n", align, size);
|
||||
errno = 0;
|
||||
void* p = our_memalign(align, size);
|
||||
check_result(size, align, p, err, null);
|
||||
@@ -81,6 +90,16 @@ int main(int argc, char** argv)
|
||||
|
||||
constexpr int SUCCESS = 0;
|
||||
|
||||
test_realloc(our_malloc(64), 4194304, SUCCESS, false);
|
||||
|
||||
for (snmalloc::sizeclass_t sc = 0; sc < (SUPERSLAB_BITS + 4); sc++)
|
||||
{
|
||||
const size_t size = 1ULL << sc;
|
||||
printf("malloc: %zu\n", size);
|
||||
check_result(size, 1, our_malloc(size), SUCCESS, false);
|
||||
check_result(size + 1, 1, our_malloc(size + 1), SUCCESS, false);
|
||||
}
|
||||
|
||||
test_calloc(0, 0, SUCCESS, false);
|
||||
|
||||
for (snmalloc::sizeclass_t sc = 0; sc < NUM_SIZECLASSES; sc++)
|
||||
@@ -97,11 +116,37 @@ int main(int argc, char** argv)
|
||||
test_calloc(n, 0, SUCCESS, false);
|
||||
}
|
||||
test_calloc(0, size, SUCCESS, false);
|
||||
}
|
||||
|
||||
for (snmalloc::sizeclass_t sc = 0; sc < NUM_SIZECLASSES; sc++)
|
||||
{
|
||||
const size_t size = sizeclass_to_size(sc);
|
||||
test_realloc(our_malloc(size), size, SUCCESS, false);
|
||||
test_realloc(our_malloc(size), 0, SUCCESS, true);
|
||||
test_realloc(nullptr, size, SUCCESS, false);
|
||||
test_realloc(our_malloc(size), (size_t)-1, ENOMEM, true);
|
||||
for (snmalloc::sizeclass_t sc2 = 0; sc2 < NUM_SIZECLASSES; sc2++)
|
||||
{
|
||||
const size_t size2 = sizeclass_to_size(sc2);
|
||||
test_realloc(our_malloc(size), size2, SUCCESS, false);
|
||||
test_realloc(our_malloc(size + 1), size2, SUCCESS, false);
|
||||
}
|
||||
}
|
||||
|
||||
for (snmalloc::sizeclass_t sc = 0; sc < (SUPERSLAB_BITS + 4); sc++)
|
||||
{
|
||||
const size_t size = 1ULL << sc;
|
||||
test_realloc(our_malloc(size), size, SUCCESS, false);
|
||||
test_realloc(our_malloc(size), 0, SUCCESS, true);
|
||||
test_realloc(nullptr, size, SUCCESS, false);
|
||||
test_realloc(our_malloc(size), (size_t)-1, ENOMEM, true);
|
||||
for (snmalloc::sizeclass_t sc2 = 0; sc2 < (SUPERSLAB_BITS + 4); sc2++)
|
||||
{
|
||||
const size_t size2 = 1ULL << sc2;
|
||||
printf("size1: %zu, size2:%zu\n", size, size2);
|
||||
test_realloc(our_malloc(size), size2, SUCCESS, false);
|
||||
test_realloc(our_malloc(size + 1), size2, SUCCESS, false);
|
||||
}
|
||||
}
|
||||
|
||||
test_posix_memalign(0, 0, EINVAL, true);
|
||||
|
||||
@@ -221,7 +221,7 @@ void test_external_pointer_large()
|
||||
|
||||
for (size_t i = 0; i < count; i++)
|
||||
{
|
||||
size_t b = snmalloc::bits::is64() ? 28 : 26;
|
||||
size_t b = SUPERSLAB_BITS + 3;
|
||||
size_t rand = r.next() & ((1 << b) - 1);
|
||||
size_t size = (1 << 24) + rand;
|
||||
total_size += size;
|
||||
|
||||
@@ -18,7 +18,7 @@ void test_align_size()
|
||||
size < snmalloc::sizeclass_to_size(snmalloc::NUM_SIZECLASSES - 1);
|
||||
size++)
|
||||
{
|
||||
size_t rsize = snmalloc::sizeclass_to_size(size_to_sizeclass(size));
|
||||
size_t rsize = snmalloc::round_size(size);
|
||||
|
||||
if (rsize < size)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user