[libc-commits] [libc] [libc] Add aligned_alloc (PR #96586)

Nick Desaulniers via libc-commits libc-commits at lists.llvm.org
Wed Jun 26 08:53:31 PDT 2024


================
@@ -567,3 +569,201 @@ TEST_FOR_EACH_BLOCK_TYPE(CanGetConstBlockFromUsableSpace) {
   const BlockType *block2 = BlockType::from_usable_space(ptr);
   EXPECT_EQ(block1, block2);
 }
+
+TEST_FOR_EACH_BLOCK_TYPE(CanAllocate) {
+  constexpr size_t kN = 1024;
+
+  // Ensure we can allocate everything up to the block size within this block.
+  for (size_t i = 0; i < kN - BlockType::BLOCK_OVERHEAD; ++i) {
+    alignas(BlockType::ALIGNMENT) array<byte, kN> bytes{};
+    auto result = BlockType::init(bytes);
+    ASSERT_TRUE(result.has_value());
+    BlockType *block = *result;
+
+    constexpr size_t kAlign = 1; // Effectively ignores alignmenr.
+    EXPECT_TRUE(block->can_allocate(kAlign, i));
+
+    // For each can_allocate, we should be able to do a successful call to
+    // allocate.
+    BlockType *prev = nullptr;
+    BlockType *next = nullptr;
+    BlockType::allocate(block, kAlign, i, prev, next);
+    EXPECT_NE(block, static_cast<BlockType *>(nullptr));
+  }
+
+  alignas(BlockType::ALIGNMENT) array<byte, kN> bytes{};
+  auto result = BlockType::init(bytes);
+  ASSERT_TRUE(result.has_value());
+  BlockType *block = *result;
+
+  // Given a block of size kN (assuming it's also a power of two), we should be
+  // able to allocate a block within it that's aligned to half its size. This is
+  // because regardless of where the buffer is located, we can always find a
+  // starting location within it that meets this alignment.
+  EXPECT_TRUE(block->can_allocate(kN / 2, 1));
+}
+
+TEST_FOR_EACH_BLOCK_TYPE(AllocateAlreadyAligned) {
+  constexpr size_t kN = 1024;
+
+  alignas(BlockType::ALIGNMENT) array<byte, kN> bytes{};
+  auto result = BlockType::init(bytes);
+  ASSERT_TRUE(result.has_value());
+  BlockType *block = *result;
+
+  // This should result in no new blocks.
+  constexpr size_t kAlignment = BlockType::ALIGNMENT;
+  constexpr size_t kExpectedSize = BlockType::ALIGNMENT;
+  EXPECT_TRUE(block->can_allocate(kAlignment, kExpectedSize));
+
+  BlockType *prev = nullptr;
+  BlockType *next = nullptr;
+  BlockType::allocate(block, BlockType::ALIGNMENT, kExpectedSize, prev, next);
+
+  // Since this is already aligned, there should be no previous block.
+  EXPECT_EQ(prev, static_cast<BlockType *>(nullptr));
+
+  // Ensure we the block is aligned and the size we expect.
+  EXPECT_NE(block, static_cast<BlockType *>(nullptr));
+  EXPECT_TRUE(block->usable_space_is_aligned(BlockType::ALIGNMENT));
+  EXPECT_EQ(block->inner_size(), kExpectedSize);
+
+  // Check the next block.
+  EXPECT_NE(next, static_cast<BlockType *>(nullptr));
+  EXPECT_EQ(block->next(), next);
+  EXPECT_EQ(next->next(), static_cast<BlockType *>(nullptr));
+  EXPECT_EQ(reinterpret_cast<byte *>(next) + next->outer_size(), &*bytes.end());
----------------
nickdesaulniers wrote:

Our `cpp::array::end` returns a `T*`, so indeed this looks like an explicit derefence to me.

https://github.com/llvm/llvm-project/pull/96586


More information about the libc-commits mailing list