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

Nick Desaulniers via libc-commits libc-commits at lists.llvm.org
Tue Jun 25 09:02:00 PDT 2024


================
@@ -357,6 +392,58 @@ void Block<OffsetType, kAlign>::free(Block *&block) {
   merge_next(block);
 }
 
+template <typename OffsetType, size_t kAlign>
+bool Block<OffsetType, kAlign>::can_allocate(size_t alignment,
+                                             size_t size) const {
+  if (usable_space_is_aligned(alignment) && inner_size() >= size)
+    return true; // Size and alignment constraints met.
+
+  // Either the alignment isn't met or we don't have enough size.
+  // If we don't meet alignment, we can always adjust such that we do meet the
+  // alignment. If we meet the alignment but just don't have enough size. This
+  // check will fail anyway.
+  size_t adjustment = extra_space_for_adjustment(alignment);
+  if (inner_size() >= size + adjustment)
+    return true;
+
+  return false;
+}
+
+template <typename OffsetType, size_t kAlign>
+void Block<OffsetType, kAlign>::allocate(Block *&block, size_t alignment,
+                                         size_t size, Block *&new_prev,
+                                         Block *&new_next) {
+  if (!block->usable_space_is_aligned(alignment)) {
+    size_t adjustment = block->extra_space_for_adjustment(alignment);
+    size_t new_inner_size = adjustment - BLOCK_OVERHEAD;
+    LIBC_ASSERT(new_inner_size % ALIGNMENT == 0 &&
+                "The adjustment calculation should always return a new size "
+                "that's a multiple of ALIGNMENT");
+
+    Block *aligned_block = *Block::split(block, adjustment - BLOCK_OVERHEAD);
+    LIBC_ASSERT(aligned_block->usable_space_is_aligned(alignment) &&
+                "The aligned block isn't aligned somehow.");
+
+    Block *prev = block->prev();
+    if (prev) {
+      // If there is a block before this, we can merge the current one with the
+      // newly created one.
+      merge_next(prev);
+    } else {
+      // Otherwise, this was the very first block in the chain. Now we can make
+      // it the new first block.
+      new_prev = block;
+    }
+
+    block = aligned_block;
+  }
+
+  // Now get a block for the requested size.
+  optional<Block *> next = Block::split(block, size);
+  if (next)
+    new_next = *next;
----------------
nickdesaulniers wrote:

```suggestion
  if (optional<Block *> next = Block::split(block, size))
    new_next = *next;
```

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


More information about the libc-commits mailing list