PagemapRegisterRange: don't presume Pagemap entry type

To date, we've had exactly one kind of Pagemap and it held exactly one
type of thing, a descendant of class MetaEntryBase.

PagemapRegisterRange tacitly assumed that the Pagemap (adapter) it
interacted would therefore store entries that could have .set_boundary()
called on them.  But in general there's no requirement that this be
true; Pagemaps are generic data structures.

To enable reuse of the PagemapRegisterRange machinery more generally,
change the type of Pagemap::register_range() to take a pointer (rather
than an address) and move the MetaEntryBase-specific functionality to
the backend_helpers/pagemap adapter.
This commit is contained in:
Nathaniel Wesley Filardo 2022-11-28 04:45:17 +00:00 коммит произвёл Nathaniel Filardo
Родитель 06873ac366
Коммит 7f3b59eaf9
6 изменённых файлов: 37 добавлений и 23 удалений

Просмотреть файл

@ -74,7 +74,9 @@ namespace snmalloc
auto [heap_base, heap_length] =
Pagemap::concretePagemap.init(base, length);
Pagemap::register_range(address_cast(heap_base), heap_length);
auto heap_arena = capptr::Arena<void>::unsafe_from(heap_base);
Pagemap::register_range(heap_arena, heap_length);
// Push memory into the global range.
range_to_pow_2_blocks<MIN_CHUNK_BITS>(

Просмотреть файл

@ -62,15 +62,9 @@ namespace snmalloc
* mmap/virtual alloc calls can be consolidated.
* @{
*/
# if defined(_WIN32) || defined(__CHERI_PURE_CAPABILITY__)
static constexpr bool CONSOLIDATE_PAL_ALLOCS = false;
# else
static constexpr bool CONSOLIDATE_PAL_ALLOCS = true;
# endif
using Base = Pipe<
PalRange<Pal>,
PagemapRegisterRange<Pagemap, CONSOLIDATE_PAL_ALLOCS>>;
using Base = Pipe<PalRange<Pal>, PagemapRegisterRange<Pagemap>>;
/**
* @}
*/

Просмотреть файл

@ -32,6 +32,21 @@ namespace snmalloc
std::is_same_v<PagemapEntry, typename ConcreteMap::EntryType>,
"BasicPagemap's PagemapEntry and ConcreteMap disagree!");
static_assert(
std::is_base_of_v<MetaEntryBase, PagemapEntry>,
"BasicPagemap's PagemapEntry type is not a MetaEntryBase");
/**
* Prevent snmalloc's backend ranges from consolidating across adjacent OS
* allocations on platforms (e.g., Windows or StrictProvenance) where
* that's required.
*/
#if defined(_WIN32) || defined(__CHERI_PURE_CAPABILITY__)
static constexpr bool CONSOLIDATE_PAL_ALLOCS = false;
#else
static constexpr bool CONSOLIDATE_PAL_ALLOCS = true;
#endif
/**
* Instance of the concrete pagemap, accessible to the backend so that
* it can call the init method whose type dependent on fixed_range.
@ -78,10 +93,19 @@ namespace snmalloc
/**
* Register a range in the pagemap as in-use, requiring it to allow writing
* to the underlying memory.
*
* Mark the MetaEntry at the bottom of the range as a boundary, preventing
* consolidation with a lower range, unless CONSOLIDATE_PAL_ALLOCS.
*/
static void register_range(address_t p, size_t sz)
static void register_range(capptr::Arena<void> p, size_t sz)
{
concretePagemap.register_range(p, sz);
concretePagemap.register_range(address_cast(p), sz);
if constexpr (!CONSOLIDATE_PAL_ALLOCS)
{
// Mark start of allocation in pagemap.
auto& entry = get_metaentry_mut(address_cast(p));
entry.set_boundary();
}
}
/**

Просмотреть файл

@ -1,14 +1,13 @@
#pragma once
#include "../mem/metadata.h"
#include "../pal/pal.h"
#include "empty_range.h"
#include "range_helpers.h"
namespace snmalloc
{
template<
SNMALLOC_CONCEPT(IsWritablePagemapWithRegister) Pagemap,
bool CanConsolidate = true>
template<SNMALLOC_CONCEPT(IsPagemapWithRegister) Pagemap>
struct PagemapRegisterRange
{
template<typename ParentRange = EmptyRange<>>
@ -30,13 +29,8 @@ namespace snmalloc
auto base = parent.alloc_range(size);
if (base != nullptr)
Pagemap::register_range(address_cast(base), size);
if (!CanConsolidate)
{
// Mark start of allocation in pagemap.
auto& entry = Pagemap::get_metaentry_mut(address_cast(base));
entry.set_boundary();
Pagemap::register_range(base, size);
}
return base;

Просмотреть файл

@ -63,10 +63,10 @@ namespace snmalloc
* which combines this and the core concept, above.
*/
template<typename Pagemap>
concept IsPagemapWithRegister = requires(address_t addr, size_t sz)
concept IsPagemapWithRegister = requires(capptr::Arena<void> p, size_t sz)
{
{
Pagemap::register_range(addr, sz)
Pagemap::register_range(p, sz)
}
->ConceptSame<void>;
};

Просмотреть файл

@ -36,7 +36,7 @@ namespace snmalloc
using LocalState = StandardLocalState<
Pal,
Pagemap,
Pipe<PalRange<Pal>, PagemapRegisterRange<Pagemap, false>>>;
Pipe<PalRange<Pal>, PagemapRegisterRange<Pagemap>>>;
using GlobalPoolState = PoolState<CoreAllocator<CustomConfig>>;