From 7f3b59eaf9b425c6c2d34828ac927978bb160f8c Mon Sep 17 00:00:00 2001 From: Nathaniel Wesley Filardo Date: Mon, 28 Nov 2022 04:45:17 +0000 Subject: [PATCH] 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. --- src/snmalloc/backend/fixedglobalconfig.h | 4 ++- src/snmalloc/backend/globalconfig.h | 10 ++----- src/snmalloc/backend_helpers/pagemap.h | 28 +++++++++++++++++-- .../backend_helpers/pagemapregisterrange.h | 12 ++------ src/snmalloc/mem/backend_concept.h | 4 +-- src/test/func/domestication/domestication.cc | 2 +- 6 files changed, 37 insertions(+), 23 deletions(-) diff --git a/src/snmalloc/backend/fixedglobalconfig.h b/src/snmalloc/backend/fixedglobalconfig.h index b3d42db..d8b0c0b 100644 --- a/src/snmalloc/backend/fixedglobalconfig.h +++ b/src/snmalloc/backend/fixedglobalconfig.h @@ -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::unsafe_from(heap_base); + + Pagemap::register_range(heap_arena, heap_length); // Push memory into the global range. range_to_pow_2_blocks( diff --git a/src/snmalloc/backend/globalconfig.h b/src/snmalloc/backend/globalconfig.h index 8dc08b5..46614f7 100644 --- a/src/snmalloc/backend/globalconfig.h +++ b/src/snmalloc/backend/globalconfig.h @@ -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, - PagemapRegisterRange>; + using Base = Pipe, PagemapRegisterRange>; + /** * @} */ diff --git a/src/snmalloc/backend_helpers/pagemap.h b/src/snmalloc/backend_helpers/pagemap.h index 0466913..2e11848 100644 --- a/src/snmalloc/backend_helpers/pagemap.h +++ b/src/snmalloc/backend_helpers/pagemap.h @@ -32,6 +32,21 @@ namespace snmalloc std::is_same_v, "BasicPagemap's PagemapEntry and ConcreteMap disagree!"); + static_assert( + std::is_base_of_v, + "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 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(); + } } /** diff --git a/src/snmalloc/backend_helpers/pagemapregisterrange.h b/src/snmalloc/backend_helpers/pagemapregisterrange.h index 9a0019e..1a96cb0 100644 --- a/src/snmalloc/backend_helpers/pagemapregisterrange.h +++ b/src/snmalloc/backend_helpers/pagemapregisterrange.h @@ -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 struct PagemapRegisterRange { template> @@ -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; diff --git a/src/snmalloc/mem/backend_concept.h b/src/snmalloc/mem/backend_concept.h index 167836a..f0ed396 100644 --- a/src/snmalloc/mem/backend_concept.h +++ b/src/snmalloc/mem/backend_concept.h @@ -63,10 +63,10 @@ namespace snmalloc * which combines this and the core concept, above. */ template - concept IsPagemapWithRegister = requires(address_t addr, size_t sz) + concept IsPagemapWithRegister = requires(capptr::Arena p, size_t sz) { { - Pagemap::register_range(addr, sz) + Pagemap::register_range(p, sz) } ->ConceptSame; }; diff --git a/src/test/func/domestication/domestication.cc b/src/test/func/domestication/domestication.cc index 7087ca6..351643f 100644 --- a/src/test/func/domestication/domestication.cc +++ b/src/test/func/domestication/domestication.cc @@ -36,7 +36,7 @@ namespace snmalloc using LocalState = StandardLocalState< Pal, Pagemap, - Pipe, PagemapRegisterRange>>; + Pipe, PagemapRegisterRange>>; using GlobalPoolState = PoolState>;