Rearrange templates for buddy allocator.

This commit is contained in:
Matthew Parkinson
2022-02-03 17:17:58 +00:00
committed by Matthew Parkinson
parent 79ea08779b
commit 79486b6331
4 changed files with 71 additions and 83 deletions

View File

@@ -19,10 +19,12 @@ namespace snmalloc
* It cannot unreserve memory, so this does not require the
* usual complexity of a buddy allocator.
*/
template<SNMALLOC_CONCEPT(ConceptPAL) PAL>
template<
SNMALLOC_CONCEPT(ConceptPAL) PAL,
SNMALLOC_CONCEPT(ConceptBackendMetaRange) Pagemap>
class AddressSpaceManager
{
AddressSpaceManagerCore core;
AddressSpaceManagerCore<Pagemap> core;
/**
* This is infrequently used code, a spin lock simplifies the code
@@ -42,7 +44,7 @@ namespace snmalloc
* part of satisfying the request will be registered with the provided
* arena_map for use in subsequent amplification.
*/
template<bool committed, SNMALLOC_CONCEPT(ConceptBackendMetaRange) Pagemap>
template<bool committed>
capptr::Chunk<void>
reserve(typename Pagemap::LocalState* local_state, size_t size)
{
@@ -70,7 +72,7 @@ namespace snmalloc
capptr::Chunk<void> res;
{
FlagLock lock(spin_lock);
res = core.template reserve<PAL, Pagemap>(local_state, size);
res = core.template reserve<PAL>(local_state, size);
if (res == nullptr)
{
// Allocation failed ask OS for more memory
@@ -134,10 +136,10 @@ namespace snmalloc
Pagemap::register_range(local_state, address_cast(block), block_size);
core.template add_range<PAL, Pagemap>(local_state, block, block_size);
core.template add_range<PAL>(local_state, block, block_size);
// still holding lock so guaranteed to succeed.
res = core.template reserve<PAL, Pagemap>(local_state, size);
res = core.template reserve<PAL>(local_state, size);
}
}
@@ -155,7 +157,7 @@ namespace snmalloc
* This is useful for allowing the space required for alignment to be
* used, by smaller objects.
*/
template<bool committed, SNMALLOC_CONCEPT(ConceptBackendMetaRange) Pagemap>
template<bool committed>
capptr::Chunk<void> reserve_with_left_over(
typename Pagemap::LocalState* local_state, size_t size)
{
@@ -165,19 +167,19 @@ namespace snmalloc
size_t rsize = bits::next_pow2(size);
auto res = reserve<false, Pagemap>(local_state, rsize);
auto res = reserve<false>(local_state, rsize);
if (res != nullptr)
{
if (rsize > size)
{
FlagLock lock(spin_lock);
core.template add_range<PAL, Pagemap>(
core.template add_range<PAL>(
local_state, pointer_offset(res, size), rsize - size);
}
if constexpr (committed)
core.commit_block<PAL>(res, size);
core.template commit_block<PAL>(res, size);
}
return res;
}
@@ -193,14 +195,13 @@ namespace snmalloc
* Add a range of memory to the address space.
* Divides blocks into power of two sizes with natural alignment
*/
template<SNMALLOC_CONCEPT(ConceptBackendMeta) Pagemap>
void add_range(
typename Pagemap::LocalState* local_state,
capptr::Chunk<void> base,
size_t length)
{
FlagLock lock(spin_lock);
core.add_range<PAL, Pagemap>(local_state, base, length);
core.template add_range<PAL>(local_state, base, length);
}
};
} // namespace snmalloc

View File

@@ -31,6 +31,7 @@ namespace snmalloc
* to Metaslab objects in perpetuity; it could also make {set,get}_next less
* scary.
*/
template<SNMALLOC_CONCEPT(ConceptBackendMeta) Pagemap>
class AddressSpaceManagerCore
{
struct FreeChunk
@@ -77,7 +78,6 @@ namespace snmalloc
* to store the next pointer for the list of unused address space of a
* particular size.
*/
template<SNMALLOC_CONCEPT(ConceptBackendMeta) Pagemap>
void set_next(
typename Pagemap::LocalState* local_state,
size_t align_bits,
@@ -112,7 +112,6 @@ namespace snmalloc
* to store the next pointer for the list of unused address space of a
* particular size.
*/
template<SNMALLOC_CONCEPT(ConceptBackendMeta) Pagemap>
capptr::Chunk<FreeChunk> get_next(
typename Pagemap::LocalState* local_state,
size_t align_bits,
@@ -132,9 +131,7 @@ namespace snmalloc
/**
* Adds a block to `ranges`.
*/
template<
SNMALLOC_CONCEPT(ConceptPAL) PAL,
SNMALLOC_CONCEPT(ConceptBackendMeta) Pagemap>
template<SNMALLOC_CONCEPT(ConceptPAL) PAL>
void add_block(
typename Pagemap::LocalState* local_state,
size_t align_bits,
@@ -143,17 +140,15 @@ namespace snmalloc
check_block(base, align_bits);
SNMALLOC_ASSERT(align_bits < 64);
set_next<Pagemap>(local_state, align_bits, base, ranges[align_bits]);
ranges[align_bits] = base.as_static<FreeChunk>();
set_next(local_state, align_bits, base, ranges[align_bits]);
ranges[align_bits] = base.template as_static<FreeChunk>();
}
/**
* Find a block of the correct size. May split larger blocks
* to satisfy this request.
*/
template<
SNMALLOC_CONCEPT(ConceptPAL) PAL,
SNMALLOC_CONCEPT(ConceptBackendMeta) Pagemap>
template<SNMALLOC_CONCEPT(ConceptPAL) PAL>
capptr::Chunk<void>
remove_block(typename Pagemap::LocalState* local_state, size_t align_bits)
{
@@ -168,7 +163,7 @@ namespace snmalloc
// Look for larger block and split up recursively
capptr::Chunk<void> bigger =
remove_block<PAL, Pagemap>(local_state, align_bits + 1);
remove_block<PAL>(local_state, align_bits + 1);
if (SNMALLOC_UNLIKELY(bigger == nullptr))
return nullptr;
@@ -184,7 +179,7 @@ namespace snmalloc
size_t half_bigger_size = bits::one_at_bit(align_bits);
auto left_over = pointer_offset(bigger, half_bigger_size);
add_block<PAL, Pagemap>(
add_block<PAL>(
local_state,
align_bits,
Aal::capptr_bound<FreeChunk, capptr::bounds::Chunk>(
@@ -196,7 +191,7 @@ namespace snmalloc
}
check_block(first, align_bits);
ranges[align_bits] = get_next<Pagemap>(local_state, align_bits, first);
ranges[align_bits] = get_next(local_state, align_bits, first);
return first.as_void();
}
@@ -205,9 +200,7 @@ namespace snmalloc
* Add a range of memory to the address space.
* Divides blocks into power of two sizes with natural alignment
*/
template<
SNMALLOC_CONCEPT(ConceptPAL) PAL,
SNMALLOC_CONCEPT(ConceptBackendMeta) Pagemap>
template<SNMALLOC_CONCEPT(ConceptPAL) PAL>
void add_range(
typename Pagemap::LocalState* local_state,
capptr::Chunk<void> base,
@@ -242,7 +235,7 @@ namespace snmalloc
Aal::capptr_bound<FreeChunk, capptr::bounds::Chunk>(base, align);
check_block(b, align_bits);
add_block<PAL, Pagemap>(local_state, align_bits, b);
add_block<PAL>(local_state, align_bits, b);
base = pointer_offset(base, align);
length -= align;
@@ -274,9 +267,7 @@ namespace snmalloc
* part of satisfying the request will be registered with the provided
* arena_map for use in subsequent amplification.
*/
template<
SNMALLOC_CONCEPT(ConceptPAL) PAL,
SNMALLOC_CONCEPT(ConceptBackendMeta) Pagemap>
template<SNMALLOC_CONCEPT(ConceptPAL) PAL>
capptr::Chunk<void>
reserve(typename Pagemap::LocalState* local_state, size_t size)
{
@@ -287,8 +278,7 @@ namespace snmalloc
SNMALLOC_ASSERT(bits::is_pow2(size));
SNMALLOC_ASSERT(size >= sizeof(void*));
return remove_block<PAL, Pagemap>(
local_state, bits::next_pow2_bits(size));
return remove_block<PAL>(local_state, bits::next_pow2_bits(size));
}
/**
@@ -298,9 +288,7 @@ namespace snmalloc
* This is useful for allowing the space required for alignment to be
* used by smaller objects.
*/
template<
SNMALLOC_CONCEPT(ConceptPAL) PAL,
SNMALLOC_CONCEPT(ConceptBackendMeta) Pagemap>
template<SNMALLOC_CONCEPT(ConceptPAL) PAL>
capptr::Chunk<void> reserve_with_left_over(
typename Pagemap::LocalState* local_state, size_t size)
{
@@ -310,7 +298,7 @@ namespace snmalloc
size_t rsize = bits::next_pow2(size);
auto res = reserve<PAL, Pagemap>(local_state, rsize);
auto res = reserve<PAL>(local_state, rsize);
if (res != nullptr)
{
@@ -323,7 +311,7 @@ namespace snmalloc
size_t residual_size = rsize - size;
auto residual = pointer_offset(res, size);
res = Aal::capptr_bound<void, capptr::bounds::Chunk>(res, size);
add_range<PAL, Pagemap>(local_state, residual, residual_size);
add_range<PAL>(local_state, residual, residual_size);
}
}
return res;

View File

@@ -62,7 +62,9 @@ namespace snmalloc
* address space to protect this from corruption.
*/
static capptr::Chunk<void> alloc_meta_data(
AddressSpaceManager<PAL>& global, LocalState* local_state, size_t size)
AddressSpaceManager<PAL, Pagemap>& global,
LocalState* local_state,
size_t size)
{
return reserve<true>(global, local_state, size);
}
@@ -77,7 +79,7 @@ namespace snmalloc
* where metaslab, is the second element of the pair return.
*/
static std::pair<capptr::Chunk<void>, Metaslab*> alloc_chunk(
AddressSpaceManager<PAL>& global,
AddressSpaceManager<PAL, Pagemap>& global,
LocalState* local_state,
size_t size,
RemoteAllocator* remote,
@@ -123,7 +125,9 @@ namespace snmalloc
*/
template<bool is_meta>
static capptr::Chunk<void> reserve(
AddressSpaceManager<PAL>& global, LocalState* local_state, size_t size)
AddressSpaceManager<PAL, Pagemap>& global,
LocalState* local_state,
size_t size)
{
#ifdef SNMALLOC_META_PROTECTED
constexpr auto MAX_CACHED_SIZE =
@@ -142,16 +146,14 @@ namespace snmalloc
auto& local = local_state->local_address_space;
#endif
p = local.template reserve_with_left_over<PAL, Pagemap>(
local_state, size);
p = local.template reserve_with_left_over<PAL>(local_state, size);
if (p != nullptr)
{
return p;
}
auto refill_size = LOCAL_CACHE_BLOCK;
auto refill =
global.template reserve<false, Pagemap>(local_state, refill_size);
auto refill = global.template reserve<false>(local_state, refill_size);
if (refill == nullptr)
return nullptr;
@@ -163,12 +165,10 @@ namespace snmalloc
}
#endif
PAL::template notify_using<NoZero>(refill.unsafe_ptr(), refill_size);
local.template add_range<PAL, Pagemap>(
local_state, refill, refill_size);
local.template add_range<PAL>(local_state, refill, refill_size);
// This should succeed
return local.template reserve_with_left_over<PAL, Pagemap>(
local_state, size);
return local.template reserve_with_left_over<PAL>(local_state, size);
}
#ifdef SNMALLOC_META_PROTECTED
@@ -179,7 +179,7 @@ namespace snmalloc
size_t rsize = bits::max(OS_PAGE_SIZE, bits::next_pow2(size));
size_t size_request = rsize * 64;
p = global.template reserve<false, Pagemap>(local_state, size_request);
p = global.template reserve<false>(local_state, size_request);
if (p == nullptr)
return nullptr;
@@ -195,8 +195,7 @@ namespace snmalloc
SNMALLOC_ASSERT(!is_meta);
#endif
p = global.template reserve_with_left_over<true, Pagemap>(
local_state, size);
p = global.template reserve_with_left_over<true>(local_state, size);
return p;
}
@@ -242,33 +241,7 @@ namespace snmalloc
public:
using Pal = PAL;
/**
* Local state for the backend allocator.
*
* This class contains thread local structures to make the implementation
* of the backend allocator more efficient.
*/
class LocalState
{
template<
SNMALLOC_CONCEPT(ConceptPAL) PAL2,
typename LocalState,
SNMALLOC_CONCEPT(ConceptBackendMetaRange) Pagemap>
friend class AddressSpaceAllocatorCommon;
AddressSpaceManagerCore local_address_space;
#ifdef SNMALLOC_META_PROTECTED
/**
* Secondary local address space, so we can apply some randomisation
* and guard pages to protect the meta-data.
*/
AddressSpaceManagerCore local_meta_address_space;
#endif
};
SNMALLOC_REQUIRE_CONSTINIT
static inline AddressSpaceManager<PAL> address_space;
class LocalState;
class Pagemap
{
@@ -343,6 +316,34 @@ namespace snmalloc
}
};
/**
* Local state for the backend allocator.
*
* This class contains thread local structures to make the implementation
* of the backend allocator more efficient.
*/
class LocalState
{
template<
SNMALLOC_CONCEPT(ConceptPAL) PAL2,
typename LocalState,
SNMALLOC_CONCEPT(ConceptBackendMetaRange) Pagemap2>
friend class AddressSpaceAllocatorCommon;
AddressSpaceManagerCore<Pagemap> local_address_space;
#ifdef SNMALLOC_META_PROTECTED
/**
* Secondary local address space, so we can apply some randomisation
* and guard pages to protect the meta-data.
*/
AddressSpaceManagerCore<Pagemap> local_meta_address_space;
#endif
};
SNMALLOC_REQUIRE_CONSTINIT
static inline AddressSpaceManager<PAL, Pagemap> address_space;
private:
using AddressSpaceAllocator =
AddressSpaceAllocatorCommon<Pal, LocalState, Pagemap>;
@@ -364,7 +365,7 @@ namespace snmalloc
auto [heap_base, heap_length] =
Pagemap::concretePagemap.init(base, length);
address_space.template add_range<Pagemap>(
address_space.add_range(
local_state, capptr::Chunk<void>(heap_base), heap_length);
}

View File

@@ -21,8 +21,6 @@ struct T
T() {}
};
AddressSpaceManager<DefaultPal> address_space;
FlatPagemap<GRANULARITY_BITS, T, DefaultPal, false> pagemap_test_unbound;
FlatPagemap<GRANULARITY_BITS, T, DefaultPal, true> pagemap_test_bound;