Make all large allocations naturally aligned

This makes any large allocation naturally aligned to its size. This
means all alignment requests can be handled without checks.
This commit is contained in:
Matthew Parkinson
2020-01-28 14:17:20 +00:00
parent a90c060708
commit 6e8edefc99
5 changed files with 6 additions and 58 deletions

View File

@@ -168,7 +168,7 @@ template<bool committed>
void* reserve(const size_t* size) noexcept;
```
Only one of these needs to be implemented, depending on whether the underlying
system can provide strongly (e.g. 16MiB) aligned memory regions.
system can provide strongly aligned memory regions.
If the system guarantees only page alignment, implement the second and snmalloc
will over-allocate and then trim the requested region.
If the system provides strong alignment, implement the first to return memory

View File

@@ -281,9 +281,6 @@ namespace snmalloc
template<class MemoryProvider>
class LargeAlloc
{
void* reserved_start = nullptr;
void* reserved_end = nullptr;
public:
// This will be a zero-size structure if stats are not enabled.
Stats stats;
@@ -292,38 +289,6 @@ namespace snmalloc
LargeAlloc(MemoryProvider& mp) : memory_provider(mp) {}
template<AllowReserve allow_reserve>
bool reserve_memory(size_t need, size_t add)
{
assert(reserved_start <= reserved_end);
/*
* Spell this comparison in terms of pointer subtraction like this,
* rather than "reserved_start + need < reserved_end" because the
* sum might not be representable on CHERI.
*/
if (pointer_diff(reserved_start, reserved_end) < need)
{
if constexpr (allow_reserve == YesReserve)
{
stats.segment_create();
reserved_start =
memory_provider.template reserve<false>(&add, SUPERSLAB_SIZE);
reserved_end = pointer_offset(reserved_start, add);
reserved_start = pointer_align_up<SUPERSLAB_SIZE>(reserved_start);
if (add < need)
return false;
}
else
{
return false;
}
}
return true;
}
template<ZeroMem zero_mem = NoZero, AllowReserve allow_reserve = YesReserve>
void* alloc(size_t large_class, size_t size)
{
@@ -337,23 +302,9 @@ namespace snmalloc
if (p == nullptr)
{
assert(reserved_start <= reserved_end);
size_t add;
if ((rsize + SUPERSLAB_SIZE) < RESERVE_SIZE)
add = RESERVE_SIZE;
else
add = rsize + SUPERSLAB_SIZE;
if (!reserve_memory<allow_reserve>(rsize, add))
return nullptr;
p = reserved_start;
reserved_start = pointer_offset(p, rsize);
stats.superslab_fresh();
// All memory is zeroed since it comes from reserved space.
memory_provider.template notify_using<NoZero>(p, size);
size_t add = rsize;
p = memory_provider.template reserve<false>(&add, rsize);
memory_provider.template notify_using<zero_mem>(p, size);
}
else
{

View File

@@ -179,8 +179,6 @@ namespace snmalloc
{
// Client responsible for checking alignment is not zero
assert(alignment != 0);
// Client responsible for checking alignment is not above SUPERSLAB_SIZE
assert(alignment <= SUPERSLAB_SIZE);
// Client responsible for checking alignment is a power of two
assert(bits::next_pow2(alignment) == alignment);

View File

@@ -108,8 +108,7 @@ extern "C"
SNMALLOC_NAME_MANGLE(memalign)(size_t alignment, size_t size)
{
if (
(alignment == 0) || (alignment == size_t(-1)) ||
(alignment > SUPERSLAB_SIZE))
(alignment == 0) || (alignment == size_t(-1)))
{
errno = EINVAL;
return nullptr;

View File

@@ -108,7 +108,7 @@ int main(int argc, char** argv)
test_posix_memalign((size_t)-1, 0, EINVAL, true);
test_posix_memalign(OS_PAGE_SIZE, sizeof(uintptr_t) / 2, EINVAL, true);
for (size_t align = sizeof(uintptr_t); align <= SUPERSLAB_SIZE; align <<= 1)
for (size_t align = sizeof(uintptr_t); align <= SUPERSLAB_SIZE * 8; align <<= 1)
{
for (snmalloc::sizeclass_t sc = 0; sc < NUM_SIZECLASSES; sc++)
{