From 07bb3210665b862d462828a8cd640e4229433530 Mon Sep 17 00:00:00 2001 From: Matthew Parkinson Date: Tue, 13 Sep 2022 11:23:52 +0100 Subject: [PATCH 1/4] Fail more abruptly if the bounds are not exact. --- src/snmalloc/aal/aal_cheri.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/snmalloc/aal/aal_cheri.h b/src/snmalloc/aal/aal_cheri.h index 7152e6490..b05bb5fad 100644 --- a/src/snmalloc/aal/aal_cheri.h +++ b/src/snmalloc/aal/aal_cheri.h @@ -86,6 +86,10 @@ namespace snmalloc } void* pb = __builtin_cheri_bounds_set_exact(a.unsafe_ptr(), size); + + SNMALLOC_ASSERT( + __builtin_cheri_tag_get(pb) && "capptr_bound exactness failed."); + return CapPtr::unsafe_from(static_cast(pb)); } From 53c1e69a64d95f504dbca082f8c5d48e37bb2c66 Mon Sep 17 00:00:00 2001 From: Matthew Parkinson Date: Wed, 14 Sep 2022 10:50:44 +0100 Subject: [PATCH 2/4] Move bounding from Pool into Backend. This commit makes the rounding and the bounding occur in the same function. --- src/snmalloc/backend/backend.h | 8 ++++++-- src/snmalloc/mem/backend_concept.h | 2 +- src/snmalloc/mem/pool.h | 7 ++----- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/src/snmalloc/backend/backend.h b/src/snmalloc/backend/backend.h index 12663be83..855daaa26 100644 --- a/src/snmalloc/backend/backend.h +++ b/src/snmalloc/backend/backend.h @@ -39,7 +39,7 @@ namespace snmalloc * does not avail itself of this degree of freedom. */ template - static capptr::Arena + static capptr::Alloc alloc_meta_data(LocalState* local_state, size_t size) { capptr::Arena p; @@ -61,9 +61,13 @@ namespace snmalloc } if (p == nullptr) + { errno = ENOMEM; + return nullptr; + } - return p; + return capptr_to_user_address_control( + Aal::capptr_bound(p, size)); } /** diff --git a/src/snmalloc/mem/backend_concept.h b/src/snmalloc/mem/backend_concept.h index 951762704..215db1caf 100644 --- a/src/snmalloc/mem/backend_concept.h +++ b/src/snmalloc/mem/backend_concept.h @@ -122,7 +122,7 @@ namespace snmalloc { Backend::template alloc_meta_data(local_state, size) } - ->ConceptSame>; + ->ConceptSame>; } &&requires( LocalState& local_state, diff --git a/src/snmalloc/mem/pool.h b/src/snmalloc/mem/pool.h index 0513c141d..537cc5eb5 100644 --- a/src/snmalloc/mem/pool.h +++ b/src/snmalloc/mem/pool.h @@ -137,11 +137,8 @@ namespace snmalloc Config::Pal::error("Failed to initialise thread local allocator."); } - p = capptr_to_user_address_control( - Aal::capptr_bound( - capptr::Arena::unsafe_from(new (raw.unsafe_ptr()) - T(std::forward(args)...)), - sizeof(T))); + p = capptr::Alloc::unsafe_from(new (raw.unsafe_ptr()) + T(std::forward(args)...)); FlagLock f(pool.lock); p->list_next = pool.list; From f83ade21be87911183d9228267b463220f02012d Mon Sep 17 00:00:00 2001 From: Matthew Parkinson Date: Wed, 14 Sep 2022 10:51:55 +0100 Subject: [PATCH 3/4] Enable smallbuddyrange to handle larger requests The smallbuddy can now pass the larger requests up the range chain if it cannot satisfy it itself. --- .../backend_helpers/smallbuddyrange.h | 30 +++++++++++-------- 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/src/snmalloc/backend_helpers/smallbuddyrange.h b/src/snmalloc/backend_helpers/smallbuddyrange.h index ce540558f..2a3f3a34c 100644 --- a/src/snmalloc/backend_helpers/smallbuddyrange.h +++ b/src/snmalloc/backend_helpers/smallbuddyrange.h @@ -174,13 +174,22 @@ namespace snmalloc base, length, [this](CapPtr base, size_t align, bool) { - CapPtr overflow = - buddy_small - .add_block( - base.template as_reinterpret>(), align) - .template as_reinterpret(); - if (overflow != nullptr) - parent.dealloc_range(overflow, bits::one_at_bit(MIN_CHUNK_BITS)); + if (align < MIN_CHUNK_SIZE) + { + CapPtr overflow = + buddy_small + .add_block( + base.template as_reinterpret>(), + align) + .template as_reinterpret(); + if (overflow != nullptr) + parent.dealloc_range( + overflow, bits::one_at_bit(MIN_CHUNK_BITS)); + } + else + { + parent.dealloc_range(base, align); + } }); } @@ -204,7 +213,8 @@ namespace snmalloc CapPtr alloc_range(size_t size) { - SNMALLOC_ASSERT(size < MIN_CHUNK_SIZE); + if (size >= MIN_CHUNK_SIZE) + return parent.alloc_range(size); auto result = buddy_small.remove_block(size); if (result != nullptr) @@ -218,8 +228,6 @@ namespace snmalloc CapPtr alloc_range_with_leftover(size_t size) { - SNMALLOC_ASSERT(size < MIN_CHUNK_SIZE); - auto rsize = bits::next_pow2(size); auto result = alloc_range(rsize); @@ -236,8 +244,6 @@ namespace snmalloc void dealloc_range(CapPtr base, size_t size) { - SNMALLOC_ASSERT(size < MIN_CHUNK_SIZE); - add_range(base, size); } }; From fcc3baf728197180485e0eb1bca43129343d1512 Mon Sep 17 00:00:00 2001 From: Matthew Parkinson Date: Wed, 14 Sep 2022 10:52:28 +0100 Subject: [PATCH 4/4] Test larger requests for meta-data. --- src/test/func/pool/pool.cc | 39 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/src/test/func/pool/pool.cc b/src/test/func/pool/pool.cc index 7eaca6bcd..c94c793d9 100644 --- a/src/test/func/pool/pool.cc +++ b/src/test/func/pool/pool.cc @@ -1,3 +1,5 @@ +#include +#include #include #include #include @@ -24,6 +26,23 @@ struct PoolBEntry : Pooled using PoolB = Pool; +struct PoolLargeEntry : Pooled +{ + std::array payload; + + PoolLargeEntry() + { + printf("."); + fflush(stdout); + payload[0] = 1; + printf("first %d\n", payload[0]); + payload[1'999'999] = 1; + printf("last %d\n", payload[1'999'999]); + }; +}; + +using PoolLarge = Pool; + void test_alloc() { auto ptr = PoolA::acquire(); @@ -116,6 +135,18 @@ void test_iterator() PoolA::release(after_iteration_ptr); } +void test_large() +{ + printf("."); + fflush(stdout); + PoolLargeEntry* p = PoolLarge::acquire(); + printf("."); + fflush(stdout); + PoolLarge::release(p); + printf("."); + fflush(stdout); +} + int main(int argc, char** argv) { setup(); @@ -128,10 +159,18 @@ int main(int argc, char** argv) #endif test_alloc(); + std::cout << "test_alloc passed" << std::endl; test_constructor(); + std::cout << "test_constructor passed" << std::endl; test_alloc_many(); + std::cout << "test_alloc_many passed" << std::endl; test_double_alloc(); + std::cout << "test_double_alloc passed" << std::endl; test_different_alloc(); + std::cout << "test_different_alloc passed" << std::endl; test_iterator(); + std::cout << "test_iterator passed" << std::endl; + test_large(); + std::cout << "test_large passed" << std::endl; return 0; }