From 591dc4c77f88e861709a55f6385afd1611735d38 Mon Sep 17 00:00:00 2001 From: Matthew Parkinson Date: Wed, 21 Sep 2022 11:15:44 +0100 Subject: [PATCH] Add indirect range (#562) * Add indirect range The ranges currently either completely own the parent range, or it is a static and thus completely shared. The indirect range allows sharing without it being global. Co-authored-by: Nathaniel Filardo --- .../backend_helpers/backend_helpers.h | 1 + src/snmalloc/backend_helpers/indirectrange.h | 54 +++++++++++++++++++ src/snmalloc/backend_helpers/range_helpers.h | 31 +++++++++++ 3 files changed, 86 insertions(+) create mode 100644 src/snmalloc/backend_helpers/indirectrange.h diff --git a/src/snmalloc/backend_helpers/backend_helpers.h b/src/snmalloc/backend_helpers/backend_helpers.h index fa4a708f7..a84a97f72 100644 --- a/src/snmalloc/backend_helpers/backend_helpers.h +++ b/src/snmalloc/backend_helpers/backend_helpers.h @@ -5,6 +5,7 @@ #include "defaultpagemapentry.h" #include "empty_range.h" #include "globalrange.h" +#include "indirectrange.h" #include "largebuddyrange.h" #include "logrange.h" #include "pagemap.h" diff --git a/src/snmalloc/backend_helpers/indirectrange.h b/src/snmalloc/backend_helpers/indirectrange.h new file mode 100644 index 000000000..932c3b2b4 --- /dev/null +++ b/src/snmalloc/backend_helpers/indirectrange.h @@ -0,0 +1,54 @@ +#pragma once + +#include "../ds/ds.h" +#include "empty_range.h" + +namespace snmalloc +{ + /** + * Stores a references to the parent range so that it can be shared + * without `static` scope. + * + * This could be used to allow multiple allocators on a single region of + * memory. + */ + struct IndirectRange + { + template> + class Type : public RefParent + { + using RefParent::parent; + + public: + static constexpr bool Aligned = ParentRange::Aligned; + + static_assert( + ParentRange::ConcurrencySafe, + "IndirectRange requires a concurrency safe parent."); + + static constexpr bool ConcurrencySafe = true; + + using ChunkBounds = typename ParentRange::ChunkBounds; + + constexpr Type() = default; + + CapPtr alloc_range(size_t size) + { + return parent->alloc_range(size); + } + + void dealloc_range(CapPtr base, size_t size) + { + parent->dealloc_range(base, size); + } + + /** + * Points the parent reference to the given range. + */ + void set_parent(ParentRange* p) + { + parent = p; + } + }; + }; +} // namespace snmalloc diff --git a/src/snmalloc/backend_helpers/range_helpers.h b/src/snmalloc/backend_helpers/range_helpers.h index 1534bb8df..9d97f0e3a 100644 --- a/src/snmalloc/backend_helpers/range_helpers.h +++ b/src/snmalloc/backend_helpers/range_helpers.h @@ -130,4 +130,35 @@ namespace snmalloc } }; + /** + * Helper class for allowing a range to be navigated to find an + * ancestor of a specific type. The parent is a pointer to a range; + * this allows the parent to be shared. + */ + template + class RefParent + { + protected: + Parent* parent{}; + + public: + /** + * Returns the outermost Ancestor with the correct type. + * + * Fails to compile if no such ancestor exists. + */ + template + Anc* ancestor() + { + if constexpr (std::is_same_v) + { + return parent; + } + else + { + return parent->template ancestor(); + } + } + }; + } // namespace snmalloc