Rearrange templates for buddy allocator.
This commit is contained in:
committed by
Matthew Parkinson
parent
79ea08779b
commit
79486b6331
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user