From 7fbca11527573d39ca2fef344e0e2c02f4bf04d8 Mon Sep 17 00:00:00 2001 From: Nathaniel Filardo <105816689+nwf-msr@users.noreply.github.com> Date: Mon, 9 Sep 2024 12:25:51 -0400 Subject: [PATCH] 0-length arrays in Buddy ranges (#672) * backend_helpers: introduce NopRange * Fix to Buddy MIN == MAX case This fixes the 0-length arrays discussed (and made into assertion failures) in the next commit. This works because the Buddy's `MIN_SIZE_BITS` is instantiated at `MIN_CHUNK_BITS`, and so we ensure that we instantiate the LargeBuddyRange only with `max_page_chunk_size_bits` above `MIN_CHUNK_BITS`. * Buddy range: assert that MAX > MIN Now that the case leading to several 0-sized arrays in Buddy ranges, that then cause gcc's -Warray-bounds to trip, has been removed, add a static assert so that we can catch this with better error messages next time. --- src/snmalloc/backend/meta_protected_range.h | 13 ++++--- .../backend_helpers/backend_helpers.h | 1 + src/snmalloc/backend_helpers/buddy.h | 2 ++ src/snmalloc/backend_helpers/noprange.h | 36 +++++++++++++++++++ 4 files changed, 47 insertions(+), 5 deletions(-) create mode 100644 src/snmalloc/backend_helpers/noprange.h diff --git a/src/snmalloc/backend/meta_protected_range.h b/src/snmalloc/backend/meta_protected_range.h index 5c5795c..b94968c 100644 --- a/src/snmalloc/backend/meta_protected_range.h +++ b/src/snmalloc/backend/meta_protected_range.h @@ -75,11 +75,14 @@ namespace snmalloc CommitRange, // In case of huge pages, we don't want to give each thread its own huge // page, so commit in the global range. - LargeBuddyRange< - max_page_chunk_size_bits, - max_page_chunk_size_bits, - Pagemap, - page_size_bits>, + std::conditional_t< + (max_page_chunk_size_bits > MIN_CHUNK_BITS), + LargeBuddyRange< + max_page_chunk_size_bits, + max_page_chunk_size_bits, + Pagemap, + page_size_bits>, + NopRange>, LogRange<4>, GlobalRange, StatsRange>; diff --git a/src/snmalloc/backend_helpers/backend_helpers.h b/src/snmalloc/backend_helpers/backend_helpers.h index 2104e68..24e02b0 100644 --- a/src/snmalloc/backend_helpers/backend_helpers.h +++ b/src/snmalloc/backend_helpers/backend_helpers.h @@ -9,6 +9,7 @@ #include "indirectrange.h" #include "largebuddyrange.h" #include "logrange.h" +#include "noprange.h" #include "pagemap.h" #include "pagemapregisterrange.h" #include "palrange.h" diff --git a/src/snmalloc/backend_helpers/buddy.h b/src/snmalloc/backend_helpers/buddy.h index 2d9f27b..c425021 100644 --- a/src/snmalloc/backend_helpers/buddy.h +++ b/src/snmalloc/backend_helpers/buddy.h @@ -15,6 +15,8 @@ namespace snmalloc template class Buddy { + static_assert(MAX_SIZE_BITS > MIN_SIZE_BITS); + struct Entry { typename Rep::Contents cache[3]; diff --git a/src/snmalloc/backend_helpers/noprange.h b/src/snmalloc/backend_helpers/noprange.h new file mode 100644 index 0000000..45dcfdc --- /dev/null +++ b/src/snmalloc/backend_helpers/noprange.h @@ -0,0 +1,36 @@ +#pragma once +#include "range_helpers.h" + +namespace snmalloc +{ + struct NopRange + { + template + class Type : public ContainsParent + { + using ContainsParent::parent; + + public: + static constexpr bool Aligned = ParentRange::Aligned; + + static constexpr bool ConcurrencySafe = ParentRange::ConcurrencySafe; + + using ChunkBounds = typename ParentRange::ChunkBounds; + static_assert( + ChunkBounds::address_space_control == + capptr::dimension::AddressSpaceControl::Full); + + 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); + } + }; + }; +} // namespace snmalloc