From 0766dbaf5305202c6f67e18184bb165df8426713 Mon Sep 17 00:00:00 2001 From: Aaron Green Date: Mon, 18 Nov 2024 17:48:34 +0000 Subject: [PATCH] pw_allocator: Refactor first fit allocators MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This CL merges the FirstFitBlockAllocator, LastFitBlockAllocator, and DualFirstFitBlockAllocator into a single class, which makes use of the updated Bucket types. It provides legacy aliases for existing consumers. Change-Id: I01c363236f3871b548617a5e134c19f80bf623fe Reviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/234816 Presubmit-Verified: CQ Bot Account Reviewed-by: Taylor Cramer Lint: Lint 🤖 Commit-Queue: Aaron Green --- docs/BUILD.gn | 4 +- pw_allocator/BUILD.bazel | 57 ++-- pw_allocator/BUILD.gn | 78 ++--- pw_allocator/CMakeLists.txt | 59 ++-- pw_allocator/allocator_test.cc | 22 +- pw_allocator/api.rst | 22 +- pw_allocator/benchmarks/BUILD.bazel | 6 +- pw_allocator/benchmarks/BUILD.gn | 6 +- .../benchmarks/dual_first_fit_benchmark.cc | 5 +- .../benchmarks/first_fit_benchmark.cc | 4 +- pw_allocator/benchmarks/last_fit_benchmark.cc | 6 +- pw_allocator/best_fit_block_allocator_test.cc | 12 +- pw_allocator/bucket_allocator_test.cc | 12 +- pw_allocator/code_size.rst | 4 +- .../dual_first_fit_block_allocator_test.cc | 170 ----------- pw_allocator/examples/BUILD.bazel | 6 +- pw_allocator/examples/BUILD.gn | 8 +- pw_allocator/examples/CMakeLists.txt | 2 +- pw_allocator/examples/block_allocator.cc | 4 +- pw_allocator/examples/linker_sections.cc | 6 +- pw_allocator/examples/size_report.cc | 4 +- pw_allocator/fallback_allocator_test.cc | 36 +-- .../first_fit_block_allocator_test.cc | 142 --------- pw_allocator/first_fit_test.cc | 284 ++++++++++++++++++ pw_allocator/guide.rst | 31 +- pw_allocator/last_fit_block_allocator_test.cc | 115 ------- pw_allocator/pmr_allocator_test.cc | 7 +- .../pw_allocator/block_allocator_testing.h | 12 +- .../dual_first_fit_block_allocator.h | 70 +---- pw_allocator/public/pw_allocator/first_fit.h | 90 ++++++ .../pw_allocator/first_fit_block_allocator.h | 53 +--- .../pw_allocator/last_fit_block_allocator.h | 48 +-- pw_allocator/public/pw_allocator/testing.h | 22 +- pw_allocator/size_report/BUILD.bazel | 36 +-- pw_allocator/size_report/BUILD.gn | 34 +-- .../dual_first_fit_block_allocator.cc | 29 -- .../size_report/fallback_allocator.cc | 6 +- .../size_report/fallback_allocator_base.cc | 6 +- ...st_fit_block_allocator.cc => first_fit.cc} | 5 +- .../size_report/last_fit_block_allocator.cc | 27 -- pw_allocator/size_report/pmr_allocator.cc | 4 +- .../size_report/pmr_allocator_base.cc | 4 +- .../size_report/synchronized_allocator_isl.cc | 4 +- .../synchronized_allocator_mutex.cc | 4 +- .../tracking_allocator_all_metrics.cc | 4 +- .../tracking_allocator_no_metrics.cc | 4 +- pw_allocator/tracking_allocator_test.cc | 35 +-- .../worst_fit_block_allocator_test.cc | 12 +- pw_malloc/BUILD.bazel | 74 ++--- pw_malloc/BUILD.gn | 45 +-- pw_malloc/CMakeLists.txt | 25 +- pw_malloc/dual_first_fit_block_allocator.cc | 44 --- ...st_fit_block_allocator.cc => first_fit.cc} | 10 +- pw_malloc/last_fit_block_allocator.cc | 34 --- 54 files changed, 696 insertions(+), 1157 deletions(-) delete mode 100644 pw_allocator/dual_first_fit_block_allocator_test.cc delete mode 100644 pw_allocator/first_fit_block_allocator_test.cc create mode 100644 pw_allocator/first_fit_test.cc delete mode 100644 pw_allocator/last_fit_block_allocator_test.cc create mode 100644 pw_allocator/public/pw_allocator/first_fit.h delete mode 100644 pw_allocator/size_report/dual_first_fit_block_allocator.cc rename pw_allocator/size_report/{first_fit_block_allocator.cc => first_fit.cc} (83%) delete mode 100644 pw_allocator/size_report/last_fit_block_allocator.cc delete mode 100644 pw_malloc/dual_first_fit_block_allocator.cc rename pw_malloc/{first_fit_block_allocator.cc => first_fit.cc} (74%) delete mode 100644 pw_malloc/last_fit_block_allocator.cc diff --git a/docs/BUILD.gn b/docs/BUILD.gn index cca105b51d..2afb6a29e0 100644 --- a/docs/BUILD.gn +++ b/docs/BUILD.gn @@ -179,12 +179,10 @@ _doxygen_input_files = [ # keep-sorted: start "$dir_pw_allocator/public/pw_allocator/chunk_pool.h", "$dir_pw_allocator/public/pw_allocator/config.h", "$dir_pw_allocator/public/pw_allocator/deallocator.h", - "$dir_pw_allocator/public/pw_allocator/dual_first_fit_block_allocator.h", "$dir_pw_allocator/public/pw_allocator/fallback_allocator.h", - "$dir_pw_allocator/public/pw_allocator/first_fit_block_allocator.h", + "$dir_pw_allocator/public/pw_allocator/first_fit.h", "$dir_pw_allocator/public/pw_allocator/fragmentation.h", "$dir_pw_allocator/public/pw_allocator/fuzzing.h", - "$dir_pw_allocator/public/pw_allocator/last_fit_block_allocator.h", "$dir_pw_allocator/public/pw_allocator/layout.h", "$dir_pw_allocator/public/pw_allocator/libc_allocator.h", "$dir_pw_allocator/public/pw_allocator/metrics.h", diff --git a/pw_allocator/BUILD.bazel b/pw_allocator/BUILD.bazel index 1079c81302..e134c1a95e 100644 --- a/pw_allocator/BUILD.bazel +++ b/pw_allocator/BUILD.bazel @@ -226,15 +226,12 @@ cc_library( ], ) +# TODO(b/376730645): Remove deprecated interfaces. cc_library( name = "dual_first_fit_block_allocator", hdrs = ["public/pw_allocator/dual_first_fit_block_allocator.h"], strip_include_prefix = "public", - deps = [ - ":block_allocator", - ":config", - "//pw_allocator/block:detailed_block", - ], + deps = [":first_fit"], ) cc_library( @@ -256,16 +253,25 @@ cc_library( ) cc_library( - name = "first_fit_block_allocator", - hdrs = ["public/pw_allocator/first_fit_block_allocator.h"], + name = "first_fit", + hdrs = ["public/pw_allocator/first_fit.h"], strip_include_prefix = "public", deps = [ ":block_allocator", ":config", "//pw_allocator/block:detailed_block", + "//pw_allocator/bucket:sequenced", ], ) +# TODO(b/376730645): Remove deprecated interfaces. +cc_library( + name = "first_fit_block_allocator", + hdrs = ["public/pw_allocator/first_fit_block_allocator.h"], + includes = ["public"], + deps = [":first_fit"], +) + cc_library( name = "fragmentation", srcs = ["fragmentation.cc"], @@ -287,15 +293,12 @@ cc_library( ], ) +# TODO(b/376730645): Remove deprecated interfaces. cc_library( name = "last_fit_block_allocator", hdrs = ["public/pw_allocator/last_fit_block_allocator.h"], strip_include_prefix = "public", - deps = [ - ":block_allocator", - ":config", - "//pw_allocator/block:detailed_block", - ], + deps = [":first_fit"], ) cc_library( @@ -412,10 +415,9 @@ cc_library( deps = [ ":allocator", ":buffer", - ":first_fit_block_allocator", + ":first_fit", ":test_config", ":tracking_allocator", - "//pw_allocator/block:detailed_block", "//pw_assert", "//pw_bytes", "//pw_result", @@ -580,16 +582,6 @@ pw_cc_test( ], ) -pw_cc_test( - name = "dual_first_fit_block_allocator_test", - srcs = ["dual_first_fit_block_allocator_test.cc"], - deps = [ - ":block_allocator_testing", - ":dual_first_fit_block_allocator", - "//pw_unit_test", - ], -) - pw_cc_test( name = "fallback_allocator_test", srcs = [ @@ -604,12 +596,15 @@ pw_cc_test( ) pw_cc_test( - name = "first_fit_block_allocator_test", - srcs = ["first_fit_block_allocator_test.cc"], + name = "first_fit_test", + srcs = ["first_fit_test.cc"], deps = [ ":block_allocator_testing", ":buffer", + ":dual_first_fit_block_allocator", + ":first_fit", ":first_fit_block_allocator", + ":last_fit_block_allocator", "//pw_unit_test", "//third_party/fuchsia:stdcompat", ], @@ -639,16 +634,6 @@ pw_cc_test( ], ) -pw_cc_test( - name = "last_fit_block_allocator_test", - srcs = ["last_fit_block_allocator_test.cc"], - deps = [ - ":block_allocator_testing", - ":last_fit_block_allocator", - "//pw_unit_test", - ], -) - pw_cc_test( name = "layout_test", srcs = ["layout_test.cc"], diff --git a/pw_allocator/BUILD.gn b/pw_allocator/BUILD.gn index 5ccb4a3d3e..bce1643b0d 100644 --- a/pw_allocator/BUILD.gn +++ b/pw_allocator/BUILD.gn @@ -204,14 +204,11 @@ pw_source_set("deallocator") { ] } +# TODO(b/376730645): Remove deprecated interfaces. pw_source_set("dual_first_fit_block_allocator") { public_configs = [ ":public_include_path" ] public = [ "public/pw_allocator/dual_first_fit_block_allocator.h" ] - public_deps = [ - ":block_allocator", - ":config", - "block:detailed_block", - ] + public_deps = [ ":first_fit" ] } pw_source_set("fallback_allocator") { @@ -227,16 +224,24 @@ pw_source_set("fallback_allocator") { deps = [ "$dir_pw_assert:check" ] } -pw_source_set("first_fit_block_allocator") { +pw_source_set("first_fit") { public_configs = [ ":public_include_path" ] - public = [ "public/pw_allocator/first_fit_block_allocator.h" ] + public = [ "public/pw_allocator/first_fit.h" ] public_deps = [ ":block_allocator", ":config", "block:detailed_block", + "bucket:sequenced", ] } +# TODO(b/376730645): Remove deprecated interfaces. +pw_source_set("first_fit_block_allocator") { + public_configs = [ ":public_include_path" ] + public = [ "public/pw_allocator/first_fit_block_allocator.h" ] + public_deps = [ ":first_fit" ] +} + pw_source_set("fragmentation") { public_configs = [ ":public_include_path" ] public = [ "public/pw_allocator/fragmentation.h" ] @@ -254,14 +259,11 @@ pw_source_set("freelist_heap") { ] } +# TODO(b/376730645): Remove deprecated interfaces. pw_source_set("last_fit_block_allocator") { public_configs = [ ":public_include_path" ] public = [ "public/pw_allocator/last_fit_block_allocator.h" ] - public_deps = [ - ":block_allocator", - ":config", - "block:detailed_block", - ] + public_deps = [ ":first_fit" ] } pw_source_set("libc_allocator") { @@ -350,10 +352,9 @@ pw_source_set("testing") { public_deps = [ ":allocator", ":buffer", - ":first_fit_block_allocator", + ":first_fit", ":tracking_allocator", "$dir_pw_sync:interrupt_spin_lock", - "block:detailed_block", dir_pw_bytes, dir_pw_result, dir_pw_status, @@ -473,14 +474,6 @@ pw_test("chunk_pool_test") { sources = [ "chunk_pool_test.cc" ] } -pw_test("dual_first_fit_block_allocator_test") { - deps = [ - ":block_allocator_testing", - ":dual_first_fit_block_allocator", - ] - sources = [ "dual_first_fit_block_allocator_test.cc" ] -} - pw_test("fallback_allocator_test") { deps = [ ":fallback_allocator", @@ -490,14 +483,17 @@ pw_test("fallback_allocator_test") { sources = [ "fallback_allocator_test.cc" ] } -pw_test("first_fit_block_allocator_test") { +pw_test("first_fit_test") { deps = [ ":block_allocator_testing", ":buffer", + ":dual_first_fit_block_allocator", + ":first_fit", ":first_fit_block_allocator", + ":last_fit_block_allocator", "$dir_pw_third_party/fuchsia:stdcompat", ] - sources = [ "first_fit_block_allocator_test.cc" ] + sources = [ "first_fit_test.cc" ] } pw_test("fragmentation_test") { @@ -518,14 +514,6 @@ pw_test("freelist_heap_test") { sources = [ "freelist_heap_test.cc" ] } -pw_test("last_fit_block_allocator_test") { - deps = [ - ":block_allocator_testing", - ":last_fit_block_allocator", - ] - sources = [ "last_fit_block_allocator_test.cc" ] -} - pw_test("layout_test") { deps = [ ":deallocator", @@ -623,12 +611,10 @@ pw_test_group("tests") { ":buffer_test", ":bump_allocator_test", ":chunk_pool_test", - ":dual_first_fit_block_allocator_test", ":fallback_allocator_test", - ":first_fit_block_allocator_test", + ":first_fit_test", ":fragmentation_test", ":freelist_heap_test", - ":last_fit_block_allocator_test", ":layout_test", ":libc_allocator_test", ":null_allocator_test", @@ -689,20 +675,10 @@ pw_size_diff("concrete_allocators_size_report") { label = "BumpAllocator" }, { - target = "size_report:dual_first_fit_block_allocator" - base = "size_report:null_allocator" - label = "DualFirstFitBlockAllocator" - }, - { - target = "size_report:first_fit_block_allocator" + target = "size_report:first_fit" base = "size_report:null_allocator" label = "FirstFitBlockAllocator" }, - { - target = "size_report:last_fit_block_allocator" - base = "size_report:null_allocator" - label = "LastFitBlockAllocator" - }, { target = "size_report:libc_allocator" base = "size_report:null_allocator" @@ -731,22 +707,22 @@ pw_size_diff("forwarding_allocators_size_report") { }, { target = "size_report:synchronized_allocator_isl" - base = "size_report:first_fit_block_allocator" + base = "size_report:first_fit" label = "SynchronizedAllocator" }, { target = "size_report:synchronized_allocator_mutex" - base = "size_report:first_fit_block_allocator" + base = "size_report:first_fit" label = "SynchronizedAllocator" }, { target = "size_report:tracking_allocator_all_metrics" - base = "size_report:first_fit_block_allocator" + base = "size_report:first_fit" label = "TrackingAllocator" }, { target = "size_report:tracking_allocator_no_metrics" - base = "size_report:first_fit_block_allocator" + base = "size_report:first_fit" label = "TrackingAllocator" }, ] @@ -757,7 +733,7 @@ pw_size_diff("allocator_utilities_size_report") { binaries = [ { target = "size_report:unique_ptr" - base = "size_report:first_fit_block_allocator" + base = "size_report:first_fit" label = "UniquePtr" }, ] diff --git a/pw_allocator/CMakeLists.txt b/pw_allocator/CMakeLists.txt index 8bbd4e4ad0..5e614f99d9 100644 --- a/pw_allocator/CMakeLists.txt +++ b/pw_allocator/CMakeLists.txt @@ -198,15 +198,14 @@ pw_add_library(pw_allocator.deallocator STATIC pw_status ) +# TODO(b/376730645): Remove deprecated interfaces. pw_add_library(pw_allocator.dual_first_fit_block_allocator INTERFACE HEADERS public/pw_allocator/dual_first_fit_block_allocator.h PUBLIC_INCLUDES public PUBLIC_DEPS - pw_allocator.block_allocator - pw_allocator.block.detailed_block - pw_allocator.config + pw_allocator.first_fit ) pw_add_library(pw_allocator.fallback_allocator STATIC @@ -225,15 +224,26 @@ pw_add_library(pw_allocator.fallback_allocator STATIC pw_assert.check ) -pw_add_library(pw_allocator.first_fit_block_allocator INTERFACE +pw_add_library(pw_allocator.first_fit INTERFACE HEADERS - public/pw_allocator/first_fit_block_allocator.h + public/pw_allocator/first_fit.h PUBLIC_INCLUDES public PUBLIC_DEPS pw_allocator.block_allocator - pw_allocator.block.detailed_block pw_allocator.config + pw_allocator.block.detailed_block + pw_allocator.bucket.sequenced +) + +# TODO(b/376730645): Remove deprecated interfaces. +pw_add_library(pw_allocator.first_fit_block_allocator INTERFACE + HEADERS + public/pw_allocator/first_fit_block_allocator.h + PUBLIC_INCLUDES + public + PUBLIC_DEPS + pw_allocator.first_fit ) pw_add_library(pw_allocator.fragmentation STATIC @@ -257,15 +267,14 @@ pw_add_library(pw_allocator.freelist_heap INTERFACE pw_preprocessor ) +# TODO(b/376730645): Remove deprecated interfaces. pw_add_library(pw_allocator.last_fit_block_allocator INTERFACE HEADERS public/pw_allocator/last_fit_block_allocator.h PUBLIC_INCLUDES public PUBLIC_DEPS - pw_allocator.block_allocator - pw_allocator.block.detailed_block - pw_allocator.config + pw_allocator.first_fit ) pw_add_library(pw_allocator.libc_allocator STATIC @@ -367,8 +376,7 @@ pw_add_library(pw_allocator.testing INTERFACE PUBLIC_DEPS pw_allocator.allocator pw_allocator.buffer - pw_allocator.block.detailed_block - pw_allocator.first_fit_block_allocator + pw_allocator.first_fit pw_allocator.test_config pw_allocator.tracking_allocator pw_bytes @@ -522,17 +530,6 @@ pw_add_test(pw_allocator.chunk_pool_test pw_allocator ) -pw_add_test(pw_allocator.dual_first_fit_block_allocator_test - SOURCES - dual_first_fit_block_allocator_test.cc - PRIVATE_DEPS - pw_allocator.block_allocator_testing - pw_allocator.dual_first_fit_block_allocator - GROUPS - modules - pw_allocator -) - pw_add_test(pw_allocator.fallback_allocator_test PRIVATE_DEPS pw_allocator.testing @@ -545,13 +542,16 @@ pw_add_test(pw_allocator.fallback_allocator_test pw_allocator ) -pw_add_test(pw_allocator.first_fit_block_allocator_test +pw_add_test(pw_allocator.first_fit_test SOURCES - first_fit_block_allocator_test.cc + first_fit_test.cc PRIVATE_DEPS pw_allocator.block_allocator_testing pw_allocator.buffer + pw_allocator.dual_first_fit_block_allocator + pw_allocator.first_fit pw_allocator.first_fit_block_allocator + pw_allocator.last_fit_block_allocator pw_third_party.fuchsia.stdcompat GROUPS modules @@ -594,17 +594,6 @@ pw_add_test(pw_allocator.layout_test pw_allocator ) -pw_add_test(pw_allocator.last_fit_block_allocator_test - SOURCES - last_fit_block_allocator_test.cc - PRIVATE_DEPS - pw_allocator.block_allocator_testing - pw_allocator.last_fit_block_allocator - GROUPS - modules - pw_allocator -) - pw_add_test(pw_allocator.libc_allocator_test SOURCES libc_allocator_test.cc diff --git a/pw_allocator/allocator_test.cc b/pw_allocator/allocator_test.cc index bc5bcf9c69..77aff1a2f6 100644 --- a/pw_allocator/allocator_test.cc +++ b/pw_allocator/allocator_test.cc @@ -25,6 +25,8 @@ namespace { using ::pw::allocator::Capability; using ::pw::allocator::Layout; using AllocatorForTest = ::pw::allocator::test::AllocatorForTest<256>; +using BlockType = AllocatorForTest::BlockType; +static_assert(sizeof(uintptr_t) == BlockType::kAlignment); TEST(AllocatorTest, HasFlags) { AllocatorForTest allocator; @@ -35,12 +37,12 @@ TEST(AllocatorTest, HasFlags) { TEST(AllocatorTest, ResizeNull) { AllocatorForTest allocator; - EXPECT_FALSE(allocator.Resize(nullptr, sizeof(uint32_t))); + EXPECT_FALSE(allocator.Resize(nullptr, sizeof(uintptr_t))); } TEST(AllocatorTest, ResizeZero) { AllocatorForTest allocator; - constexpr Layout layout = Layout::Of(); + constexpr Layout layout = Layout::Of(); void* ptr = allocator.Allocate(layout); ASSERT_NE(ptr, nullptr); EXPECT_FALSE(allocator.Resize(ptr, 0)); @@ -48,7 +50,7 @@ TEST(AllocatorTest, ResizeZero) { TEST(AllocatorTest, ResizeSame) { AllocatorForTest allocator; - constexpr Layout layout = Layout::Of(); + constexpr Layout layout = Layout::Of(); void* ptr = allocator.Allocate(layout); ASSERT_NE(ptr, nullptr); EXPECT_TRUE(allocator.Resize(ptr, layout.size())); @@ -59,7 +61,7 @@ TEST(AllocatorTest, ResizeSame) { TEST(AllocatorTest, ReallocateNull) { AllocatorForTest allocator; - constexpr Layout old_layout = Layout::Of(); + constexpr Layout old_layout = Layout::Of(); constexpr Layout new_layout(old_layout.size(), old_layout.alignment()); void* new_ptr = allocator.Reallocate(nullptr, new_layout); @@ -76,7 +78,7 @@ TEST(AllocatorTest, ReallocateNull) { TEST(AllocatorTest, ReallocateZeroNewSize) { AllocatorForTest allocator; - constexpr Layout old_layout = Layout::Of(); + constexpr Layout old_layout = Layout::Of(); void* ptr = allocator.Allocate(old_layout); ASSERT_EQ(allocator.allocate_size(), old_layout.size()); ASSERT_NE(ptr, nullptr); @@ -99,7 +101,7 @@ TEST(AllocatorTest, ReallocateZeroNewSize) { TEST(AllocatorTest, ReallocateSame) { AllocatorForTest allocator; - constexpr Layout layout = Layout::Of(); + constexpr Layout layout = Layout::Of(); void* ptr = allocator.Allocate(layout); ASSERT_EQ(allocator.allocate_size(), layout.size()); ASSERT_NE(ptr, nullptr); @@ -125,13 +127,13 @@ TEST(AllocatorTest, ReallocateSame) { TEST(AllocatorTest, ReallocateSmaller) { AllocatorForTest allocator; - constexpr Layout old_layout = Layout::Of(); + constexpr Layout old_layout = Layout::Of(); void* ptr = allocator.Allocate(old_layout); ASSERT_EQ(allocator.allocate_size(), old_layout.size()); ASSERT_NE(ptr, nullptr); allocator.ResetParameters(); - constexpr Layout new_layout(sizeof(uint32_t), old_layout.alignment()); + constexpr Layout new_layout(sizeof(uintptr_t), old_layout.alignment()); void* new_ptr = allocator.Reallocate(ptr, new_layout); // Reallocate should call Resize. @@ -152,7 +154,7 @@ TEST(AllocatorTest, ReallocateSmaller) { TEST(AllocatorTest, ReallocateLarger) { AllocatorForTest allocator; - constexpr Layout old_layout = Layout::Of(); + constexpr Layout old_layout = Layout::Of(); void* ptr = allocator.Allocate(old_layout); ASSERT_EQ(allocator.allocate_size(), old_layout.size()); ASSERT_NE(ptr, nullptr); @@ -166,7 +168,7 @@ TEST(AllocatorTest, ReallocateLarger) { ASSERT_NE(next, nullptr); allocator.ResetParameters(); - constexpr Layout new_layout(sizeof(uint32_t[3]), old_layout.alignment()); + constexpr Layout new_layout(sizeof(uintptr_t[3]), old_layout.alignment()); void* new_ptr = allocator.Reallocate(ptr, new_layout); // Reallocate should call Resize. diff --git a/pw_allocator/api.rst b/pw_allocator/api.rst index 091e1af053..59efaf9043 100644 --- a/pw_allocator/api.rst +++ b/pw_allocator/api.rst @@ -99,18 +99,11 @@ BlockAllocator .. doxygenclass:: pw::allocator::BlockAllocator :members: -.. _module-pw_allocator-api-first_fit_block_allocator: +.. _module-pw_allocator-api-first_fit_allocator: -FirstFitBlockAllocator ----------------------- -.. doxygenclass:: pw::allocator::FirstFitBlockAllocator - :members: - -.. _module-pw_allocator-api-last_fit_block_allocator: - -LastFitBlockAllocator ---------------------- -.. doxygenclass:: pw::allocator::LastFitBlockAllocator +FirstFitAllocator +----------------- +.. doxygenclass:: pw::allocator::FirstFitAllocator :members: .. _module-pw_allocator-api-best_fit_block_allocator: @@ -127,13 +120,6 @@ WorstFitBlockAllocator .. doxygenclass:: pw::allocator::WorstFitBlockAllocator :members: -.. _module-pw_allocator-api-dual_first_fit_block_allocator: - -DualFirstFitBlockAllocator --------------------------- -.. doxygenclass:: pw::allocator::DualFirstFitBlockAllocator - :members: - .. _module-pw_allocator-api-bucket_block_allocator: BucketAllocator diff --git a/pw_allocator/benchmarks/BUILD.bazel b/pw_allocator/benchmarks/BUILD.bazel index 5205ec1aa6..0b87c8e31a 100644 --- a/pw_allocator/benchmarks/BUILD.bazel +++ b/pw_allocator/benchmarks/BUILD.bazel @@ -89,7 +89,7 @@ cc_binary( ], deps = [ ":benchmark", - "//pw_allocator:dual_first_fit_block_allocator", + "//pw_allocator:first_fit", "//pw_random", ], ) @@ -102,7 +102,7 @@ cc_binary( ], deps = [ ":benchmark", - "//pw_allocator:first_fit_block_allocator", + "//pw_allocator:first_fit", "//pw_random", ], ) @@ -115,7 +115,7 @@ cc_binary( ], deps = [ ":benchmark", - "//pw_allocator:last_fit_block_allocator", + "//pw_allocator:first_fit", "//pw_random", ], ) diff --git a/pw_allocator/benchmarks/BUILD.gn b/pw_allocator/benchmarks/BUILD.gn index 7e806274b4..bfcd6d3fa0 100644 --- a/pw_allocator/benchmarks/BUILD.gn +++ b/pw_allocator/benchmarks/BUILD.gn @@ -79,7 +79,7 @@ pw_executable("dual_first_fit_benchmark") { sources = [ "dual_first_fit_benchmark.cc" ] deps = [ ":benchmark", - "$dir_pw_allocator:dual_first_fit_block_allocator", + "$dir_pw_allocator:first_fit", "$dir_pw_random", ] } @@ -88,7 +88,7 @@ pw_executable("first_fit_benchmark") { sources = [ "first_fit_benchmark.cc" ] deps = [ ":benchmark", - "$dir_pw_allocator:first_fit_block_allocator", + "$dir_pw_allocator:first_fit", "$dir_pw_random", ] } @@ -97,7 +97,7 @@ pw_executable("last_fit_benchmark") { sources = [ "last_fit_benchmark.cc" ] deps = [ ":benchmark", - "$dir_pw_allocator:last_fit_block_allocator", + "$dir_pw_allocator:first_fit", "$dir_pw_random", ] } diff --git a/pw_allocator/benchmarks/dual_first_fit_benchmark.cc b/pw_allocator/benchmarks/dual_first_fit_benchmark.cc index a914eda7ff..97a9ee3c7a 100644 --- a/pw_allocator/benchmarks/dual_first_fit_benchmark.cc +++ b/pw_allocator/benchmarks/dual_first_fit_benchmark.cc @@ -18,7 +18,7 @@ #include "pw_allocator/benchmarks/benchmark.h" #include "pw_allocator/benchmarks/config.h" -#include "pw_allocator/dual_first_fit_block_allocator.h" +#include "pw_allocator/first_fit.h" namespace pw::allocator { @@ -28,7 +28,8 @@ constexpr metric::Token kDualFirstFitBenchmark = std::array buffer; void DoDualFirstFitBenchmark() { - DualFirstFitBlockAllocator allocator(buffer, benchmarks::kMaxSize / 2); + FirstFitAllocator allocator(buffer); + allocator.set_threshold(benchmarks::kMaxSize / 2); DefaultBlockAllocatorBenchmark benchmark(kDualFirstFitBenchmark, allocator); benchmark.set_prng_seed(1); benchmark.set_available(benchmarks::kCapacity); diff --git a/pw_allocator/benchmarks/first_fit_benchmark.cc b/pw_allocator/benchmarks/first_fit_benchmark.cc index 00bdf11308..703075fd2c 100644 --- a/pw_allocator/benchmarks/first_fit_benchmark.cc +++ b/pw_allocator/benchmarks/first_fit_benchmark.cc @@ -18,7 +18,7 @@ #include "pw_allocator/benchmarks/benchmark.h" #include "pw_allocator/benchmarks/config.h" -#include "pw_allocator/first_fit_block_allocator.h" +#include "pw_allocator/first_fit.h" namespace pw::allocator { @@ -28,7 +28,7 @@ constexpr metric::Token kFirstFitBenchmark = std::array buffer; void DoFirstFitBenchmark() { - FirstFitBlockAllocator allocator(buffer); + FirstFitAllocator allocator(buffer); DefaultBlockAllocatorBenchmark benchmark(kFirstFitBenchmark, allocator); benchmark.set_prng_seed(1); benchmark.set_available(benchmarks::kCapacity); diff --git a/pw_allocator/benchmarks/last_fit_benchmark.cc b/pw_allocator/benchmarks/last_fit_benchmark.cc index aa3116c8ab..caf39a96db 100644 --- a/pw_allocator/benchmarks/last_fit_benchmark.cc +++ b/pw_allocator/benchmarks/last_fit_benchmark.cc @@ -15,10 +15,11 @@ #include #include #include +#include #include "pw_allocator/benchmarks/benchmark.h" #include "pw_allocator/benchmarks/config.h" -#include "pw_allocator/last_fit_block_allocator.h" +#include "pw_allocator/first_fit.h" namespace pw::allocator { @@ -28,7 +29,8 @@ constexpr metric::Token kLastFitBenchmark = std::array buffer; void DoLastFitBenchmark() { - LastFitBlockAllocator allocator(buffer); + FirstFitAllocator allocator(buffer); + allocator.set_threshold(std::numeric_limits::max()); DefaultBlockAllocatorBenchmark benchmark(kLastFitBenchmark, allocator); benchmark.set_prng_seed(1); benchmark.set_available(benchmarks::kCapacity); diff --git a/pw_allocator/best_fit_block_allocator_test.cc b/pw_allocator/best_fit_block_allocator_test.cc index 64db3ee9ec..c57709d139 100644 --- a/pw_allocator/best_fit_block_allocator_test.cc +++ b/pw_allocator/best_fit_block_allocator_test.cc @@ -37,14 +37,14 @@ class BestFitBlockAllocatorTest : public BlockAllocatorTest { // Unit tests. -TEST_F(BestFitBlockAllocatorTest, CanAutomaticallyInit) { +TEST_F(BestFitBlockAllocatorTest, AutomaticallyInit) { BestFitBlockAllocator allocator(GetBytes()); - CanAutomaticallyInit(allocator); + AutomaticallyInit(allocator); } -TEST_F(BestFitBlockAllocatorTest, CanExplicitlyInit) { +TEST_F(BestFitBlockAllocatorTest, ExplicitlyInit) { BestFitBlockAllocator allocator; - CanExplicitlyInit(allocator); + ExplicitlyInit(allocator); } TEST_F(BestFitBlockAllocatorTest, GetCapacity) { GetCapacity(); } @@ -115,8 +115,8 @@ TEST_F(BestFitBlockAllocatorTest, ResizeSmallLargerFailure) { ResizeSmallLargerFailure(); } -TEST_F(BestFitBlockAllocatorTest, CanMeasureFragmentation) { - CanMeasureFragmentation(); +TEST_F(BestFitBlockAllocatorTest, MeasureFragmentation) { + MeasureFragmentation(); } TEST_F(BestFitBlockAllocatorTest, PoisonPeriodically) { PoisonPeriodically(); } diff --git a/pw_allocator/bucket_allocator_test.cc b/pw_allocator/bucket_allocator_test.cc index dfdd0a04a4..0f3fc69734 100644 --- a/pw_allocator/bucket_allocator_test.cc +++ b/pw_allocator/bucket_allocator_test.cc @@ -43,14 +43,14 @@ class BucketAllocatorTest : public BlockAllocatorTest { // Unit tests. -TEST_F(BucketAllocatorTest, CanAutomaticallyInit) { +TEST_F(BucketAllocatorTest, AutomaticallyInit) { BucketAllocator allocator(GetBytes()); - CanAutomaticallyInit(allocator); + AutomaticallyInit(allocator); } -TEST_F(BucketAllocatorTest, CanExplicitlyInit) { +TEST_F(BucketAllocatorTest, ExplicitlyInit) { BucketAllocator allocator; - CanExplicitlyInit(allocator); + ExplicitlyInit(allocator); } TEST_F(BucketAllocatorTest, GetCapacity) { GetCapacity(); } @@ -205,9 +205,7 @@ TEST_F(BucketAllocatorTest, ResizeSmallLargerFailure) { ResizeSmallLargerFailure(); } -TEST_F(BucketAllocatorTest, CanMeasureFragmentation) { - CanMeasureFragmentation(); -} +TEST_F(BucketAllocatorTest, MeasureFragmentation) { MeasureFragmentation(); } TEST_F(BucketAllocatorTest, PoisonPeriodically) { PoisonPeriodically(); } diff --git a/pw_allocator/code_size.rst b/pw_allocator/code_size.rst index 0e0920ab06..71f1c3fb69 100644 --- a/pw_allocator/code_size.rst +++ b/pw_allocator/code_size.rst @@ -36,7 +36,7 @@ Forwarding allocators implementations The following are code sizes for each of the provided "forwarding" allocators as described by :ref:`module-pw_allocator-design-forwarding`. These are measured by having the forwarding allocator wrap a -:ref:`module-pw_allocator-api-first_fit_block_allocator`, and are measured -relative to that implementation. +:ref:`module-pw_allocator-api-first_fit_allocator`, and are measured relative to +that implementation. .. include:: forwarding_allocators_size_report diff --git a/pw_allocator/dual_first_fit_block_allocator_test.cc b/pw_allocator/dual_first_fit_block_allocator_test.cc deleted file mode 100644 index e28ece67fa..0000000000 --- a/pw_allocator/dual_first_fit_block_allocator_test.cc +++ /dev/null @@ -1,170 +0,0 @@ -// Copyright 2024 The Pigweed Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); you may not -// use this file except in compliance with the License. You may obtain a copy of -// the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -// License for the specific language governing permissions and limitations under -// the License. - -#include "pw_allocator/dual_first_fit_block_allocator.h" - -#include "pw_allocator/block_allocator_testing.h" -#include "pw_unit_test/framework.h" - -namespace { - -// Test fixtures. - -using ::pw::allocator::Layout; -using ::pw::allocator::test::Preallocation; -using DualFirstFitBlockAllocator = - ::pw::allocator::DualFirstFitBlockAllocator; -using BlockAllocatorTest = - ::pw::allocator::test::BlockAllocatorTest; - -// Minimum size of a "large" allocation; allocation less than this size are -// considered "small" when using the DualFirstFit strategy. -static constexpr size_t kDualFitThreshold = - BlockAllocatorTest::kSmallInnerSize * 2; - -class DualFirstFitBlockAllocatorTest : public BlockAllocatorTest { - public: - DualFirstFitBlockAllocatorTest() : BlockAllocatorTest(allocator_) {} - - private: - DualFirstFitBlockAllocator allocator_; -}; - -// Unit tests. - -TEST_F(DualFirstFitBlockAllocatorTest, CanAutomaticallyInit) { - DualFirstFitBlockAllocator allocator(GetBytes(), kDualFitThreshold); - CanAutomaticallyInit(allocator); -} - -TEST_F(DualFirstFitBlockAllocatorTest, CanExplicitlyInit) { - DualFirstFitBlockAllocator allocator; - CanExplicitlyInit(allocator); -} - -TEST_F(DualFirstFitBlockAllocatorTest, GetCapacity) { GetCapacity(); } - -TEST_F(DualFirstFitBlockAllocatorTest, AllocateLarge) { AllocateLarge(); } - -TEST_F(DualFirstFitBlockAllocatorTest, AllocateSmall) { AllocateSmall(); } - -TEST_F(DualFirstFitBlockAllocatorTest, AllocateLargeAlignment) { - AllocateLargeAlignment(); -} - -TEST_F(DualFirstFitBlockAllocatorTest, AllocateAlignmentFailure) { - AllocateAlignmentFailure(); -} - -TEST_F(DualFirstFitBlockAllocatorTest, AllocatesUsingThreshold) { - auto& allocator = GetAllocator({ - {kLargeOuterSize, Preallocation::kFree}, - {kSmallerOuterSize, Preallocation::kUsed}, - {kSmallOuterSize, Preallocation::kFree}, - {Preallocation::kSizeRemaining, Preallocation::kUsed}, - {kLargeOuterSize, Preallocation::kFree}, - {kSmallerOuterSize, Preallocation::kUsed}, - {kSmallOuterSize, Preallocation::kFree}, - }); - auto& dual_first_fit_block_allocator = - static_cast(allocator); - dual_first_fit_block_allocator.set_threshold(kDualFitThreshold); - - Store(0, allocator.Allocate(Layout(kLargeInnerSize, 1))); - EXPECT_EQ(NextAfter(0), Fetch(1)); - Store(4, allocator.Allocate(Layout(kLargeInnerSize, 1))); - EXPECT_EQ(NextAfter(3), Fetch(4)); - EXPECT_EQ(NextAfter(4), Fetch(5)); - Store(6, allocator.Allocate(Layout(kSmallInnerSize, 1))); - EXPECT_EQ(NextAfter(5), Fetch(6)); - EXPECT_EQ(NextAfter(6), Fetch(7)); - Store(2, allocator.Allocate(Layout(kSmallInnerSize, 1))); - EXPECT_EQ(NextAfter(1), Fetch(2)); - EXPECT_EQ(NextAfter(2), Fetch(3)); -} - -TEST_F(DualFirstFitBlockAllocatorTest, DeallocateNull) { DeallocateNull(); } - -TEST_F(DualFirstFitBlockAllocatorTest, DeallocateShuffled) { - DeallocateShuffled(); -} - -TEST_F(DualFirstFitBlockAllocatorTest, IterateOverBlocks) { - IterateOverBlocks(); -} - -TEST_F(DualFirstFitBlockAllocatorTest, ResizeNull) { ResizeNull(); } - -TEST_F(DualFirstFitBlockAllocatorTest, ResizeLargeSame) { ResizeLargeSame(); } - -TEST_F(DualFirstFitBlockAllocatorTest, ResizeLargeSmaller) { - ResizeLargeSmaller(); -} - -TEST_F(DualFirstFitBlockAllocatorTest, ResizeLargeLarger) { - ResizeLargeLarger(); -} - -TEST_F(DualFirstFitBlockAllocatorTest, ResizeLargeLargerFailure) { - ResizeLargeLargerFailure(); -} - -TEST_F(DualFirstFitBlockAllocatorTest, ResizeSmallSame) { ResizeSmallSame(); } - -TEST_F(DualFirstFitBlockAllocatorTest, ResizeSmallSmaller) { - ResizeSmallSmaller(); -} - -TEST_F(DualFirstFitBlockAllocatorTest, ResizeSmallLarger) { - ResizeSmallLarger(); -} - -TEST_F(DualFirstFitBlockAllocatorTest, ResizeSmallLargerFailure) { - ResizeSmallLargerFailure(); -} - -TEST_F(DualFirstFitBlockAllocatorTest, ResizeLargeSmallerAcrossThreshold) { - auto& allocator = GetAllocator({ - {kDualFitThreshold * 2, Preallocation::kUsed}, - {Preallocation::kSizeRemaining, Preallocation::kUsed}, - }); - // Shrinking succeeds, and the pointer is unchanged even though it is now - // below the threshold. - size_t new_size = kDualFitThreshold / 2; - ASSERT_TRUE(allocator.Resize(Fetch(0), new_size)); - UseMemory(Fetch(0), kDualFitThreshold / 2); -} - -TEST_F(DualFirstFitBlockAllocatorTest, ResizeSmallLargerAcrossThreshold) { - auto& allocator = GetAllocator({ - {Preallocation::kSizeRemaining, Preallocation::kUsed}, - {kDualFitThreshold / 2, Preallocation::kUsed}, - {kDualFitThreshold * 2, Preallocation::kFree}, - }); - // Growing succeeds, and the pointer is unchanged even though it is now - // above the threshold. - size_t new_size = kDualFitThreshold * 2; - ASSERT_TRUE(allocator.Resize(Fetch(1), new_size)); - UseMemory(Fetch(1), kDualFitThreshold * 2); -} - -TEST_F(DualFirstFitBlockAllocatorTest, CanMeasureFragmentation) { - CanMeasureFragmentation(); -} - -TEST_F(DualFirstFitBlockAllocatorTest, PoisonPeriodically) { - PoisonPeriodically(); -} - -} // namespace diff --git a/pw_allocator/examples/BUILD.bazel b/pw_allocator/examples/BUILD.bazel index 4d12612081..729800aa94 100644 --- a/pw_allocator/examples/BUILD.bazel +++ b/pw_allocator/examples/BUILD.bazel @@ -74,7 +74,7 @@ pw_cc_test( srcs = ["block_allocator.cc"], deps = [ ":named_u32", - "//pw_allocator:last_fit_block_allocator", + "//pw_allocator:first_fit", ], ) @@ -108,7 +108,7 @@ pw_cc_test( deps = [ ":named_u32", "//pw_allocator:allocator", - "//pw_allocator:first_fit_block_allocator", + "//pw_allocator:first_fit", "//pw_allocator:worst_fit_block_allocator", ], ) @@ -140,7 +140,7 @@ pw_cc_binary( srcs = ["size_report.cc"], deps = [ ":custom_allocator", - "//pw_allocator:first_fit_block_allocator", + "//pw_allocator:first_fit", "//pw_allocator:size_reporter", ], ) diff --git a/pw_allocator/examples/BUILD.gn b/pw_allocator/examples/BUILD.gn index 814d4ad477..7f28c504d3 100644 --- a/pw_allocator/examples/BUILD.gn +++ b/pw_allocator/examples/BUILD.gn @@ -70,7 +70,7 @@ pw_test("basic") { pw_test("block_allocator") { deps = [ ":named_u32", - "$dir_pw_allocator:last_fit_block_allocator", + "$dir_pw_allocator:first_fit", ] sources = [ "block_allocator.cc" ] } @@ -102,7 +102,7 @@ pw_test("linker_sections") { deps = [ ":named_u32", "$dir_pw_allocator:allocator", - "$dir_pw_allocator:first_fit_block_allocator", + "$dir_pw_allocator:first_fit", "$dir_pw_allocator:worst_fit_block_allocator", ] sources = [ "linker_sections.cc" ] @@ -131,7 +131,7 @@ pw_executable("size_report") { sources = [ "size_report.cc" ] deps = [ ":custom_allocator", - "$dir_pw_allocator:first_fit_block_allocator", + "$dir_pw_allocator:first_fit", "$dir_pw_allocator:size_reporter", ] } @@ -170,7 +170,7 @@ pw_size_diff("custom_allocator_size_report") { binaries = [ { target = ":size_report" - base = "$dir_pw_allocator/size_report:first_fit_block_allocator" + base = "$dir_pw_allocator/size_report:first_fit" label = "CustomAllocator" }, ] diff --git a/pw_allocator/examples/CMakeLists.txt b/pw_allocator/examples/CMakeLists.txt index 90741c9654..a07a83e118 100644 --- a/pw_allocator/examples/CMakeLists.txt +++ b/pw_allocator/examples/CMakeLists.txt @@ -68,7 +68,7 @@ pw_add_test(pw_allocator.examples.basic pw_add_test(pw_allocator.examples.block_allocator PRIVATE_DEPS pw_allocator.examples.named_u32 - pw_allocator.last_fit_block_allocator + pw_allocator.first_fit SOURCES block_allocator.cc ) diff --git a/pw_allocator/examples/block_allocator.cc b/pw_allocator/examples/block_allocator.cc index c3ba14e2e7..9a3b88288a 100644 --- a/pw_allocator/examples/block_allocator.cc +++ b/pw_allocator/examples/block_allocator.cc @@ -16,7 +16,7 @@ #include #include "examples/named_u32.h" -#include "pw_allocator/last_fit_block_allocator.h" +#include "pw_allocator/first_fit.h" #include "pw_unit_test/framework.h" namespace examples { @@ -24,7 +24,7 @@ namespace examples { std::array buffer; // DOCSTAG: [pw_allocator-examples-block_allocator-poison] -pw::allocator::LastFitBlockAllocator allocator(buffer); +pw::allocator::FirstFitAllocator<> allocator(buffer); // DOCSTAG: [pw_allocator-examples-block_allocator-poison] // DOCSTAG: [pw_allocator-examples-block_allocator-layout_of] diff --git a/pw_allocator/examples/linker_sections.cc b/pw_allocator/examples/linker_sections.cc index 369652b474..7a3a8cdcef 100644 --- a/pw_allocator/examples/linker_sections.cc +++ b/pw_allocator/examples/linker_sections.cc @@ -18,7 +18,8 @@ #include "examples/named_u32.h" #include "pw_allocator/allocator.h" -#include "pw_allocator/first_fit_block_allocator.h" +#include "pw_allocator/block/detailed_block.h" +#include "pw_allocator/first_fit.h" #include "pw_allocator/worst_fit_block_allocator.h" #include "pw_unit_test/framework.h" @@ -49,7 +50,8 @@ class NamedU32Factory { // DOCSTAG: [pw_allocator-examples-linker_sections-placement] // Set up an object that allocates from SRAM memory. PW_PLACE_IN_SECTION(".sram") std::array sram_buffer; -pw::allocator::FirstFitBlockAllocator sram_allocator(sram_buffer); +using SramBlock = ::pw::allocator::FirstFitBlock; +pw::allocator::FirstFitAllocator sram_allocator(sram_buffer); NamedU32Factory sram_factory(sram_allocator); // Set up an object that allocates from PSRAM memory. diff --git a/pw_allocator/examples/size_report.cc b/pw_allocator/examples/size_report.cc index 0c3d037c9d..8bfc977bcb 100644 --- a/pw_allocator/examples/size_report.cc +++ b/pw_allocator/examples/size_report.cc @@ -16,14 +16,14 @@ #include #include "examples/custom_allocator.h" -#include "pw_allocator/first_fit_block_allocator.h" +#include "pw_allocator/first_fit.h" #include "pw_allocator/size_reporter.h" int main() { pw::allocator::SizeReporter reporter; reporter.SetBaseline(); - pw::allocator::FirstFitBlockAllocator<> allocator(reporter.buffer()); + pw::allocator::FirstFitAllocator<> allocator(reporter.buffer()); examples::CustomAllocator custom(allocator, 128); reporter.Measure(custom); diff --git a/pw_allocator/fallback_allocator_test.cc b/pw_allocator/fallback_allocator_test.cc index c1133e6797..d724f2564f 100644 --- a/pw_allocator/fallback_allocator_test.cc +++ b/pw_allocator/fallback_allocator_test.cc @@ -14,6 +14,7 @@ #include "pw_allocator/fallback_allocator.h" +#include "pw_allocator/block/basic.h" #include "pw_allocator/testing.h" #include "pw_status/status.h" #include "pw_unit_test/framework.h" @@ -29,6 +30,7 @@ using ::pw::allocator::test::AllocatorForTest; class FallbackAllocatorTest : public ::testing::Test { protected: constexpr static size_t kCapacity = 256; + static_assert(sizeof(uintptr_t) >= AllocatorForTest::kMinSize); FallbackAllocatorTest() : allocator_(primary_, secondary_) {} @@ -46,7 +48,7 @@ TEST_F(FallbackAllocatorTest, GetCapacity) { } TEST_F(FallbackAllocatorTest, AllocateFromPrimary) { - Layout layout = Layout::Of(); + Layout layout = Layout::Of(); void* ptr = allocator_.Allocate(layout); EXPECT_NE(ptr, nullptr); EXPECT_EQ(primary_.allocate_size(), layout.size()); @@ -55,7 +57,7 @@ TEST_F(FallbackAllocatorTest, AllocateFromPrimary) { TEST_F(FallbackAllocatorTest, AllocateFromSecondary) { primary_.Exhaust(); - Layout layout = Layout::Of(); + Layout layout = Layout::Of(); void* ptr = allocator_.Allocate(layout); EXPECT_NE(ptr, nullptr); EXPECT_EQ(primary_.allocate_size(), layout.size()); @@ -63,7 +65,7 @@ TEST_F(FallbackAllocatorTest, AllocateFromSecondary) { } TEST_F(FallbackAllocatorTest, AllocateFailure) { - Layout layout = Layout::Of(); + Layout layout = Layout::Of(); void* ptr = allocator_.Allocate(layout); EXPECT_EQ(ptr, nullptr); EXPECT_EQ(primary_.allocate_size(), layout.size()); @@ -71,7 +73,7 @@ TEST_F(FallbackAllocatorTest, AllocateFailure) { } TEST_F(FallbackAllocatorTest, DeallocateUsingPrimary) { - Layout layout = Layout::Of(); + Layout layout = Layout::Of(); void* ptr = allocator_.Allocate(layout); ASSERT_NE(ptr, nullptr); allocator_.Deallocate(ptr); @@ -83,7 +85,7 @@ TEST_F(FallbackAllocatorTest, DeallocateUsingPrimary) { TEST_F(FallbackAllocatorTest, DeallocateUsingSecondary) { primary_.Exhaust(); - Layout layout = Layout::Of(); + Layout layout = Layout::Of(); void* ptr = allocator_.Allocate(layout); ASSERT_NE(ptr, nullptr); allocator_.Deallocate(ptr); @@ -94,11 +96,11 @@ TEST_F(FallbackAllocatorTest, DeallocateUsingSecondary) { } TEST_F(FallbackAllocatorTest, ResizePrimary) { - Layout old_layout = Layout::Of(); + Layout old_layout = Layout::Of(); void* ptr = allocator_.Allocate(old_layout); ASSERT_NE(ptr, nullptr); - size_t new_size = sizeof(uint32_t[3]); + size_t new_size = sizeof(uintptr_t[3]); EXPECT_TRUE(allocator_.Resize(ptr, new_size)); EXPECT_EQ(primary_.resize_ptr(), ptr); EXPECT_EQ(primary_.resize_old_size(), old_layout.size()); @@ -111,12 +113,12 @@ TEST_F(FallbackAllocatorTest, ResizePrimary) { } TEST_F(FallbackAllocatorTest, ResizePrimaryFailure) { - Layout old_layout = Layout::Of(); + Layout old_layout = Layout::Of(); void* ptr = allocator_.Allocate(old_layout); ASSERT_NE(ptr, nullptr); primary_.Exhaust(); - size_t new_size = sizeof(uint32_t[3]); + size_t new_size = sizeof(uintptr_t[3]); EXPECT_FALSE(allocator_.Resize(ptr, new_size)); EXPECT_EQ(primary_.resize_ptr(), ptr); EXPECT_EQ(primary_.resize_old_size(), old_layout.size()); @@ -130,11 +132,11 @@ TEST_F(FallbackAllocatorTest, ResizePrimaryFailure) { TEST_F(FallbackAllocatorTest, ResizeSecondary) { primary_.Exhaust(); - Layout old_layout = Layout::Of(); + Layout old_layout = Layout::Of(); void* ptr = allocator_.Allocate(old_layout); ASSERT_NE(ptr, nullptr); - size_t new_size = sizeof(uint32_t[3]); + size_t new_size = sizeof(uintptr_t[3]); EXPECT_TRUE(allocator_.Resize(ptr, new_size)); EXPECT_EQ(secondary_.resize_ptr(), ptr); EXPECT_EQ(secondary_.resize_old_size(), old_layout.size()); @@ -148,12 +150,12 @@ TEST_F(FallbackAllocatorTest, ResizeSecondary) { TEST_F(FallbackAllocatorTest, ResizeSecondaryFailure) { primary_.Exhaust(); - Layout old_layout = Layout::Of(); + Layout old_layout = Layout::Of(); void* ptr = allocator_.Allocate(old_layout); ASSERT_NE(ptr, nullptr); secondary_.Exhaust(); - size_t new_size = sizeof(uint32_t[3]); + size_t new_size = sizeof(uintptr_t[3]); EXPECT_FALSE(allocator_.Resize(ptr, new_size)); EXPECT_EQ(secondary_.resize_ptr(), ptr); EXPECT_EQ(secondary_.resize_old_size(), old_layout.size()); @@ -166,7 +168,7 @@ TEST_F(FallbackAllocatorTest, ResizeSecondaryFailure) { } TEST_F(FallbackAllocatorTest, ReallocateSameAllocator) { - Layout old_layout = Layout::Of(); + Layout old_layout = Layout::Of(); void* ptr1 = allocator_.Allocate(old_layout); ASSERT_NE(ptr1, nullptr); @@ -174,7 +176,7 @@ TEST_F(FallbackAllocatorTest, ReallocateSameAllocator) { void* ptr2 = allocator_.Allocate(old_layout); ASSERT_NE(ptr2, nullptr); - Layout new_layout = Layout::Of(); + Layout new_layout = Layout::Of(); void* new_ptr = allocator_.Reallocate(ptr1, new_layout); EXPECT_NE(new_ptr, nullptr); EXPECT_EQ(primary_.deallocate_ptr(), ptr1); @@ -183,11 +185,11 @@ TEST_F(FallbackAllocatorTest, ReallocateSameAllocator) { } TEST_F(FallbackAllocatorTest, ReallocateDifferentAllocator) { - Layout old_layout = Layout::Of(); + Layout old_layout = Layout::Of(); void* ptr = allocator_.Allocate(old_layout); primary_.Exhaust(); - Layout new_layout = Layout::Of(); + Layout new_layout = Layout::Of(); void* new_ptr = allocator_.Reallocate(ptr, new_layout); EXPECT_NE(new_ptr, nullptr); EXPECT_EQ(primary_.deallocate_ptr(), ptr); diff --git a/pw_allocator/first_fit_block_allocator_test.cc b/pw_allocator/first_fit_block_allocator_test.cc deleted file mode 100644 index 0a7044ea27..0000000000 --- a/pw_allocator/first_fit_block_allocator_test.cc +++ /dev/null @@ -1,142 +0,0 @@ -// Copyright 2024 The Pigweed Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); you may not -// use this file except in compliance with the License. You may obtain a copy of -// the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -// License for the specific language governing permissions and limitations under -// the License. - -#include "pw_allocator/first_fit_block_allocator.h" - -#include - -#include "lib/stdcompat/bit.h" -#include "pw_allocator/block_allocator_testing.h" -#include "pw_allocator/buffer.h" -#include "pw_unit_test/framework.h" - -namespace { - -using ::pw::allocator::Layout; -using ::pw::allocator::test::Preallocation; -using FirstFitBlockAllocator = - ::pw::allocator::FirstFitBlockAllocator; -using BlockAllocatorTest = - ::pw::allocator::test::BlockAllocatorTest; - -class FirstFitBlockAllocatorTest : public BlockAllocatorTest { - public: - FirstFitBlockAllocatorTest() : BlockAllocatorTest(allocator_) {} - - private: - FirstFitBlockAllocator allocator_; -}; - -TEST_F(FirstFitBlockAllocatorTest, CanAutomaticallyInit) { - FirstFitBlockAllocator allocator(GetBytes()); - CanAutomaticallyInit(allocator); -} - -TEST_F(FirstFitBlockAllocatorTest, CanExplicitlyInit) { - FirstFitBlockAllocator allocator; - CanExplicitlyInit(allocator); -} - -TEST_F(FirstFitBlockAllocatorTest, GetCapacity) { GetCapacity(); } - -TEST_F(FirstFitBlockAllocatorTest, AllocateLarge) { AllocateLarge(); } - -TEST_F(FirstFitBlockAllocatorTest, AllocateSmall) { AllocateSmall(); } - -TEST_F(FirstFitBlockAllocatorTest, AllocateLargeAlignment) { - AllocateLargeAlignment(); - - alignas(FirstFitBlockAllocator::BlockType::kAlignment) - std::array - buffer; - pw::ByteSpan bytes(buffer); - auto addr = cpp20::bit_cast(bytes.data()); - size_t offset = 64 - (addr % 64); - offset += 4 * 12; - offset %= 64; - bytes = bytes.subspan(offset); - FirstFitBlockAllocator allocator; - allocator.Init(bytes); - - constexpr size_t kAlignment = 64; - void* ptr0 = allocator.Allocate(Layout(kLargeInnerSize, kAlignment)); - ASSERT_NE(ptr0, nullptr); - EXPECT_EQ(cpp20::bit_cast(ptr0) % kAlignment, 0U); - UseMemory(ptr0, kLargeInnerSize); - - void* ptr1 = allocator.Allocate(Layout(kLargeInnerSize, kAlignment)); - ASSERT_NE(ptr1, nullptr); - EXPECT_EQ(cpp20::bit_cast(ptr1) % kAlignment, 0U); - UseMemory(ptr1, kLargeInnerSize); - - allocator.Deallocate(ptr0); - allocator.Deallocate(ptr1); -} - -TEST_F(FirstFitBlockAllocatorTest, AllocateAlignmentFailure) { - AllocateAlignmentFailure(); -} - -TEST_F(FirstFitBlockAllocatorTest, AllocatesFirstCompatible) { - auto& allocator = GetAllocator({ - {kSmallOuterSize, Preallocation::kFree}, - {kSmallerOuterSize, Preallocation::kUsed}, - {kSmallOuterSize, Preallocation::kFree}, - {kSmallerOuterSize, Preallocation::kUsed}, - {kLargeOuterSize, Preallocation::kFree}, - {Preallocation::kSizeRemaining, Preallocation::kUsed}, - }); - - Store(0, allocator.Allocate(Layout(kSmallInnerSize, 1))); - EXPECT_EQ(NextAfter(0), Fetch(1)); - Store(4, allocator.Allocate(Layout(kLargeInnerSize, 1))); - EXPECT_EQ(NextAfter(3), Fetch(4)); - EXPECT_EQ(NextAfter(4), Fetch(5)); -} - -TEST_F(FirstFitBlockAllocatorTest, DeallocateNull) { DeallocateNull(); } - -TEST_F(FirstFitBlockAllocatorTest, DeallocateShuffled) { DeallocateShuffled(); } - -TEST_F(FirstFitBlockAllocatorTest, IterateOverBlocks) { IterateOverBlocks(); } - -TEST_F(FirstFitBlockAllocatorTest, ResizeNull) { ResizeNull(); } - -TEST_F(FirstFitBlockAllocatorTest, ResizeLargeSame) { ResizeLargeSame(); } - -TEST_F(FirstFitBlockAllocatorTest, ResizeLargeSmaller) { ResizeLargeSmaller(); } - -TEST_F(FirstFitBlockAllocatorTest, ResizeLargeLarger) { ResizeLargeLarger(); } - -TEST_F(FirstFitBlockAllocatorTest, ResizeLargeLargerFailure) { - ResizeLargeLargerFailure(); -} - -TEST_F(FirstFitBlockAllocatorTest, ResizeSmallSame) { ResizeSmallSame(); } - -TEST_F(FirstFitBlockAllocatorTest, ResizeSmallSmaller) { ResizeSmallSmaller(); } - -TEST_F(FirstFitBlockAllocatorTest, ResizeSmallLarger) { ResizeSmallLarger(); } - -TEST_F(FirstFitBlockAllocatorTest, ResizeSmallLargerFailure) { - ResizeSmallLargerFailure(); -} - -TEST_F(FirstFitBlockAllocatorTest, CanMeasureFragmentation) { - CanMeasureFragmentation(); -} - -TEST_F(FirstFitBlockAllocatorTest, PoisonPeriodically) { PoisonPeriodically(); } - -} // namespace diff --git a/pw_allocator/first_fit_test.cc b/pw_allocator/first_fit_test.cc new file mode 100644 index 0000000000..2786567318 --- /dev/null +++ b/pw_allocator/first_fit_test.cc @@ -0,0 +1,284 @@ +// Copyright 2024 The Pigweed Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy of +// the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. + +#include "pw_allocator/first_fit.h" + +#include + +#include "pw_allocator/block/detailed_block.h" +#include "pw_allocator/block_allocator_testing.h" +#include "pw_allocator/buffer.h" +#include "pw_allocator/dual_first_fit_block_allocator.h" +#include "pw_allocator/first_fit_block_allocator.h" +#include "pw_allocator/last_fit_block_allocator.h" +#include "pw_unit_test/framework.h" + +namespace { + +using ::pw::allocator::Layout; +using ::pw::allocator::test::Preallocation; +using BlockType = ::pw::allocator::FirstFitBlock; +using FirstFitAllocator = ::pw::allocator::FirstFitAllocator; +using ::pw::allocator::test::BlockAllocatorTest; + +// Minimum size of a "large" allocation; allocation less than this size are +// considered "small" when using the "dual first fit" strategy. +static constexpr size_t kThreshold = + BlockAllocatorTest::kSmallInnerSize * 2; + +class FirstFitAllocatorTest : public BlockAllocatorTest { + public: + FirstFitAllocatorTest() : BlockAllocatorTest(allocator_) {} + + private: + FirstFitAllocator allocator_; +}; + +TEST_F(FirstFitAllocatorTest, AutomaticallyInit) { + FirstFitAllocator allocator(GetBytes()); + AutomaticallyInit(allocator); +} + +TEST_F(FirstFitAllocatorTest, ExplicitlyInit) { + FirstFitAllocator allocator; + ExplicitlyInit(allocator); +} + +TEST_F(FirstFitAllocatorTest, GetCapacity) { GetCapacity(); } + +TEST_F(FirstFitAllocatorTest, AllocateLarge) { AllocateLarge(); } + +TEST_F(FirstFitAllocatorTest, AllocateSmall) { AllocateSmall(); } + +TEST_F(FirstFitAllocatorTest, AllocateLargeAlignment) { + AllocateLargeAlignment(); +} + +TEST_F(FirstFitAllocatorTest, AllocateAlignmentFailure) { + AllocateAlignmentFailure(); +} + +TEST_F(FirstFitAllocatorTest, AllocatesZeroThreshold) { + FirstFitAllocator& allocator = GetAllocator({ + {kSmallOuterSize, Preallocation::kFree}, + {kSmallerOuterSize, Preallocation::kUsed}, + {kSmallOuterSize, Preallocation::kFree}, + {kSmallerOuterSize, Preallocation::kUsed}, + {kLargeOuterSize, Preallocation::kFree}, + {Preallocation::kSizeRemaining, Preallocation::kUsed}, + }); + + Store(0, allocator.Allocate(Layout(kSmallInnerSize, 1))); + EXPECT_EQ(NextAfter(0), Fetch(1)); + Store(4, allocator.Allocate(Layout(kLargeInnerSize, 1))); + EXPECT_EQ(NextAfter(3), Fetch(4)); + EXPECT_EQ(NextAfter(4), Fetch(5)); +} + +TEST_F(FirstFitAllocatorTest, AllocatesMaxThreshold) { + FirstFitAllocator& allocator = GetAllocator({ + {kLargeOuterSize, Preallocation::kFree}, + {kSmallerOuterSize, Preallocation::kUsed}, + {kSmallOuterSize, Preallocation::kFree}, + {kSmallerOuterSize, Preallocation::kUsed}, + {kSmallOuterSize, Preallocation::kFree}, + {Preallocation::kSizeRemaining, Preallocation::kUsed}, + }); + allocator.set_threshold(std::numeric_limits::max()); + + Store(0, allocator.Allocate(Layout(kLargeInnerSize, 1))); + EXPECT_EQ(NextAfter(0), Fetch(1)); + Store(4, allocator.Allocate(Layout(kSmallInnerSize, 1))); + EXPECT_EQ(NextAfter(3), Fetch(4)); + EXPECT_EQ(NextAfter(4), Fetch(5)); +} + +TEST_F(FirstFitAllocatorTest, AllocatesUsingThreshold) { + FirstFitAllocator& allocator = GetAllocator({ + {kLargeOuterSize, Preallocation::kFree}, + {kSmallerOuterSize, Preallocation::kUsed}, + {kSmallOuterSize, Preallocation::kFree}, + {Preallocation::kSizeRemaining, Preallocation::kUsed}, + {kLargeOuterSize, Preallocation::kFree}, + {kSmallerOuterSize, Preallocation::kUsed}, + {kSmallOuterSize, Preallocation::kFree}, + }); + allocator.set_threshold(kThreshold); + + Store(0, allocator.Allocate(Layout(kLargeInnerSize, 1))); + EXPECT_EQ(NextAfter(0), Fetch(1)); + Store(4, allocator.Allocate(Layout(kLargeInnerSize, 1))); + EXPECT_EQ(NextAfter(3), Fetch(4)); + EXPECT_EQ(NextAfter(4), Fetch(5)); + Store(6, allocator.Allocate(Layout(kSmallInnerSize, 1))); + EXPECT_EQ(NextAfter(5), Fetch(6)); + EXPECT_EQ(NextAfter(6), Fetch(7)); + Store(2, allocator.Allocate(Layout(kSmallInnerSize, 1))); + EXPECT_EQ(NextAfter(1), Fetch(2)); + EXPECT_EQ(NextAfter(2), Fetch(3)); +} + +TEST_F(FirstFitAllocatorTest, DeallocateNull) { DeallocateNull(); } + +TEST_F(FirstFitAllocatorTest, DeallocateShuffled) { DeallocateShuffled(); } + +TEST_F(FirstFitAllocatorTest, IterateOverBlocks) { IterateOverBlocks(); } + +TEST_F(FirstFitAllocatorTest, ResizeNull) { ResizeNull(); } + +TEST_F(FirstFitAllocatorTest, ResizeLargeSame) { ResizeLargeSame(); } + +TEST_F(FirstFitAllocatorTest, ResizeLargeSmaller) { ResizeLargeSmaller(); } + +TEST_F(FirstFitAllocatorTest, ResizeLargeLarger) { ResizeLargeLarger(); } + +TEST_F(FirstFitAllocatorTest, ResizeLargeLargerFailure) { + ResizeLargeLargerFailure(); +} + +TEST_F(FirstFitAllocatorTest, ResizeSmallSame) { ResizeSmallSame(); } + +TEST_F(FirstFitAllocatorTest, ResizeSmallSmaller) { ResizeSmallSmaller(); } + +TEST_F(FirstFitAllocatorTest, ResizeSmallLarger) { ResizeSmallLarger(); } + +TEST_F(FirstFitAllocatorTest, ResizeSmallLargerFailure) { + ResizeSmallLargerFailure(); +} + +TEST_F(FirstFitAllocatorTest, ResizeLargeSmallerAcrossThreshold) { + FirstFitAllocator& allocator = GetAllocator({ + {kThreshold * 2, Preallocation::kUsed}, + {Preallocation::kSizeRemaining, Preallocation::kFree}, + }); + allocator.set_threshold(kThreshold); + + // Shrinking succeeds, and the pointer is unchanged even though it is now + // below the threshold. + size_t new_size = kThreshold / 2; + ASSERT_TRUE(allocator.Resize(Fetch(0), new_size)); + UseMemory(Fetch(0), kThreshold / 2); +} + +TEST_F(FirstFitAllocatorTest, ResizeSmallLargerAcrossThreshold) { + FirstFitAllocator& allocator = GetAllocator({ + {Preallocation::kSizeRemaining, Preallocation::kUsed}, + {kThreshold / 2, Preallocation::kUsed}, + {kThreshold * 2, Preallocation::kFree}, + }); + allocator.set_threshold(kThreshold); + + // Growing succeeds, and the pointer is unchanged even though it is now + // above the threshold. + size_t new_size = kThreshold * 2; + ASSERT_TRUE(allocator.Resize(Fetch(1), new_size)); + UseMemory(Fetch(1), kThreshold * 2); +} + +TEST_F(FirstFitAllocatorTest, MeasureFragmentation) { MeasureFragmentation(); } + +TEST_F(FirstFitAllocatorTest, PoisonPeriodically) { PoisonPeriodically(); } + +// TODO(b/376730645): Remove this test when the legacy alias is deprecated. +using DualFirstFitBlockAllocator = + ::pw::allocator::DualFirstFitBlockAllocator; +class DualFirstFitBlockAllocatorTest + : public BlockAllocatorTest { + public: + DualFirstFitBlockAllocatorTest() : BlockAllocatorTest(allocator_) {} + + private: + DualFirstFitBlockAllocator allocator_; +}; +TEST_F(DualFirstFitBlockAllocatorTest, AllocatesUsingThreshold) { + auto& allocator = GetAllocator({ + {kLargeOuterSize, Preallocation::kFree}, + {kSmallerOuterSize, Preallocation::kUsed}, + {kSmallOuterSize, Preallocation::kFree}, + {Preallocation::kSizeRemaining, Preallocation::kUsed}, + {kLargeOuterSize, Preallocation::kFree}, + {kSmallerOuterSize, Preallocation::kUsed}, + {kSmallOuterSize, Preallocation::kFree}, + }); + allocator.set_threshold(kThreshold); + + Store(0, allocator.Allocate(Layout(kLargeInnerSize, 1))); + EXPECT_EQ(NextAfter(0), Fetch(1)); + Store(4, allocator.Allocate(Layout(kLargeInnerSize, 1))); + EXPECT_EQ(NextAfter(3), Fetch(4)); + EXPECT_EQ(NextAfter(4), Fetch(5)); + Store(6, allocator.Allocate(Layout(kSmallInnerSize, 1))); + EXPECT_EQ(NextAfter(5), Fetch(6)); + EXPECT_EQ(NextAfter(6), Fetch(7)); + Store(2, allocator.Allocate(Layout(kSmallInnerSize, 1))); + EXPECT_EQ(NextAfter(1), Fetch(2)); + EXPECT_EQ(NextAfter(2), Fetch(3)); +} + +// TODO(b/376730645): Remove this test when the legacy alias is deprecated. +using FirstFitBlockAllocator = + ::pw::allocator::FirstFitBlockAllocator; +class FirstFitBlockAllocatorTest + : public BlockAllocatorTest { + public: + FirstFitBlockAllocatorTest() : BlockAllocatorTest(allocator_) {} + + private: + FirstFitBlockAllocator allocator_; +}; +TEST_F(FirstFitBlockAllocatorTest, AllocatesFirstCompatible) { + auto& allocator = GetAllocator({ + {kSmallOuterSize, Preallocation::kFree}, + {kSmallerOuterSize, Preallocation::kUsed}, + {kSmallOuterSize, Preallocation::kFree}, + {kSmallerOuterSize, Preallocation::kUsed}, + {kLargeOuterSize, Preallocation::kFree}, + {Preallocation::kSizeRemaining, Preallocation::kUsed}, + }); + + Store(0, allocator.Allocate(Layout(kSmallInnerSize, 1))); + EXPECT_EQ(NextAfter(0), Fetch(1)); + Store(4, allocator.Allocate(Layout(kLargeInnerSize, 1))); + EXPECT_EQ(NextAfter(3), Fetch(4)); + EXPECT_EQ(NextAfter(4), Fetch(5)); +} + +// TODO(b/376730645): Remove this test when the legacy alias is deprecated. +using LastFitBlockAllocator = ::pw::allocator::LastFitBlockAllocator; +class LastFitBlockAllocatorTest + : public BlockAllocatorTest { + public: + LastFitBlockAllocatorTest() : BlockAllocatorTest(allocator_) {} + + private: + LastFitBlockAllocator allocator_; +}; +TEST_F(LastFitBlockAllocatorTest, AllocatesLastCompatible) { + auto& allocator = GetAllocator({ + {kLargeOuterSize, Preallocation::kFree}, + {kSmallerOuterSize, Preallocation::kUsed}, + {kSmallOuterSize, Preallocation::kFree}, + {kSmallerOuterSize, Preallocation::kUsed}, + {kSmallOuterSize, Preallocation::kFree}, + {Preallocation::kSizeRemaining, Preallocation::kUsed}, + }); + + Store(0, allocator.Allocate(Layout(kLargeInnerSize, 1))); + EXPECT_EQ(NextAfter(0), Fetch(1)); + Store(4, allocator.Allocate(Layout(kSmallInnerSize, 1))); + EXPECT_EQ(NextAfter(3), Fetch(4)); + EXPECT_EQ(NextAfter(4), Fetch(5)); +} + +} // namespace diff --git a/pw_allocator/guide.rst b/pw_allocator/guide.rst index 7e652de15d..80d3f9d172 100644 --- a/pw_allocator/guide.rst +++ b/pw_allocator/guide.rst @@ -247,14 +247,9 @@ overview. Consult the :ref:`module-pw_allocator-api` for additional details. for how to choose a block to use to satisfy a request. See also :ref:`module-pw_allocator-design-block`. Derived types include: - - :ref:`module-pw_allocator-api-first_fit_block_allocator`: Chooses the first + - :ref:`module-pw_allocator-api-first_fit_allocator`: Chooses the first block that's large enough to satisfy a request. This strategy is very fast, but may increase fragmentation. - - :ref:`module-pw_allocator-api-last_fit_block_allocator`: Chooses the last - block that's large enough to satisfy a request. This strategy is fast, and - may fragment memory less than - :ref:`module-pw_allocator-api-first_fit_block_allocator` when satisfying - aligned memory requests. - :ref:`module-pw_allocator-api-best_fit_block_allocator`: Chooses the smallest block that's large enough to satisfy a request. This strategy maximizes the avilable space for large allocations, but may increase @@ -262,13 +257,6 @@ overview. Consult the :ref:`module-pw_allocator-api` for additional details. - :ref:`module-pw_allocator-api-worst_fit_block_allocator`: Chooses the largest block if it's large enough to satisfy a request. This strategy minimizes the amount of memory in unusably small blocks, but is slower. - - :ref:`module-pw_allocator-api-dual_first_fit_block_allocator`: Acts like - :ref:`module-pw_allocator-api-first_fit_block_allocator` or - :ref:`module-pw_allocator-api-last_fit_block_allocator` depending on - whether a request is larger or smaller, respectively, than a given - threshold value. This strategy preserves the speed of the two other - strategies, while fragmenting memory less by co-locating allocations of - similar sizes. - :ref:`module-pw_allocator-api-bucket_block_allocator`: Sorts and stores each free blocks in a :ref:`module-pw_allocator-api-bucket` with a given maximum block inner size. @@ -453,17 +441,6 @@ deallocation by writing a set pattern to the usable memory, and later check on allocation that the pattern is intact. If it's not, some routine has modified unallocated memory. -The :ref:`module-pw_allocator-api-block_allocator` has a -``kPoisonInterval`` template parameter to control how frequently blocks are -poisoned on deallocation. This allows projects to stochiastically sample -allocations for memory corruptions while mitigating the performance impact. - -.. literalinclude:: examples/block_allocator.cc - :language: cpp - :linenos: - :start-after: [pw_allocator-examples-block_allocator-poison] - :end-before: [pw_allocator-examples-block_allocator-poison] - ---------------------- Test custom allocators ---------------------- @@ -525,8 +502,8 @@ For example, the C++ code for a size report binary might look like: :start-after: [pw_allocator-examples-size_report] The resulting binary could be compared with the binary produced from -pw_allocator/size_report/first_fit_block_allocator.cc to identify just the code -added in this case by ``CustomAllocator``. +pw_allocator/size_report/first_fit.cc to identify just the code added in this +case by ``CustomAllocator``. For example, the GN build rule to generate a size report might look liek: @@ -537,7 +514,7 @@ For example, the GN build rule to generate a size report might look liek: binaries = [ { target = ":size_report" - base = "$dir_pw_allocator/size_report:first_fit_block_allocator" + base = "$dir_pw_allocator/size_report:first_fit" label = "CustomAllocator" }, ] diff --git a/pw_allocator/last_fit_block_allocator_test.cc b/pw_allocator/last_fit_block_allocator_test.cc deleted file mode 100644 index aceabfa23a..0000000000 --- a/pw_allocator/last_fit_block_allocator_test.cc +++ /dev/null @@ -1,115 +0,0 @@ -// Copyright 2024 The Pigweed Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); you may not -// use this file except in compliance with the License. You may obtain a copy of -// the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -// License for the specific language governing permissions and limitations under -// the License. - -#include "pw_allocator/last_fit_block_allocator.h" - -#include "pw_allocator/block_allocator_testing.h" -#include "pw_unit_test/framework.h" - -namespace { - -// Test fixtures. - -using ::pw::allocator::Layout; -using ::pw::allocator::test::Preallocation; -using LastFitBlockAllocator = ::pw::allocator::LastFitBlockAllocator; -using BlockAllocatorTest = - ::pw::allocator::test::BlockAllocatorTest; - -class LastFitBlockAllocatorTest : public BlockAllocatorTest { - public: - LastFitBlockAllocatorTest() : BlockAllocatorTest(allocator_) {} - - private: - LastFitBlockAllocator allocator_; -}; - -// Unit tests. - -TEST_F(LastFitBlockAllocatorTest, CanAutomaticallyInit) { - LastFitBlockAllocator allocator(GetBytes()); - CanAutomaticallyInit(allocator); -} - -TEST_F(LastFitBlockAllocatorTest, CanExplicitlyInit) { - LastFitBlockAllocator allocator; - CanExplicitlyInit(allocator); -} - -TEST_F(LastFitBlockAllocatorTest, GetCapacity) { GetCapacity(); } - -TEST_F(LastFitBlockAllocatorTest, AllocateLarge) { AllocateLarge(); } - -TEST_F(LastFitBlockAllocatorTest, AllocateSmall) { AllocateSmall(); } - -TEST_F(LastFitBlockAllocatorTest, AllocateLargeAlignment) { - AllocateLargeAlignment(); -} - -TEST_F(LastFitBlockAllocatorTest, AllocateAlignmentFailure) { - AllocateAlignmentFailure(); -} - -TEST_F(LastFitBlockAllocatorTest, AllocatesLastCompatible) { - auto& allocator = GetAllocator({ - {kLargeOuterSize, Preallocation::kFree}, - {kSmallerOuterSize, Preallocation::kUsed}, - {kSmallOuterSize, Preallocation::kFree}, - {kSmallerOuterSize, Preallocation::kUsed}, - {kSmallOuterSize, Preallocation::kFree}, - {Preallocation::kSizeRemaining, Preallocation::kUsed}, - }); - - Store(0, allocator.Allocate(Layout(kLargeInnerSize, 1))); - EXPECT_EQ(NextAfter(0), Fetch(1)); - Store(4, allocator.Allocate(Layout(kSmallInnerSize, 1))); - EXPECT_EQ(NextAfter(3), Fetch(4)); - EXPECT_EQ(NextAfter(4), Fetch(5)); -} - -TEST_F(LastFitBlockAllocatorTest, DeallocateNull) { DeallocateNull(); } - -TEST_F(LastFitBlockAllocatorTest, DeallocateShuffled) { DeallocateShuffled(); } - -TEST_F(LastFitBlockAllocatorTest, IterateOverBlocks) { IterateOverBlocks(); } - -TEST_F(LastFitBlockAllocatorTest, ResizeNull) { ResizeNull(); } - -TEST_F(LastFitBlockAllocatorTest, ResizeLargeSame) { ResizeLargeSame(); } - -TEST_F(LastFitBlockAllocatorTest, ResizeLargeSmaller) { ResizeLargeSmaller(); } - -TEST_F(LastFitBlockAllocatorTest, ResizeLargeLarger) { ResizeLargeLarger(); } - -TEST_F(LastFitBlockAllocatorTest, ResizeLargeLargerFailure) { - ResizeLargeLargerFailure(); -} - -TEST_F(LastFitBlockAllocatorTest, ResizeSmallSame) { ResizeSmallSame(); } - -TEST_F(LastFitBlockAllocatorTest, ResizeSmallSmaller) { ResizeSmallSmaller(); } - -TEST_F(LastFitBlockAllocatorTest, ResizeSmallLarger) { ResizeSmallLarger(); } - -TEST_F(LastFitBlockAllocatorTest, ResizeSmallLargerFailure) { - ResizeSmallLargerFailure(); -} - -TEST_F(LastFitBlockAllocatorTest, CanMeasureFragmentation) { - CanMeasureFragmentation(); -} - -TEST_F(LastFitBlockAllocatorTest, PoisonPeriodically) { PoisonPeriodically(); } - -} // namespace diff --git a/pw_allocator/pmr_allocator_test.cc b/pw_allocator/pmr_allocator_test.cc index b91b5ab0e8..5c61d539b7 100644 --- a/pw_allocator/pmr_allocator_test.cc +++ b/pw_allocator/pmr_allocator_test.cc @@ -34,9 +34,9 @@ using ::pw::allocator::PmrAllocator; using ::pw::allocator::test::AllocatorForTest; struct Foo { - uint32_t value; + uintptr_t value; - Foo(uint32_t value_) : value(value_) {} + Foo(uintptr_t value_) : value(value_) {} }; bool operator==(const Foo& lhs, const Foo& rhs) { @@ -50,7 +50,7 @@ bool operator<(const Foo& lhs, const Foo& rhs) { return lhs.value < rhs.value; } template <> struct std::hash { size_t operator()(const Foo& foo) const { - return std::hash()(foo.value); + return std::hash()(foo.value); } }; @@ -96,6 +96,7 @@ struct has_mapped_type > template void TestPmrAllocator() { AllocatorForTest underlying; + static_assert(sizeof(Foo) >= AllocatorForTest::kMinSize); auto& requested_bytes = underlying.metrics().requested_bytes; EXPECT_EQ(requested_bytes.value(), 0U); diff --git a/pw_allocator/public/pw_allocator/block_allocator_testing.h b/pw_allocator/public/pw_allocator/block_allocator_testing.h index 98825be498..b01aded351 100644 --- a/pw_allocator/public/pw_allocator/block_allocator_testing.h +++ b/pw_allocator/public/pw_allocator/block_allocator_testing.h @@ -146,10 +146,10 @@ class BlockAllocatorTest : public BlockAllocatorTestBase { void TearDown() override; // Unit tests. - static void CanAutomaticallyInit(BlockAllocatorType& allocator); - void CanExplicitlyInit(BlockAllocatorType& allocator); + static void AutomaticallyInit(BlockAllocatorType& allocator); + void ExplicitlyInit(BlockAllocatorType& allocator); void IterateOverBlocks(); - void CanMeasureFragmentation(); + void MeasureFragmentation(); void PoisonPeriodically(); private: @@ -208,13 +208,13 @@ void BlockAllocatorTest::TearDown() { // Unit tests template method implementations. template -void BlockAllocatorTest::CanAutomaticallyInit( +void BlockAllocatorTest::AutomaticallyInit( BlockAllocatorType& allocator) { EXPECT_NE(*(allocator.blocks().begin()), nullptr); } template -void BlockAllocatorTest::CanExplicitlyInit( +void BlockAllocatorTest::ExplicitlyInit( BlockAllocatorType& allocator) { EXPECT_EQ(*(allocator.blocks().begin()), nullptr); allocator.Init(GetBytes()); @@ -251,7 +251,7 @@ void BlockAllocatorTest::IterateOverBlocks() { } template -void BlockAllocatorTest::CanMeasureFragmentation() { +void BlockAllocatorTest::MeasureFragmentation() { Allocator& allocator = GetGenericAllocator({ {0x020, Preallocation::kFree}, {0x040, Preallocation::kUsed}, diff --git a/pw_allocator/public/pw_allocator/dual_first_fit_block_allocator.h b/pw_allocator/public/pw_allocator/dual_first_fit_block_allocator.h index 4915576d08..92d59578ba 100644 --- a/pw_allocator/public/pw_allocator/dual_first_fit_block_allocator.h +++ b/pw_allocator/public/pw_allocator/dual_first_fit_block_allocator.h @@ -13,77 +13,19 @@ // the License. #pragma once -#include "pw_allocator/block/detailed_block.h" -#include "pw_allocator/block_allocator.h" +#include "pw_allocator/config.h" +#include "pw_allocator/first_fit.h" namespace pw::allocator { /// Alias for a default block type that is compatible with /// `DualFirstFitBlockAllocator`. template -using DualFirstFitBlock = DetailedBlock; +using DualFirstFitBlock = FirstFitBlock; -/// Block allocator that uses a "dual first-fit" allocation strategy split -/// between large and small allocations. -/// -/// In this strategy, the strategy includes a threshold value. Requests for -/// more than this threshold are handled similarly to `FirstFit`, while requests -/// for less than this threshold are handled similarly to `LastFit`. -/// -/// This algorithm approaches the performance of `FirstFit` and `LastFit` while -/// improving on those algorithms fragmentation. +/// Alias providing the legacy name for a first fit allocator with a threshold. template -class DualFirstFitBlockAllocator - : public BlockAllocator> { - public: - using BlockType = DualFirstFitBlock; - - private: - using Base = BlockAllocator; - - public: - /// Constexpr constructor. Callers must explicitly call `Init`. - constexpr DualFirstFitBlockAllocator() = default; - - /// Non-constexpr constructor that automatically calls `Init`. - /// - /// @param[in] region Region of memory to use when satisfying allocation - /// requests. The region MUST be valid as an argument - /// to `BlockType::Init`. - /// @param[in] threshold Value for which requests are considered "large". - DualFirstFitBlockAllocator(ByteSpan region, size_t threshold) - : threshold_(threshold) { - Base::Init(region); - } - - /// Sets the threshold value for which requests are considered "large". - void set_threshold(size_t threshold) { threshold_ = threshold; } - - private: - /// @copydoc BlockAllocator::ChooseBlock - BlockResult ChooseBlock(Layout layout) override { - if (layout.size() < threshold_) { - // Search backwards for the last block that can hold this allocation. - for (auto* block : Base::rblocks()) { - auto result = BlockType::AllocLast(std::move(block), layout); - if (result.ok()) { - return result; - } - } - } else { - // Search forwards for the first block that can hold this allocation. - for (auto* block : Base::blocks()) { - auto result = BlockType::AllocFirst(std::move(block), layout); - if (result.ok()) { - return result; - } - } - } - // No valid block found. - return BlockResult(nullptr, Status::NotFound()); - } - - size_t threshold_ = 0; -}; +using DualFirstFitBlockAllocator PW_ALLOCATOR_DEPRECATED = + FirstFitAllocator>; } // namespace pw::allocator diff --git a/pw_allocator/public/pw_allocator/first_fit.h b/pw_allocator/public/pw_allocator/first_fit.h new file mode 100644 index 0000000000..b1d1d07aa7 --- /dev/null +++ b/pw_allocator/public/pw_allocator/first_fit.h @@ -0,0 +1,90 @@ +// Copyright 2024 The Pigweed Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy of +// the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +#pragma once + +#include + +#include "pw_allocator/block/detailed_block.h" +#include "pw_allocator/block_allocator.h" +#include "pw_allocator/bucket/sequenced.h" + +namespace pw::allocator { + +/// Alias for a default block type that is compatible with `FirstFitAllocator`. +template +using FirstFitBlock = DetailedBlock; + +/// Block allocator that uses a "first-fit" allocation strategy split +/// between large and small allocations. +/// +/// In this strategy, the allocator handles an allocation request by starting at +/// the beginning of the range of blocks and looking for the first one which can +/// satisfy the request. +/// +/// Optionally, callers may set a "threshold" value. If set, requests smaller +/// than the threshold are satisfied using the *last* compatible block. This +/// separates large and small requests and can reduce overall fragmentation. +template > +class FirstFitAllocator : public BlockAllocator { + public: + using Base = BlockAllocator; + + /// Constexpr constructor. Callers must explicitly call `Init`. + constexpr FirstFitAllocator() = default; + + /// Non-constexpr constructor that automatically calls `Init`. + /// + /// @param[in] region Region of memory to use when satisfying allocation + /// requests. The region MUST be valid as an argument + /// to `BlockType::Init`. + FirstFitAllocator(ByteSpan region) { Base::Init(region); } + + /// Non-constexpr constructor that automatically calls `Init`. + /// + /// @param[in] region Region of memory to use when satisfying allocation + /// requests. The region MUST be valid as an argument + /// to `BlockType::Init`. + /// @param[in] threshold Value for which requests are considered "large". + FirstFitAllocator(ByteSpan region, size_t threshold) { + Base::Init(region); + bucket_.set_threshold(threshold); + } + + /// Sets the threshold value for which requests are considered "large". + void set_threshold(size_t threshold) { bucket_.set_threshold(threshold); } + + private: + /// @copydoc BlockAllocator::ChooseBlock + BlockResult ChooseBlock(Layout layout) override { + if (BlockType* block = bucket_.RemoveCompatible(layout); block != nullptr) { + return BlockType::AllocFirst(std::move(block), layout); + } + return BlockResult(nullptr, Status::NotFound()); + } + + /// @copydoc BlockAllocator::ReserveBlock + void ReserveBlock(BlockType& block) override { + std::ignore = bucket_.Remove(block); + } + + /// @copydoc BlockAllocator::RecycleBlock + void RecycleBlock(BlockType& block) override { + std::ignore = bucket_.Add(block); + } + + SequencedBucket bucket_; + size_t threshold_ = 0; +}; + +} // namespace pw::allocator diff --git a/pw_allocator/public/pw_allocator/first_fit_block_allocator.h b/pw_allocator/public/pw_allocator/first_fit_block_allocator.h index 5c0980c093..3e13cedabb 100644 --- a/pw_allocator/public/pw_allocator/first_fit_block_allocator.h +++ b/pw_allocator/public/pw_allocator/first_fit_block_allocator.h @@ -13,57 +13,14 @@ // the License. #pragma once -#include "pw_allocator/block/detailed_block.h" -#include "pw_allocator/block_allocator.h" +#include "pw_allocator/config.h" +#include "pw_allocator/first_fit.h" namespace pw::allocator { -/// Alias for a default block type that is compatible with -/// `FirstFitBlockAllocator`. -template -using FirstFitBlock = DetailedBlock; - -/// Block allocator that uses a "first-fit" allocation strategy. -/// -/// In this strategy, the allocator handles an allocation request by starting at -/// the beginning of the range of blocks and looking for the first one which can -/// satisfy the request. -/// -/// This strategy may result in slightly worse fragmentation than the -/// corresponding "last-fit" strategy, since the alignment may result in unused -/// fragments both before and after an allocated block. +/// Alias providing the legacy name for a first fit allocator with a threshold. template -class FirstFitBlockAllocator - : public BlockAllocator> { - public: - using BlockType = FirstFitBlock; - - private: - using Base = BlockAllocator; - - public: - /// Constexpr constructor. Callers must explicitly call `Init`. - constexpr FirstFitBlockAllocator() = default; - - /// Non-constexpr constructor that automatically calls `Init`. - /// - /// @param[in] region Region of memory to use when satisfying allocation - /// requests. The region MUST be valid as an argument to - /// `BlockType::Init`. - explicit FirstFitBlockAllocator(ByteSpan region) { Base::Init(region); } - - private: - /// @copydoc Allocator::Allocate - BlockResult ChooseBlock(Layout layout) override { - // Search forwards for the first block that can hold this allocation. - for (auto* block : Base::blocks()) { - auto result = BlockType::AllocFirst(std::move(block), layout); - if (result.ok()) { - return result; - } - } - return BlockResult(nullptr, Status::NotFound()); - } -}; +using FirstFitBlockAllocator PW_ALLOCATOR_DEPRECATED = + FirstFitAllocator>; } // namespace pw::allocator diff --git a/pw_allocator/public/pw_allocator/last_fit_block_allocator.h b/pw_allocator/public/pw_allocator/last_fit_block_allocator.h index 2dc2beb5a3..3f665397ef 100644 --- a/pw_allocator/public/pw_allocator/last_fit_block_allocator.h +++ b/pw_allocator/public/pw_allocator/last_fit_block_allocator.h @@ -13,56 +13,38 @@ // the License. #pragma once -#include "pw_allocator/block/detailed_block.h" -#include "pw_allocator/block_allocator.h" +#include "pw_allocator/config.h" +#include "pw_allocator/first_fit.h" namespace pw::allocator { /// Alias for a default block type that is compatible with /// `LastFitBlockAllocator`. template -using LastFitBlock = DetailedBlock; +using LastFitBlock = FirstFitBlock; -/// Block allocator that uses a "last-fit" allocation strategy. +/// Legacy last fit allocator. /// -/// In this strategy, the allocator handles an allocation request by starting at -/// the end of the range of blocks and looking for the last one which can -/// satisfy the request. +/// New usages should prefer to use `FirstFitAllocator` directly. /// -/// This strategy may result in slightly better fragmentation than the -/// corresponding "first-fit" strategy, since even with alignment it will result -/// in at most one unused fragment before the allocated block. +/// This allocator sets the base type's threshold to value to the maximum value, +/// ensuring that all allocations come from the end of the region. template -class LastFitBlockAllocator : public BlockAllocator> { +class PW_ALLOCATOR_DEPRECATED LastFitBlockAllocator + : public FirstFitAllocator> { public: using BlockType = LastFitBlock; private: - using Base = BlockAllocator; + using Base = FirstFitAllocator; public: - /// Constexpr constructor. Callers must explicitly call `Init`. - constexpr LastFitBlockAllocator() = default; - - /// Non-constexpr constructor that automatically calls `Init`. - /// - /// @param[in] region Region of memory to use when satisfying allocation - /// requests. The region MUST be valid as an argument to - /// `BlockType::Init`. - explicit LastFitBlockAllocator(ByteSpan region) { Base::Init(region); } - - private: - /// @copydoc Allocator::Allocate - BlockResult ChooseBlock(Layout layout) override { - // Search backwards for the last block that can hold this allocation. - for (auto* block : Base::rblocks()) { - auto result = BlockType::AllocLast(std::move(block), layout); - if (result.ok()) { - return result; - } - } - return BlockResult(nullptr, Status::NotFound()); + constexpr LastFitBlockAllocator() { + Base::set_threshold(std::numeric_limits::max()); } + + explicit LastFitBlockAllocator(ByteSpan region) + : Base(region, std::numeric_limits::max()) {} }; } // namespace pw::allocator diff --git a/pw_allocator/public/pw_allocator/testing.h b/pw_allocator/public/pw_allocator/testing.h index 88ff3fa8c1..d8bec5a8d9 100644 --- a/pw_allocator/public/pw_allocator/testing.h +++ b/pw_allocator/public/pw_allocator/testing.h @@ -17,10 +17,9 @@ #include #include "pw_allocator/allocator.h" -#include "pw_allocator/block/detailed_block.h" #include "pw_allocator/buffer.h" #include "pw_allocator/config.h" -#include "pw_allocator/first_fit_block_allocator.h" +#include "pw_allocator/first_fit.h" #include "pw_allocator/metrics.h" #include "pw_allocator/tracking_allocator.h" #include "pw_assert/assert.h" @@ -67,11 +66,17 @@ void FreeAll(typename BlockType::Range range) { } /// An `AllocatorForTest` that is automatically initialized on construction. -template +template , + typename MetricsType = internal::AllMetrics> class AllocatorForTest : public Allocator { public: - using AllocatorType = FirstFitBlockAllocator; - using BlockType = typename AllocatorType::BlockType; + using BlockType = BlockType_; + using AllocatorType = FirstFitAllocator; + + // Since the unbderlying first-fit allocator uses an intrusive free list, all + // allocations will be at least this size. + static constexpr size_t kMinSize = BlockType::kAlignment; AllocatorForTest() : Allocator(AllocatorType::kCapabilities), tracker_(kToken, *allocator_) { @@ -179,10 +184,13 @@ class AllocatorForTest : public Allocator { /// An `AllocatorForTest` that is thread and interrupt-safe and automatically /// initialized on construction. -template +template , + typename MetricsType = internal::AllMetrics> class SynchronizedAllocatorForTest : public Allocator { private: - using Base = AllocatorForTest; + using BlockType = BlockType_; + using Base = AllocatorForTest; /// @copydoc Allocator::Allocate void* DoAllocate(Layout layout) override { diff --git a/pw_allocator/size_report/BUILD.bazel b/pw_allocator/size_report/BUILD.bazel index 3d065ced0c..cfbb419ee5 100644 --- a/pw_allocator/size_report/BUILD.bazel +++ b/pw_allocator/size_report/BUILD.bazel @@ -61,20 +61,11 @@ pw_cc_binary( ], ) -pw_cc_binary( - name = "dual_first_fit_block_allocator", - srcs = ["dual_first_fit_block_allocator.cc"], - deps = [ - "//pw_allocator:dual_first_fit_block_allocator", - "//pw_allocator:size_reporter", - ], -) - pw_cc_binary( name = "fallback_allocator_base", srcs = ["fallback_allocator_base.cc"], deps = [ - "//pw_allocator:first_fit_block_allocator", + "//pw_allocator:first_fit", "//pw_allocator:size_reporter", ], ) @@ -84,25 +75,16 @@ pw_cc_binary( srcs = ["fallback_allocator.cc"], deps = [ "//pw_allocator:fallback_allocator", - "//pw_allocator:first_fit_block_allocator", + "//pw_allocator:first_fit", "//pw_allocator:size_reporter", ], ) pw_cc_binary( - name = "first_fit_block_allocator", - srcs = ["first_fit_block_allocator.cc"], + name = "first_fit", + srcs = ["first_fit.cc"], deps = [ - "//pw_allocator:first_fit_block_allocator", - "//pw_allocator:size_reporter", - ], -) - -pw_cc_binary( - name = "last_fit_block_allocator", - srcs = ["last_fit_block_allocator.cc"], - deps = [ - "//pw_allocator:last_fit_block_allocator", + "//pw_allocator:first_fit", "//pw_allocator:size_reporter", ], ) @@ -148,7 +130,7 @@ pw_cc_binary( name = "synchronized_allocator_isl", srcs = ["synchronized_allocator_isl.cc"], deps = [ - "//pw_allocator:first_fit_block_allocator", + "//pw_allocator:first_fit", "//pw_allocator:size_reporter", "//pw_allocator:synchronized_allocator", "//pw_sync:interrupt_spin_lock", @@ -159,7 +141,7 @@ pw_cc_binary( name = "synchronized_allocator_mutex", srcs = ["synchronized_allocator_mutex.cc"], deps = [ - "//pw_allocator:first_fit_block_allocator", + "//pw_allocator:first_fit", "//pw_allocator:size_reporter", "//pw_allocator:synchronized_allocator", "//pw_sync:mutex", @@ -170,7 +152,7 @@ pw_cc_binary( name = "tracking_allocator_all_metrics", srcs = ["tracking_allocator_all_metrics.cc"], deps = [ - "//pw_allocator:first_fit_block_allocator", + "//pw_allocator:first_fit", "//pw_allocator:size_reporter", "//pw_allocator:tracking_allocator", ], @@ -180,7 +162,7 @@ pw_cc_binary( name = "tracking_allocator_no_metrics", srcs = ["tracking_allocator_no_metrics.cc"], deps = [ - "//pw_allocator:first_fit_block_allocator", + "//pw_allocator:first_fit", "//pw_allocator:size_reporter", "//pw_allocator:tracking_allocator", ], diff --git a/pw_allocator/size_report/BUILD.gn b/pw_allocator/size_report/BUILD.gn index ef93fcd0c0..218e8c2ae4 100644 --- a/pw_allocator/size_report/BUILD.gn +++ b/pw_allocator/size_report/BUILD.gn @@ -62,19 +62,11 @@ pw_executable("bump_allocator") { ] } -pw_executable("dual_first_fit_block_allocator") { - sources = [ "dual_first_fit_block_allocator.cc" ] - deps = [ - "..:dual_first_fit_block_allocator", - "..:size_reporter", - ] -} - pw_executable("fallback_allocator_base") { sources = [ "fallback_allocator_base.cc" ] deps = [ "..:fallback_allocator", - "..:first_fit_block_allocator", + "..:first_fit", "..:size_reporter", ] } @@ -83,23 +75,15 @@ pw_executable("fallback_allocator") { sources = [ "fallback_allocator.cc" ] deps = [ "..:fallback_allocator", - "..:first_fit_block_allocator", + "..:first_fit", "..:size_reporter", ] } -pw_executable("first_fit_block_allocator") { - sources = [ "first_fit_block_allocator.cc" ] +pw_executable("first_fit") { + sources = [ "first_fit.cc" ] deps = [ - "..:first_fit_block_allocator", - "..:size_reporter", - ] -} - -pw_executable("last_fit_block_allocator") { - sources = [ "last_fit_block_allocator.cc" ] - deps = [ - "..:last_fit_block_allocator", + "..:first_fit", "..:size_reporter", ] } @@ -141,7 +125,7 @@ pw_executable("synchronized_allocator_isl") { sources = [ "synchronized_allocator_isl.cc" ] deps = [ "$dir_pw_sync:interrupt_spin_lock", - "..:first_fit_block_allocator", + "..:first_fit", "..:size_reporter", "..:synchronized_allocator", ] @@ -151,7 +135,7 @@ pw_executable("synchronized_allocator_mutex") { sources = [ "synchronized_allocator_mutex.cc" ] deps = [ "$dir_pw_sync:mutex", - "..:first_fit_block_allocator", + "..:first_fit", "..:size_reporter", "..:synchronized_allocator", ] @@ -160,7 +144,7 @@ pw_executable("synchronized_allocator_mutex") { pw_executable("tracking_allocator_all_metrics") { sources = [ "tracking_allocator_all_metrics.cc" ] deps = [ - "..:first_fit_block_allocator", + "..:first_fit", "..:size_reporter", "..:tracking_allocator", ] @@ -169,7 +153,7 @@ pw_executable("tracking_allocator_all_metrics") { pw_executable("tracking_allocator_no_metrics") { sources = [ "tracking_allocator_no_metrics.cc" ] deps = [ - "..:first_fit_block_allocator", + "..:first_fit", "..:size_reporter", "..:tracking_allocator", ] diff --git a/pw_allocator/size_report/dual_first_fit_block_allocator.cc b/pw_allocator/size_report/dual_first_fit_block_allocator.cc deleted file mode 100644 index 01961d21bc..0000000000 --- a/pw_allocator/size_report/dual_first_fit_block_allocator.cc +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright 2024 The Pigweed Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); you may not -// use this file except in compliance with the License. You may obtain a copy of -// the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -// License for the specific language governing permissions and limitations under -// the License. - -#include "pw_allocator/dual_first_fit_block_allocator.h" - -#include "pw_allocator/size_reporter.h" - -int main() { - pw::allocator::SizeReporter reporter; - reporter.SetBaseline(); - - constexpr size_t kThreshold = 128; - pw::allocator::DualFirstFitBlockAllocator<> allocator(reporter.buffer(), - kThreshold); - reporter.Measure(allocator); - - return 0; -} diff --git a/pw_allocator/size_report/fallback_allocator.cc b/pw_allocator/size_report/fallback_allocator.cc index fe698d60d0..af42318bbe 100644 --- a/pw_allocator/size_report/fallback_allocator.cc +++ b/pw_allocator/size_report/fallback_allocator.cc @@ -14,7 +14,7 @@ #include "pw_allocator/fallback_allocator.h" -#include "pw_allocator/first_fit_block_allocator.h" +#include "pw_allocator/first_fit.h" #include "pw_allocator/size_reporter.h" int main() { @@ -22,8 +22,8 @@ int main() { reporter.SetBaseline(); std::array buffer; - pw::allocator::FirstFitBlockAllocator<> primary(reporter.buffer()); - pw::allocator::FirstFitBlockAllocator<> secondary(buffer); + pw::allocator::FirstFitAllocator<> primary(reporter.buffer()); + pw::allocator::FirstFitAllocator<> secondary(buffer); reporter.Measure(secondary); reporter.Measure(primary); diff --git a/pw_allocator/size_report/fallback_allocator_base.cc b/pw_allocator/size_report/fallback_allocator_base.cc index 390e288861..2c4c1eed1b 100644 --- a/pw_allocator/size_report/fallback_allocator_base.cc +++ b/pw_allocator/size_report/fallback_allocator_base.cc @@ -12,7 +12,7 @@ // License for the specific language governing permissions and limitations under // the License. -#include "pw_allocator/first_fit_block_allocator.h" +#include "pw_allocator/first_fit.h" #include "pw_allocator/size_reporter.h" int main() { @@ -20,8 +20,8 @@ int main() { reporter.SetBaseline(); std::array buffer; - pw::allocator::FirstFitBlockAllocator<> primary(reporter.buffer()); - pw::allocator::FirstFitBlockAllocator<> secondary(buffer); + pw::allocator::FirstFitAllocator<> primary(reporter.buffer()); + pw::allocator::FirstFitAllocator<> secondary(buffer); reporter.Measure(primary); reporter.Measure(secondary); diff --git a/pw_allocator/size_report/first_fit_block_allocator.cc b/pw_allocator/size_report/first_fit.cc similarity index 83% rename from pw_allocator/size_report/first_fit_block_allocator.cc rename to pw_allocator/size_report/first_fit.cc index f25978aca8..a487ee9689 100644 --- a/pw_allocator/size_report/first_fit_block_allocator.cc +++ b/pw_allocator/size_report/first_fit.cc @@ -12,7 +12,7 @@ // License for the specific language governing permissions and limitations under // the License. -#include "pw_allocator/first_fit_block_allocator.h" +#include "pw_allocator/first_fit.h" #include "pw_allocator/size_reporter.h" @@ -20,7 +20,8 @@ int main() { pw::allocator::SizeReporter reporter; reporter.SetBaseline(); - pw::allocator::FirstFitBlockAllocator<> allocator(reporter.buffer()); + constexpr size_t kThreshold = 128; + pw::allocator::FirstFitAllocator<> allocator(reporter.buffer(), kThreshold); reporter.Measure(allocator); return 0; diff --git a/pw_allocator/size_report/last_fit_block_allocator.cc b/pw_allocator/size_report/last_fit_block_allocator.cc deleted file mode 100644 index 3c28318996..0000000000 --- a/pw_allocator/size_report/last_fit_block_allocator.cc +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright 2024 The Pigweed Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); you may not -// use this file except in compliance with the License. You may obtain a copy of -// the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -// License for the specific language governing permissions and limitations under -// the License. - -#include "pw_allocator/last_fit_block_allocator.h" - -#include "pw_allocator/size_reporter.h" - -int main() { - pw::allocator::SizeReporter reporter; - reporter.SetBaseline(); - - pw::allocator::LastFitBlockAllocator<> allocator(reporter.buffer()); - reporter.Measure(allocator); - - return 0; -} diff --git a/pw_allocator/size_report/pmr_allocator.cc b/pw_allocator/size_report/pmr_allocator.cc index f3d575f992..e25b276acb 100644 --- a/pw_allocator/size_report/pmr_allocator.cc +++ b/pw_allocator/size_report/pmr_allocator.cc @@ -16,7 +16,7 @@ #include -#include "pw_allocator/first_fit_block_allocator.h" +#include "pw_allocator/first_fit.h" #include "pw_allocator/size_reporter.h" #include "pw_assert/check.h" @@ -26,7 +26,7 @@ int main() { pw::allocator::SizeReporter reporter; reporter.SetBaseline(); - pw::allocator::FirstFitBlockAllocator<> base(reporter.buffer()); + pw::allocator::FirstFitAllocator<> base(reporter.buffer()); pw::allocator::PmrAllocator allocator(base); std::pmr::vector vec(allocator); vec.emplace_back(1); diff --git a/pw_allocator/size_report/pmr_allocator_base.cc b/pw_allocator/size_report/pmr_allocator_base.cc index 2551f89128..30cc3ab58a 100644 --- a/pw_allocator/size_report/pmr_allocator_base.cc +++ b/pw_allocator/size_report/pmr_allocator_base.cc @@ -14,7 +14,7 @@ #include -#include "pw_allocator/first_fit_block_allocator.h" +#include "pw_allocator/first_fit.h" #include "pw_allocator/size_reporter.h" #include "pw_assert/check.h" @@ -24,7 +24,7 @@ int main() { pw::allocator::SizeReporter reporter; reporter.SetBaseline(); - pw::allocator::FirstFitBlockAllocator<> base(reporter.buffer()); + pw::allocator::FirstFitAllocator<> base(reporter.buffer()); std::vector vec; auto* bar = base.New(1); vec.emplace_back(std::move(*bar)); diff --git a/pw_allocator/size_report/synchronized_allocator_isl.cc b/pw_allocator/size_report/synchronized_allocator_isl.cc index ccba686b39..b71fa7835d 100644 --- a/pw_allocator/size_report/synchronized_allocator_isl.cc +++ b/pw_allocator/size_report/synchronized_allocator_isl.cc @@ -12,7 +12,7 @@ // License for the specific language governing permissions and limitations under // the License. -#include "pw_allocator/first_fit_block_allocator.h" +#include "pw_allocator/first_fit.h" #include "pw_allocator/size_reporter.h" #include "pw_allocator/synchronized_allocator.h" #include "pw_sync/interrupt_spin_lock.h" @@ -21,7 +21,7 @@ int main() { pw::allocator::SizeReporter reporter; reporter.SetBaseline(); - pw::allocator::FirstFitBlockAllocator<> allocator(reporter.buffer()); + pw::allocator::FirstFitAllocator<> allocator(reporter.buffer()); pw::allocator::SynchronizedAllocator synchronized(allocator); reporter.Measure(synchronized); diff --git a/pw_allocator/size_report/synchronized_allocator_mutex.cc b/pw_allocator/size_report/synchronized_allocator_mutex.cc index 98e9edab5f..584f4a3b5a 100644 --- a/pw_allocator/size_report/synchronized_allocator_mutex.cc +++ b/pw_allocator/size_report/synchronized_allocator_mutex.cc @@ -12,7 +12,7 @@ // License for the specific language governing permissions and limitations under // the License. -#include "pw_allocator/first_fit_block_allocator.h" +#include "pw_allocator/first_fit.h" #include "pw_allocator/size_reporter.h" #include "pw_allocator/synchronized_allocator.h" #include "pw_sync/mutex.h" @@ -21,7 +21,7 @@ int main() { pw::allocator::SizeReporter reporter; reporter.SetBaseline(); - pw::allocator::FirstFitBlockAllocator<> allocator(reporter.buffer()); + pw::allocator::FirstFitAllocator<> allocator(reporter.buffer()); pw::allocator::SynchronizedAllocator synchronized(allocator); reporter.Measure(synchronized); diff --git a/pw_allocator/size_report/tracking_allocator_all_metrics.cc b/pw_allocator/size_report/tracking_allocator_all_metrics.cc index edb4794d5a..1c6537caf8 100644 --- a/pw_allocator/size_report/tracking_allocator_all_metrics.cc +++ b/pw_allocator/size_report/tracking_allocator_all_metrics.cc @@ -12,7 +12,7 @@ // License for the specific language governing permissions and limitations under // the License. -#include "pw_allocator/first_fit_block_allocator.h" +#include "pw_allocator/first_fit.h" #include "pw_allocator/metrics.h" #include "pw_allocator/size_reporter.h" #include "pw_allocator/tracking_allocator.h" @@ -21,7 +21,7 @@ int main() { pw::allocator::SizeReporter reporter; reporter.SetBaseline(); - pw::allocator::FirstFitBlockAllocator<> allocator(reporter.buffer()); + pw::allocator::FirstFitAllocator<> allocator(reporter.buffer()); pw::allocator::TrackingAllocator tracker( 1, allocator); reporter.Measure(tracker); diff --git a/pw_allocator/size_report/tracking_allocator_no_metrics.cc b/pw_allocator/size_report/tracking_allocator_no_metrics.cc index 2daa8e45f5..42c123269a 100644 --- a/pw_allocator/size_report/tracking_allocator_no_metrics.cc +++ b/pw_allocator/size_report/tracking_allocator_no_metrics.cc @@ -12,7 +12,7 @@ // License for the specific language governing permissions and limitations under // the License. -#include "pw_allocator/first_fit_block_allocator.h" +#include "pw_allocator/first_fit.h" #include "pw_allocator/metrics.h" #include "pw_allocator/size_reporter.h" #include "pw_allocator/tracking_allocator.h" @@ -21,7 +21,7 @@ int main() { pw::allocator::SizeReporter reporter; reporter.SetBaseline(); - pw::allocator::FirstFitBlockAllocator<> allocator(reporter.buffer()); + pw::allocator::FirstFitAllocator<> allocator(reporter.buffer()); pw::allocator::TrackingAllocator tracker(1, allocator); reporter.Measure(tracker); diff --git a/pw_allocator/tracking_allocator_test.cc b/pw_allocator/tracking_allocator_test.cc index 824bcd0efa..438be7b95e 100644 --- a/pw_allocator/tracking_allocator_test.cc +++ b/pw_allocator/tracking_allocator_test.cc @@ -16,6 +16,7 @@ #include #include "pw_allocator/allocator.h" +#include "pw_allocator/first_fit.h" #include "pw_allocator/metrics.h" #include "pw_allocator/testing.h" #include "pw_log/log.h" @@ -27,7 +28,6 @@ namespace { // Test fixtures. using ::pw::allocator::Layout; -// using ::pw::allocator::NoMetrics; using ::pw::allocator::TrackingAllocator; using TestMetrics = ::pw::allocator::internal::AllMetrics; @@ -44,8 +44,9 @@ class TrackingAllocatorForTest : public TrackingAllocator { class TrackingAllocatorTest : public ::testing::Test { protected: - using AllocatorType = ::pw::allocator::FirstFitBlockAllocator; - using BlockType = typename AllocatorType::BlockType; + using BlockType = ::pw::allocator::FirstFitBlock; + using AllocatorType = ::pw::allocator::FirstFitAllocator; + static_assert(sizeof(uintptr_t) >= BlockType::kAlignment); constexpr static size_t kCapacity = 256; constexpr static pw::metric::Token kToken = 1U; @@ -142,7 +143,7 @@ TEST_F(TrackingAllocatorTest, AllocateDeallocate) { const TestMetrics& metrics = tracker_.metrics(); ExpectedValues expected; - constexpr Layout layout1 = Layout::Of(); + constexpr Layout layout1 = Layout::Of(); void* ptr1 = tracker_.Allocate(layout1); size_t ptr1_allocated = tracker_.GetAllocatedLayout(ptr1)->size(); ASSERT_NE(ptr1, nullptr); @@ -162,7 +163,7 @@ TEST_F(TrackingAllocatorTest, AllocateFailure) { const TestMetrics& metrics = tracker_.metrics(); ExpectedValues expected; - constexpr Layout layout = Layout::Of(); + constexpr Layout layout = Layout::Of(); void* ptr = tracker_.Allocate(layout); EXPECT_EQ(ptr, nullptr); expected.num_failures += 1; @@ -174,7 +175,7 @@ TEST_F(TrackingAllocatorTest, AllocateDeallocateMultiple) { const TestMetrics& metrics = tracker_.metrics(); ExpectedValues expected; - Layout layout1 = Layout::Of(); + Layout layout1 = Layout::Of(); void* ptr1 = tracker_.Allocate(layout1); ASSERT_NE(ptr1, nullptr); size_t ptr1_allocated = tracker_.GetAllocatedLayout(ptr1)->size(); @@ -183,7 +184,7 @@ TEST_F(TrackingAllocatorTest, AllocateDeallocateMultiple) { expected.num_allocations += 1; EXPECT_METRICS_EQ(expected, metrics); - Layout layout2 = Layout::Of(); + Layout layout2 = Layout::Of(); void* ptr2 = tracker_.Allocate(layout2); ASSERT_NE(ptr2, nullptr); size_t ptr2_allocated = tracker_.GetAllocatedLayout(ptr2)->size(); @@ -198,7 +199,7 @@ TEST_F(TrackingAllocatorTest, AllocateDeallocateMultiple) { expected.num_deallocations += 1; EXPECT_METRICS_EQ(expected, metrics); - Layout layout3 = Layout::Of(); + Layout layout3 = Layout::Of(); void* ptr3 = tracker_.Allocate(layout3); ASSERT_NE(ptr3, nullptr); size_t ptr3_allocated = tracker_.GetAllocatedLayout(ptr3)->size(); @@ -224,7 +225,7 @@ TEST_F(TrackingAllocatorTest, ResizeLarger) { const TestMetrics& metrics = tracker_.metrics(); ExpectedValues expected; - constexpr Layout layout1 = Layout::Of(); + constexpr Layout layout1 = Layout::Of(); void* ptr = tracker_.Allocate(layout1); size_t ptr_allocated1 = tracker_.GetAllocatedLayout(ptr)->size(); ASSERT_NE(ptr, nullptr); @@ -233,7 +234,7 @@ TEST_F(TrackingAllocatorTest, ResizeLarger) { expected.num_allocations += 1; EXPECT_METRICS_EQ(expected, metrics); - constexpr size_t size2 = sizeof(uint32_t[5]); + constexpr size_t size2 = sizeof(uintptr_t[5]); EXPECT_TRUE(tracker_.Resize(ptr, size2)); size_t ptr_allocated2 = tracker_.GetAllocatedLayout(ptr)->size(); expected.AddRequestedBytes(size2 - layout1.size()); @@ -252,7 +253,7 @@ TEST_F(TrackingAllocatorTest, ResizeSmaller) { const TestMetrics& metrics = tracker_.metrics(); ExpectedValues expected; - constexpr Layout layout1 = Layout::Of(); + constexpr Layout layout1 = Layout::Of(); void* ptr = tracker_.Allocate(layout1); size_t ptr_allocated1 = tracker_.GetAllocatedLayout(ptr)->size(); ASSERT_NE(ptr, nullptr); @@ -261,7 +262,7 @@ TEST_F(TrackingAllocatorTest, ResizeSmaller) { expected.num_allocations += 1; EXPECT_METRICS_EQ(expected, metrics); - constexpr size_t size2 = sizeof(uint32_t[1]); + constexpr size_t size2 = sizeof(uintptr_t[1]); EXPECT_TRUE(tracker_.Resize(ptr, size2)); size_t ptr_allocated2 = tracker_.GetAllocatedLayout(ptr)->size(); expected.requested_bytes -= layout1.size() - size2; @@ -280,7 +281,7 @@ TEST_F(TrackingAllocatorTest, ResizeFailure) { const TestMetrics& metrics = tracker_.metrics(); ExpectedValues expected; - constexpr Layout layout = Layout::Of(); + constexpr Layout layout = Layout::Of(); void* ptr1 = tracker_.Allocate(layout); ASSERT_NE(ptr1, nullptr); size_t ptr1_allocated = tracker_.GetAllocatedLayout(ptr1)->size(); @@ -307,7 +308,7 @@ TEST_F(TrackingAllocatorTest, Reallocate) { const TestMetrics& metrics = tracker_.metrics(); ExpectedValues expected; - constexpr Layout layout1 = Layout::Of(); + constexpr Layout layout1 = Layout::Of(); void* ptr1 = tracker_.Allocate(layout1); ASSERT_NE(ptr1, nullptr); size_t ptr1_allocated = tracker_.GetAllocatedLayout(ptr1)->size(); @@ -317,7 +318,7 @@ TEST_F(TrackingAllocatorTest, Reallocate) { EXPECT_METRICS_EQ(expected, metrics); // If `Reallocate` just resizes, no extra memory is allocated - constexpr Layout layout2 = Layout::Of(); + constexpr Layout layout2 = Layout::Of(); void* ptr2 = tracker_.Reallocate(ptr1, layout2); EXPECT_EQ(ptr2, ptr1); size_t ptr2_allocated = tracker_.GetAllocatedLayout(ptr2)->size(); @@ -338,7 +339,7 @@ TEST_F(TrackingAllocatorTest, Reallocate) { // If `Reallocate` must copy to a new location, it allocates before // deallocating and results in higher peaks. - constexpr Layout layout4 = Layout::Of(); + constexpr Layout layout4 = Layout::Of(); void* ptr4 = tracker_.Reallocate(ptr2, layout4); EXPECT_NE(ptr4, ptr2); size_t ptr4_allocated = tracker_.GetAllocatedLayout(ptr4)->size(); @@ -365,7 +366,7 @@ TEST_F(TrackingAllocatorTest, ReallocateFailure) { const TestMetrics& metrics = tracker_.metrics(); ExpectedValues expected; - constexpr Layout layout1 = Layout::Of(); + constexpr Layout layout1 = Layout::Of(); void* ptr1 = tracker_.Allocate(layout1); ASSERT_NE(ptr1, nullptr); size_t ptr1_allocated = tracker_.GetAllocatedLayout(ptr1)->size(); diff --git a/pw_allocator/worst_fit_block_allocator_test.cc b/pw_allocator/worst_fit_block_allocator_test.cc index 0b2b24fd87..312b61da86 100644 --- a/pw_allocator/worst_fit_block_allocator_test.cc +++ b/pw_allocator/worst_fit_block_allocator_test.cc @@ -40,14 +40,14 @@ class WorstFitBlockAllocatorTest : public BlockAllocatorTest { // Unit tests. -TEST_F(WorstFitBlockAllocatorTest, CanAutomaticallyInit) { +TEST_F(WorstFitBlockAllocatorTest, AutomaticallyInit) { WorstFitBlockAllocator allocator(GetBytes()); - CanAutomaticallyInit(allocator); + AutomaticallyInit(allocator); } -TEST_F(WorstFitBlockAllocatorTest, CanExplicitlyInit) { +TEST_F(WorstFitBlockAllocatorTest, ExplicitlyInit) { WorstFitBlockAllocator allocator; - CanExplicitlyInit(allocator); + ExplicitlyInit(allocator); } TEST_F(WorstFitBlockAllocatorTest, GetCapacity) { GetCapacity(); } @@ -118,8 +118,8 @@ TEST_F(WorstFitBlockAllocatorTest, ResizeSmallLargerFailure) { ResizeSmallLargerFailure(); } -TEST_F(WorstFitBlockAllocatorTest, CanMeasureFragmentation) { - CanMeasureFragmentation(); +TEST_F(WorstFitBlockAllocatorTest, MeasureFragmentation) { + MeasureFragmentation(); } TEST_F(WorstFitBlockAllocatorTest, PoisonPeriodically) { PoisonPeriodically(); } diff --git a/pw_malloc/BUILD.bazel b/pw_malloc/BUILD.bazel index 57560dd3f9..a3033ea823 100644 --- a/pw_malloc/BUILD.bazel +++ b/pw_malloc/BUILD.bazel @@ -99,23 +99,31 @@ constraint_value( constraint_setting = "//pw_malloc:backend_constraint_setting", ) +constraint_value( + name = "first_fit_backend", + constraint_setting = "//pw_malloc:backend_constraint_setting", +) + +# TODO(b/376730645): Remove deprecated backends. constraint_value( name = "dual_first_fit_block_allocator_backend", constraint_setting = "//pw_malloc:backend_constraint_setting", ) +# TODO(b/376730645): Remove deprecated backends. constraint_value( name = "first_fit_block_allocator_backend", constraint_setting = "//pw_malloc:backend_constraint_setting", ) +# TODO(b/376730645): Remove deprecated backends. constraint_value( - name = "freelist_backend", + name = "last_fit_block_allocator_backend", constraint_setting = "//pw_malloc:backend_constraint_setting", ) constraint_value( - name = "last_fit_block_allocator_backend", + name = "freelist_backend", constraint_setting = "//pw_malloc:backend_constraint_setting", ) @@ -131,9 +139,9 @@ alias( "//pw_malloc:best_fit_block_allocator_backend": "//pw_malloc:best_fit_block_allocator", "//pw_malloc:bucket_allocator_backend": "//pw_malloc:bucket_allocator", "//pw_malloc:bucket_block_allocator_backend": "//pw_malloc:bucket_allocator", - "//pw_malloc:dual_first_fit_block_allocator_backend": "//pw_malloc:dual_first_fit_block_allocator", - "//pw_malloc:first_fit_block_allocator_backend": "//pw_malloc:first_fit_block_allocator", - "//pw_malloc:last_fit_block_allocator_backend": "//pw_malloc:last_fit_block_allocator", + "//pw_malloc:dual_first_fit_block_allocator_backend": "//pw_malloc:first_fit", + "//pw_malloc:first_fit_block_allocator_backend": "//pw_malloc:first_fit", + "//pw_malloc:last_fit_block_allocator_backend": "//pw_malloc:first_fit", "//pw_malloc:worst_fit_block_allocator_backend": "//pw_malloc:worst_fit_block_allocator", "//pw_malloc_freelist:backend": "//pw_malloc:bucket_allocator", "//pw_malloc_freertos:backend": "//pw_malloc_freertos", @@ -167,30 +175,30 @@ cc_library( ) cc_library( - name = "dual_first_fit_block_allocator", - srcs = ["dual_first_fit_block_allocator.cc"], + name = "first_fit", + srcs = ["first_fit.cc"], deps = [ - "//pw_allocator:dual_first_fit_block_allocator", + "//pw_allocator:first_fit", "//pw_malloc:facade", ], ) +# TODO(b/376730645): Remove deprecated backends. +cc_library( + name = "dual_first_fit_block_allocator", + deps = [":first_fit"], +) + +# TODO(b/376730645): Remove deprecated backends. cc_library( name = "first_fit_block_allocator", - srcs = ["first_fit_block_allocator.cc"], - deps = [ - "//pw_allocator:first_fit_block_allocator", - "//pw_malloc:facade", - ], + deps = [":first_fit"], ) +# TODO(b/376730645): Remove deprecated backends. cc_library( name = "last_fit_block_allocator", - srcs = ["last_fit_block_allocator.cc"], - deps = [ - "//pw_allocator:last_fit_block_allocator", - "//pw_malloc:facade", - ], + deps = [":first_fit"], ) cc_library( @@ -286,38 +294,14 @@ pw_cc_test( ) pw_cc_test( - name = "dual_first_fit_block_allocator_test", - srcs = [ - "dual_first_fit_block_allocator.cc", - "malloc_test.cc", - ], - deps = [ - ":testing", - "//pw_allocator:dual_first_fit_block_allocator", - ], -) - -pw_cc_test( - name = "first_fit_block_allocator_test", - srcs = [ - "first_fit_block_allocator.cc", - "malloc_test.cc", - ], - deps = [ - ":testing", - "//pw_allocator:first_fit_block_allocator", - ], -) - -pw_cc_test( - name = "last_fit_block_allocator_test", + name = "first_fit_test", srcs = [ - "last_fit_block_allocator.cc", + "first_fit.cc", "malloc_test.cc", ], deps = [ ":testing", - "//pw_allocator:last_fit_block_allocator", + "//pw_allocator:first_fit", ], ) diff --git a/pw_malloc/BUILD.gn b/pw_malloc/BUILD.gn index 15bdd892eb..cb8f853808 100644 --- a/pw_malloc/BUILD.gn +++ b/pw_malloc/BUILD.gn @@ -114,22 +114,25 @@ pw_source_set("bucket_block_allocator") { public_deps = [ ":bucket_allocator" ] } +# TODO(b/376730645): Remove deprecated backends. pw_source_set("dual_first_fit_block_allocator") { + public_deps = [ ":first_fit" ] +} + +pw_source_set("first_fit") { public_deps = [ ":pw_malloc.facade" ] - deps = [ "$dir_pw_allocator:dual_first_fit_block_allocator" ] - sources = [ "dual_first_fit_block_allocator.cc" ] + deps = [ "$dir_pw_allocator:first_fit" ] + sources = [ "first_fit.cc" ] } +# TODO(b/376730645): Remove deprecated backends. pw_source_set("first_fit_block_allocator") { - public_deps = [ ":pw_malloc.facade" ] - deps = [ "$dir_pw_allocator:first_fit_block_allocator" ] - sources = [ "first_fit_block_allocator.cc" ] + public_deps = [ ":first_fit" ] } +# TODO(b/376730645): Remove deprecated backends. pw_source_set("last_fit_block_allocator") { - public_deps = [ ":pw_malloc.facade" ] - deps = [ "$dir_pw_allocator:last_fit_block_allocator" ] - sources = [ "last_fit_block_allocator.cc" ] + public_deps = [ ":first_fit" ] } pw_source_set("worst_fit_block_allocator") { @@ -174,28 +177,12 @@ pw_test("bucket_allocator_test") { sources = [ "bucket_allocator.cc" ] } -pw_test("dual_first_fit_block_allocator_test") { - deps = [ - ":testing", - "$dir_pw_allocator:dual_first_fit_block_allocator", - ] - sources = [ "dual_first_fit_block_allocator.cc" ] -} - -pw_test("first_fit_block_allocator_test") { - deps = [ - ":testing", - "$dir_pw_allocator:first_fit_block_allocator", - ] - sources = [ "first_fit_block_allocator.cc" ] -} - -pw_test("last_fit_block_allocator_test") { +pw_test("first_fit_test") { deps = [ ":testing", - "$dir_pw_allocator:last_fit_block_allocator", + "$dir_pw_allocator:first_fit", ] - sources = [ "last_fit_block_allocator.cc" ] + sources = [ "first_fit.cc" ] } pw_test("worst_fit_block_allocator_test") { @@ -246,9 +233,7 @@ pw_test_group("tests") { tests = [ ":best_fit_block_allocator_test", ":bucket_allocator_test", - ":dual_first_fit_block_allocator_test", - ":first_fit_block_allocator_test", - ":last_fit_block_allocator_test", + ":first_fit_test", ":worst_fit_block_allocator_test", ] } diff --git a/pw_malloc/CMakeLists.txt b/pw_malloc/CMakeLists.txt index 47dcfc15b5..0088e6a16e 100644 --- a/pw_malloc/CMakeLists.txt +++ b/pw_malloc/CMakeLists.txt @@ -13,7 +13,6 @@ # the License. include($ENV{PW_ROOT}/pw_build/pigweed.cmake) -include($ENV{PW_ROOT}/pw_malloc/backend.cmake) pw_add_module_config(pw_malloc_CONFIG) @@ -91,31 +90,13 @@ pw_add_library(pw_malloc.bucket_block_allocator INTERFACE pw_allocator.bucket_allocator ) -pw_add_library(pw_malloc.dual_first_fit_block_allocator STATIC +pw_add_library(pw_malloc.first_fit STATIC PUBLIC_DEPS pw_malloc.facade PRIVATE_DEPS - pw_allocator.dual_first_fit_block_allocator + pw_allocator.first_fit SOURCES - dual_first_fit_block_allocator.cc -) - -pw_add_library(pw_malloc.first_fit_block_allocator STATIC - PUBLIC_DEPS - pw_malloc.facade - PRIVATE_DEPS - pw_allocator.first_fit_block_allocator - SOURCES - first_fit_block_allocator.cc -) - -pw_add_library(pw_malloc.last_fit_block_allocator STATIC - PUBLIC_DEPS - pw_malloc.facade - PRIVATE_DEPS - pw_allocator.last_fit_block_allocator - SOURCES - last_fit_block_allocator.cc + first_fit.cc ) pw_add_library(pw_malloc.worst_fit_block_allocator STATIC diff --git a/pw_malloc/dual_first_fit_block_allocator.cc b/pw_malloc/dual_first_fit_block_allocator.cc deleted file mode 100644 index 4061e128b7..0000000000 --- a/pw_malloc/dual_first_fit_block_allocator.cc +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright 2024 The Pigweed Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); you may not -// use this file except in compliance with the License. You may obtain a copy of -// the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -// License for the specific language governing permissions and limitations under -// the License. - -#include "pw_allocator/dual_first_fit_block_allocator.h" - -#include "pw_malloc/config.h" -#include "pw_malloc/malloc.h" - -namespace pw::malloc { -namespace { - -using DualFirstFitBlockAllocator = - ::pw::allocator::DualFirstFitBlockAllocator; - -DualFirstFitBlockAllocator& GetDualFirstFitBlockAllocator() { - static DualFirstFitBlockAllocator system_allocator; - return system_allocator; -} - -} // namespace - -void InitSystemAllocator(ByteSpan heap) { - auto& system_allocator = GetDualFirstFitBlockAllocator(); - system_allocator.set_threshold(PW_MALLOC_DUAL_FIRST_FIT_THRESHOLD); - system_allocator.Init(heap); -} - -Allocator* GetSystemAllocator() { - auto& system_allocator = GetDualFirstFitBlockAllocator(); - return &system_allocator; -} - -} // namespace pw::malloc diff --git a/pw_malloc/first_fit_block_allocator.cc b/pw_malloc/first_fit.cc similarity index 74% rename from pw_malloc/first_fit_block_allocator.cc rename to pw_malloc/first_fit.cc index 4e2cf03d89..f48b8b8ec8 100644 --- a/pw_malloc/first_fit_block_allocator.cc +++ b/pw_malloc/first_fit.cc @@ -12,22 +12,22 @@ // License for the specific language governing permissions and limitations under // the License. -#include "pw_allocator/first_fit_block_allocator.h" +#include "pw_allocator/first_fit.h" #include "pw_malloc/config.h" #include "pw_malloc/malloc.h" namespace pw::malloc { -using FirstFitBlockAllocator = - ::pw::allocator::FirstFitBlockAllocator; +using BlockType = ::pw::allocator::FirstFitBlock; +using FirstFitAllocator = ::pw::allocator::FirstFitAllocator; void InitSystemAllocator(ByteSpan heap) { - InitSystemAllocator(heap); + InitSystemAllocator(heap); } Allocator* GetSystemAllocator() { - static FirstFitBlockAllocator allocator; + static FirstFitAllocator allocator; return &allocator; } diff --git a/pw_malloc/last_fit_block_allocator.cc b/pw_malloc/last_fit_block_allocator.cc deleted file mode 100644 index 46ce4c9382..0000000000 --- a/pw_malloc/last_fit_block_allocator.cc +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright 2024 The Pigweed Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); you may not -// use this file except in compliance with the License. You may obtain a copy of -// the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -// License for the specific language governing permissions and limitations under -// the License. - -#include "pw_allocator/last_fit_block_allocator.h" - -#include "pw_malloc/config.h" -#include "pw_malloc/malloc.h" - -namespace pw::malloc { - -using LastFitBlockAllocator = - ::pw::allocator::LastFitBlockAllocator; - -void InitSystemAllocator(ByteSpan heap) { - InitSystemAllocator(heap); -} - -Allocator* GetSystemAllocator() { - static LastFitBlockAllocator allocator; - return &allocator; -} - -} // namespace pw::malloc