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] = auto [heap_base, heap_length] =
Pagemap::concretePagemap.init(base, 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. // Push memory into the global range.
range_to_pow_2_blocks<MIN_CHUNK_BITS>( range_to_pow_2_blocks<MIN_CHUNK_BITS>(

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

@ -62,15 +62,9 @@ namespace snmalloc
* mmap/virtual alloc calls can be consolidated. * 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< using Base = Pipe<PalRange<Pal>, PagemapRegisterRange<Pagemap>>;
PalRange<Pal>,
PagemapRegisterRange<Pagemap, CONSOLIDATE_PAL_ALLOCS>>;
/** /**
* @} * @}
*/ */

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

@ -32,6 +32,21 @@ namespace snmalloc
std::is_same_v<PagemapEntry, typename ConcreteMap::EntryType>, std::is_same_v<PagemapEntry, typename ConcreteMap::EntryType>,
"BasicPagemap's PagemapEntry and ConcreteMap disagree!"); "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 * Instance of the concrete pagemap, accessible to the backend so that
* it can call the init method whose type dependent on fixed_range. * 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 * Register a range in the pagemap as in-use, requiring it to allow writing
* to the underlying memory. * 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 #pragma once
#include "../mem/metadata.h"
#include "../pal/pal.h" #include "../pal/pal.h"
#include "empty_range.h" #include "empty_range.h"
#include "range_helpers.h" #include "range_helpers.h"
namespace snmalloc namespace snmalloc
{ {
template< template<SNMALLOC_CONCEPT(IsPagemapWithRegister) Pagemap>
SNMALLOC_CONCEPT(IsWritablePagemapWithRegister) Pagemap,
bool CanConsolidate = true>
struct PagemapRegisterRange struct PagemapRegisterRange
{ {
template<typename ParentRange = EmptyRange<>> template<typename ParentRange = EmptyRange<>>
@ -30,13 +29,8 @@ namespace snmalloc
auto base = parent.alloc_range(size); auto base = parent.alloc_range(size);
if (base != nullptr) if (base != nullptr)
Pagemap::register_range(address_cast(base), size);
if (!CanConsolidate)
{ {
// Mark start of allocation in pagemap. Pagemap::register_range(base, size);
auto& entry = Pagemap::get_metaentry_mut(address_cast(base));
entry.set_boundary();
} }
return base; return base;

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

@ -63,10 +63,10 @@ namespace snmalloc
* which combines this and the core concept, above. * which combines this and the core concept, above.
*/ */
template<typename Pagemap> 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>; ->ConceptSame<void>;
}; };

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

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