Natural alignment for USE_MALLOC (#248)
* Add concept of natural alignment to tests. snmalloc naturally aligns blocks very heavily, so that the largest power-of-two in the rounded size is the alignment. This checks that in the test, and provides a method for finding the natural alignment of a block. * Improve USE_MALLOC to provide alignment snmalloc provides a lot of alginment guarantees. This ensures that when we pass through to the system allocator we still get those alignment guarantees. The commit also fixes the tests to work with USE_MALLOC, and builds a set of unit tests for ctest to check behaviour.
This commit is contained in:
committed by
GitHub
parent
f89f78ad46
commit
923705e514
@@ -23,6 +23,7 @@ extern "C" void oe_abort()
|
||||
using namespace snmalloc;
|
||||
int main()
|
||||
{
|
||||
#ifndef SNMALLOC_PASS_THROUGH // Depends on snmalloc specific features
|
||||
auto& mp = *MemoryProviderStateMixin<DefaultPal>::make();
|
||||
|
||||
// 28 is large enough to produce a nested allocator.
|
||||
@@ -51,4 +52,5 @@ int main()
|
||||
if (oe_end < r1)
|
||||
abort();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -22,7 +22,15 @@ void check_result(size_t size, size_t align, void* p, int err, bool null)
|
||||
|
||||
const auto alloc_size = our_malloc_usable_size(p);
|
||||
const auto expected_size = round_size(size);
|
||||
if ((align == 1) && (alloc_size != expected_size))
|
||||
#ifdef SNMALLOC_PASS_THROUGH
|
||||
// Calling system allocator may allocate a larger block than
|
||||
// snmalloc. Note, we have called the system allocator with
|
||||
// the size snmalloc would allocate, so it won't be smaller.
|
||||
const auto exact_size = false;
|
||||
#else
|
||||
const auto exact_size = align == 1;
|
||||
#endif
|
||||
if (exact_size && (alloc_size != expected_size))
|
||||
{
|
||||
printf(
|
||||
"Usable size is %zu, but required to be %zu.\n",
|
||||
@@ -30,7 +38,7 @@ void check_result(size_t size, size_t align, void* p, int err, bool null)
|
||||
expected_size);
|
||||
abort();
|
||||
}
|
||||
if ((align != 1) && (alloc_size < expected_size))
|
||||
if ((!exact_size) && (alloc_size < expected_size))
|
||||
{
|
||||
printf(
|
||||
"Usable size is %zu, but required to be at least %zu.\n",
|
||||
@@ -46,6 +54,16 @@ void check_result(size_t size, size_t align, void* p, int err, bool null)
|
||||
align);
|
||||
abort();
|
||||
}
|
||||
if (
|
||||
static_cast<size_t>(
|
||||
reinterpret_cast<uintptr_t>(p) % natural_alignment(size)) != 0)
|
||||
{
|
||||
printf(
|
||||
"Address is 0x%zx, but should have natural alignment to 0x%zx.\n",
|
||||
reinterpret_cast<uintptr_t>(p),
|
||||
natural_alignment(size));
|
||||
abort();
|
||||
}
|
||||
|
||||
our_free(p);
|
||||
}
|
||||
|
||||
@@ -140,7 +140,7 @@ void test_random_allocation()
|
||||
cell = alloc->alloc(16);
|
||||
auto pair = allocated.insert(cell);
|
||||
// Check not already allocated
|
||||
SNMALLOC_ASSERT(pair.second);
|
||||
SNMALLOC_CHECK(pair.second);
|
||||
UNUSED(pair);
|
||||
alloc_count++;
|
||||
}
|
||||
@@ -197,14 +197,14 @@ void test_double_alloc()
|
||||
for (size_t i = 0; i < (n * 2); i++)
|
||||
{
|
||||
void* p = a1->alloc(20);
|
||||
SNMALLOC_ASSERT(set1.find(p) == set1.end());
|
||||
SNMALLOC_CHECK(set1.find(p) == set1.end());
|
||||
set1.insert(p);
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < (n * 2); i++)
|
||||
{
|
||||
void* p = a2->alloc(20);
|
||||
SNMALLOC_ASSERT(set2.find(p) == set2.end());
|
||||
SNMALLOC_CHECK(set2.find(p) == set2.end());
|
||||
set2.insert(p);
|
||||
}
|
||||
|
||||
@@ -245,8 +245,8 @@ void test_external_pointer()
|
||||
void* p4 = Alloc::external_pointer<End>(p2);
|
||||
UNUSED(p3);
|
||||
UNUSED(p4);
|
||||
SNMALLOC_ASSERT(p1 == p3);
|
||||
SNMALLOC_ASSERT((size_t)p4 == (size_t)p1 + size - 1);
|
||||
SNMALLOC_CHECK(p1 == p3);
|
||||
SNMALLOC_CHECK((size_t)p4 == (size_t)p1 + size - 1);
|
||||
}
|
||||
|
||||
alloc->dealloc(p1, size);
|
||||
@@ -348,7 +348,7 @@ void test_alloc_16M()
|
||||
const size_t size = 16'000'000;
|
||||
|
||||
void* p1 = alloc->alloc(size);
|
||||
SNMALLOC_ASSERT(Alloc::alloc_size(Alloc::external_pointer(p1)) >= size);
|
||||
SNMALLOC_CHECK(Alloc::alloc_size(Alloc::external_pointer(p1)) >= size);
|
||||
alloc->dealloc(p1);
|
||||
}
|
||||
|
||||
@@ -359,7 +359,7 @@ void test_calloc_16M()
|
||||
const size_t size = 16'000'000;
|
||||
|
||||
void* p1 = alloc->alloc<YesZero>(size);
|
||||
SNMALLOC_ASSERT(Alloc::alloc_size(Alloc::external_pointer(p1)) >= size);
|
||||
SNMALLOC_CHECK(Alloc::alloc_size(Alloc::external_pointer(p1)) >= size);
|
||||
alloc->dealloc(p1);
|
||||
}
|
||||
|
||||
@@ -373,7 +373,7 @@ void test_calloc_large_bug()
|
||||
const size_t size = (SUPERSLAB_SIZE << 3) - 7;
|
||||
|
||||
void* p1 = alloc->alloc<YesZero>(size);
|
||||
SNMALLOC_ASSERT(Alloc::alloc_size(Alloc::external_pointer(p1)) >= size);
|
||||
SNMALLOC_CHECK(Alloc::alloc_size(Alloc::external_pointer(p1)) >= size);
|
||||
alloc->dealloc(p1);
|
||||
}
|
||||
|
||||
@@ -403,15 +403,17 @@ int main(int argc, char** argv)
|
||||
UNUSED(argv);
|
||||
#endif
|
||||
|
||||
test_calloc_large_bug();
|
||||
test_external_pointer_dealloc_bug();
|
||||
test_external_pointer_large();
|
||||
test_alloc_dealloc_64k();
|
||||
test_random_allocation();
|
||||
test_calloc();
|
||||
test_double_alloc();
|
||||
#ifndef SNMALLOC_PASS_THROUGH // Depends on snmalloc specific features
|
||||
test_calloc_large_bug();
|
||||
test_external_pointer_dealloc_bug();
|
||||
test_external_pointer_large();
|
||||
test_external_pointer();
|
||||
test_alloc_16M();
|
||||
test_calloc_16M();
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -76,7 +76,7 @@ int main(int argc, char** argv)
|
||||
{
|
||||
UNUSED(argc);
|
||||
UNUSED(argv);
|
||||
|
||||
#ifndef SNMALLOC_PASS_THROUGH // Depends on snmalloc specific features
|
||||
setup();
|
||||
|
||||
add_n_allocs(5);
|
||||
@@ -100,4 +100,5 @@ int main(int argc, char** argv)
|
||||
|
||||
remove_n_allocs(3);
|
||||
std::cout << "Teardown complete!" << std::endl;
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ void test_align_size()
|
||||
{
|
||||
bool failed = false;
|
||||
|
||||
SNMALLOC_ASSERT(snmalloc::aligned_size(128, 160) == 256);
|
||||
SNMALLOC_CHECK(snmalloc::aligned_size(128, 160) == 256);
|
||||
|
||||
for (size_t size = 1;
|
||||
size < snmalloc::sizeclass_to_size(snmalloc::NUM_SIZECLASSES - 1);
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
int main()
|
||||
{
|
||||
#ifndef SNMALLOC_PASS_THROUGH // This test depends on snmalloc internals
|
||||
snmalloc::Alloc* a = snmalloc::ThreadAlloc::get();
|
||||
bool result;
|
||||
|
||||
@@ -36,4 +37,5 @@ int main()
|
||||
{
|
||||
abort();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
Reference in New Issue
Block a user