xref: /llvm-project/libc/src/__support/block.h (revision e237e37c62804b5caa7ca5501d7372d7b01167ad)
1 //===-- Implementation header for a block of memory -------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #ifndef LLVM_LIBC_SRC___SUPPORT_BLOCK_H
10 #define LLVM_LIBC_SRC___SUPPORT_BLOCK_H
11 
12 #include "src/__support/CPP/algorithm.h"
13 #include "src/__support/CPP/cstddef.h"
14 #include "src/__support/CPP/limits.h"
15 #include "src/__support/CPP/new.h"
16 #include "src/__support/CPP/optional.h"
17 #include "src/__support/CPP/span.h"
18 #include "src/__support/CPP/type_traits.h"
19 #include "src/__support/libc_assert.h"
20 #include "src/__support/macros/config.h"
21 #include "src/__support/math_extras.h"
22 
23 #include <stdint.h>
24 
25 namespace LIBC_NAMESPACE_DECL {
26 
27 /// Returns the value rounded down to the nearest multiple of alignment.
28 LIBC_INLINE constexpr size_t align_down(size_t value, size_t alignment) {
29   // Note this shouldn't overflow since the result will always be <= value.
30   return (value / alignment) * alignment;
31 }
32 
33 /// Returns the value rounded up to the nearest multiple of alignment. May wrap
34 /// around.
35 LIBC_INLINE constexpr size_t align_up(size_t value, size_t alignment) {
36   return align_down(value + alignment - 1, alignment);
37 }
38 
39 using ByteSpan = cpp::span<LIBC_NAMESPACE::cpp::byte>;
40 using cpp::optional;
41 
42 /// Memory region with links to adjacent blocks.
43 ///
44 /// The blocks store their offsets to the previous and next blocks. The latter
45 /// is also the block's size.
46 ///
47 /// All blocks have their usable space aligned to some multiple of max_align_t.
48 /// This also implies that block outer sizes are aligned to max_align_t.
49 ///
50 /// As an example, the diagram below represents two contiguous `Block`s. The
51 /// indices indicate byte offsets:
52 ///
53 /// @code{.unparsed}
54 /// Block 1:
55 /// +---------------------+--------------+
56 /// | Header              | Usable space |
57 /// +----------+----------+--------------+
58 /// | prev     | next     |              |
59 /// | 0......3 | 4......7 | 8........227 |
60 /// | 00000000 | 00000230 |  <app data>  |
61 /// +----------+----------+--------------+
62 /// Block 2:
63 /// +---------------------+--------------+
64 /// | Header              | Usable space |
65 /// +----------+----------+--------------+
66 /// | prev     | next     |              |
67 /// | 0......3 | 4......7 | 8........827 |
68 /// | 00000230 | 00000830 | f7f7....f7f7 |
69 /// +----------+----------+--------------+
70 /// @endcode
71 ///
72 /// As a space optimization, when a block is allocated, it consumes the prev
73 /// field of the following block:
74 ///
75 /// Block 1 (used):
76 /// +---------------------+--------------+
77 /// | Header              | Usable space |
78 /// +----------+----------+--------------+
79 /// | prev     | next     |              |
80 /// | 0......3 | 4......7 | 8........230 |
81 /// | 00000000 | 00000230 |  <app data>  |
82 /// +----------+----------+--------------+
83 /// Block 2:
84 /// +---------------------+--------------+
85 /// | B1       | Header   | Usable space |
86 /// +----------+----------+--------------+
87 /// |          | next     |              |
88 /// | 0......3 | 4......7 | 8........827 |
89 /// | xxxxxxxx | 00000830 | f7f7....f7f7 |
90 /// +----------+----------+--------------+
91 ///
92 /// The next offset of a block matches the previous offset of its next block.
93 /// The first block in a list is denoted by having a previous offset of `0`.
94 class Block {
95   // Masks for the contents of the next_ field.
96   static constexpr size_t PREV_FREE_MASK = 1 << 0;
97   static constexpr size_t LAST_MASK = 1 << 1;
98   static constexpr size_t SIZE_MASK = ~(PREV_FREE_MASK | LAST_MASK);
99 
100 public:
101   // No copy or move.
102   Block(const Block &other) = delete;
103   Block &operator=(const Block &other) = delete;
104 
105   /// Initializes a given memory region into a first block and a sentinel last
106   /// block. Returns the first block, which has its usable space aligned to
107   /// max_align_t.
108   static optional<Block *> init(ByteSpan region);
109 
110   /// @returns  A pointer to a `Block`, given a pointer to the start of the
111   ///           usable space inside the block.
112   ///
113   /// This is the inverse of `usable_space()`.
114   ///
115   /// @warning  This method does not do any checking; passing a random
116   ///           pointer will return a non-null pointer.
117   LIBC_INLINE static Block *from_usable_space(void *usable_space) {
118     auto *bytes = reinterpret_cast<cpp::byte *>(usable_space);
119     return reinterpret_cast<Block *>(bytes - sizeof(Block));
120   }
121   LIBC_INLINE static const Block *from_usable_space(const void *usable_space) {
122     const auto *bytes = reinterpret_cast<const cpp::byte *>(usable_space);
123     return reinterpret_cast<const Block *>(bytes - sizeof(Block));
124   }
125 
126   /// @returns The total size of the block in bytes, including the header.
127   LIBC_INLINE size_t outer_size() const { return next_ & SIZE_MASK; }
128 
129   LIBC_INLINE static size_t outer_size(size_t inner_size) {
130     // The usable region includes the prev_ field of the next block.
131     return inner_size - sizeof(prev_) + sizeof(Block);
132   }
133 
134   /// @returns The number of usable bytes inside the block were it to be
135   /// allocated.
136   LIBC_INLINE size_t inner_size() const {
137     if (!next())
138       return 0;
139     return inner_size(outer_size());
140   }
141 
142   /// @returns The number of usable bytes inside a block with the given outer
143   /// size were it to be allocated.
144   LIBC_INLINE static size_t inner_size(size_t outer_size) {
145     // The usable region includes the prev_ field of the next block.
146     return inner_size_free(outer_size) + sizeof(prev_);
147   }
148 
149   /// @returns The number of usable bytes inside the block if it remains free.
150   LIBC_INLINE size_t inner_size_free() const {
151     if (!next())
152       return 0;
153     return inner_size_free(outer_size());
154   }
155 
156   /// @returns The number of usable bytes inside a block with the given outer
157   /// size if it remains free.
158   LIBC_INLINE static size_t inner_size_free(size_t outer_size) {
159     return outer_size - sizeof(Block);
160   }
161 
162   /// @returns A pointer to the usable space inside this block.
163   ///
164   /// Aligned to some multiple of max_align_t.
165   LIBC_INLINE cpp::byte *usable_space() {
166     auto *s = reinterpret_cast<cpp::byte *>(this) + sizeof(Block);
167     LIBC_ASSERT(reinterpret_cast<uintptr_t>(s) % alignof(max_align_t) == 0 &&
168                 "usable space must be aligned to a multiple of max_align_t");
169     return s;
170   }
171   LIBC_INLINE const cpp::byte *usable_space() const {
172     const auto *s = reinterpret_cast<const cpp::byte *>(this) + sizeof(Block);
173     LIBC_ASSERT(reinterpret_cast<uintptr_t>(s) % alignof(max_align_t) == 0 &&
174                 "usable space must be aligned to a multiple of max_align_t");
175     return s;
176   }
177 
178   // @returns The region of memory the block manages, including the header.
179   LIBC_INLINE ByteSpan region() {
180     return {reinterpret_cast<cpp::byte *>(this), outer_size()};
181   }
182 
183   /// Attempts to split this block.
184   ///
185   /// If successful, the block will have an inner size of at least
186   /// `new_inner_size`. The remaining space will be returned as a new block,
187   /// with usable space aligned to `usable_space_alignment`. Note that the prev_
188   /// field of the next block counts as part of the inner size of the block.
189   /// `usable_space_alignment` must be a multiple of max_align_t.
190   optional<Block *> split(size_t new_inner_size,
191                           size_t usable_space_alignment = alignof(max_align_t));
192 
193   /// Merges this block with the one that comes after it.
194   bool merge_next();
195 
196   /// @returns The block immediately after this one, or a null pointer if this
197   /// is the last block.
198   LIBC_INLINE Block *next() const {
199     if (next_ & LAST_MASK)
200       return nullptr;
201     return reinterpret_cast<Block *>(reinterpret_cast<uintptr_t>(this) +
202                                      outer_size());
203   }
204 
205   /// @returns The free block immediately before this one, otherwise nullptr.
206   LIBC_INLINE Block *prev_free() const {
207     if (!(next_ & PREV_FREE_MASK))
208       return nullptr;
209     return reinterpret_cast<Block *>(reinterpret_cast<uintptr_t>(this) - prev_);
210   }
211 
212   /// @returns Whether the block is unavailable for allocation.
213   LIBC_INLINE bool used() const { return !next() || !next()->prev_free(); }
214 
215   /// Marks this block as in use.
216   LIBC_INLINE void mark_used() {
217     LIBC_ASSERT(next() && "last block is always considered used");
218     next()->next_ &= ~PREV_FREE_MASK;
219   }
220 
221   /// Marks this block as free.
222   LIBC_INLINE void mark_free() {
223     LIBC_ASSERT(next() && "last block is always considered used");
224     next()->next_ |= PREV_FREE_MASK;
225     // The next block's prev_ field becomes alive, as it is no longer part of
226     // this block's used space.
227     *new (&next()->prev_) size_t = outer_size();
228   }
229 
230   LIBC_INLINE Block(size_t outer_size, bool is_last) : next_(outer_size) {
231     // Last blocks are not usable, so they need not have sizes aligned to
232     // max_align_t. Their lower bits must still be free, so they must be aligned
233     // to Block.
234     LIBC_ASSERT(
235         outer_size % (is_last ? alignof(Block) : alignof(max_align_t)) == 0 &&
236         "block sizes must be aligned");
237     LIBC_ASSERT(is_usable_space_aligned(alignof(max_align_t)) &&
238                 "usable space must be aligned to a multiple of max_align_t");
239     if (is_last)
240       next_ |= LAST_MASK;
241   }
242 
243   LIBC_INLINE bool is_usable_space_aligned(size_t alignment) const {
244     return reinterpret_cast<uintptr_t>(usable_space()) % alignment == 0;
245   }
246 
247   // Returns the minimum inner size necessary for a block of that size to
248   // always be able to allocate at the given size and alignment.
249   //
250   // Returns 0 if there is no such size.
251   LIBC_INLINE static size_t min_size_for_allocation(size_t alignment,
252                                                     size_t size) {
253     LIBC_ASSERT(alignment >= alignof(max_align_t) &&
254                 alignment % alignof(max_align_t) == 0 &&
255                 "alignment must be multiple of max_align_t");
256 
257     if (alignment == alignof(max_align_t))
258       return size;
259 
260     // We must create a new block inside this one (splitting). This requires a
261     // block header in addition to the requested size.
262     if (add_overflow(size, sizeof(Block), size))
263       return 0;
264 
265     // Beyond that, padding space may need to remain in this block to ensure
266     // that the usable space of the next block is aligned.
267     //
268     // Consider a position P of some lesser alignment, L, with maximal distance
269     // to the next position of some greater alignment, G, where G is a multiple
270     // of L. P must be one L unit past a G-aligned point. If it were one L-unit
271     // earlier, its distance would be zero. If it were one L-unit later, its
272     // distance would not be maximal. If it were not some integral number of L
273     // units away, it would not be L-aligned.
274     //
275     // So the maximum distance would be G - L. As a special case, if L is 1
276     // (unaligned), the max distance is G - 1.
277     //
278     // This block's usable space is aligned to max_align_t >= Block. With zero
279     // padding, the next block's usable space is sizeof(Block) past it, which is
280     // a point aligned to Block. Thus the max padding needed is alignment -
281     // alignof(Block).
282     if (add_overflow(size, alignment - alignof(Block), size))
283       return 0;
284     return size;
285   }
286 
287   // This is the return type for `allocate` which can split one block into up to
288   // three blocks.
289   struct BlockInfo {
290     // This is the newly aligned block. It will have the alignment requested by
291     // a call to `allocate` and at most `size`.
292     Block *block;
293 
294     // If the usable_space in the new block was not aligned according to the
295     // `alignment` parameter, we will need to split into this block and the
296     // `block` to ensure `block` is properly aligned. In this case, `prev` will
297     // be a pointer to this new "padding" block. `prev` will be nullptr if no
298     // new block was created or we were able to merge the block before the
299     // original block with the "padding" block.
300     Block *prev;
301 
302     // This is the remainder of the next block after splitting the `block`
303     // according to `size`. This can happen if there's enough space after the
304     // `block`.
305     Block *next;
306   };
307 
308   // Divide a block into up to 3 blocks according to `BlockInfo`. Behavior is
309   // undefined if allocation is not possible for the given size and alignment.
310   static BlockInfo allocate(Block *block, size_t alignment, size_t size);
311 
312   // These two functions may wrap around.
313   LIBC_INLINE static uintptr_t next_possible_block_start(
314       uintptr_t ptr, size_t usable_space_alignment = alignof(max_align_t)) {
315     return align_up(ptr + sizeof(Block), usable_space_alignment) -
316            sizeof(Block);
317   }
318   LIBC_INLINE static uintptr_t prev_possible_block_start(
319       uintptr_t ptr, size_t usable_space_alignment = alignof(max_align_t)) {
320     return align_down(ptr, usable_space_alignment) - sizeof(Block);
321   }
322 
323 private:
324   /// Construct a block to represent a span of bytes. Overwrites only enough
325   /// memory for the block header; the rest of the span is left alone.
326   LIBC_INLINE static Block *as_block(ByteSpan bytes) {
327     LIBC_ASSERT(reinterpret_cast<uintptr_t>(bytes.data()) % alignof(Block) ==
328                     0 &&
329                 "block start must be suitably aligned");
330     return ::new (bytes.data()) Block(bytes.size(), /*is_last=*/false);
331   }
332 
333   LIBC_INLINE static void make_last_block(cpp::byte *start) {
334     LIBC_ASSERT(reinterpret_cast<uintptr_t>(start) % alignof(Block) == 0 &&
335                 "block start must be suitably aligned");
336     ::new (start) Block(sizeof(Block), /*is_last=*/true);
337   }
338 
339   /// Offset from this block to the previous block. 0 if this is the first
340   /// block. This field is only alive when the previous block is free;
341   /// otherwise, its memory is reused as part of the previous block's usable
342   /// space.
343   size_t prev_ = 0;
344 
345   /// Offset from this block to the next block. Valid even if this is the last
346   /// block, since it equals the size of the block.
347   size_t next_ = 0;
348 
349   /// Information about the current state of the block is stored in the two low
350   /// order bits of the next_ value. These are guaranteed free by a minimum
351   /// alignment (and thus, alignment of the size) of 4. The lowest bit is the
352   /// `prev_free` flag, and the other bit is the `last` flag.
353   ///
354   /// * If the `prev_free` flag is set, the block isn't the first and the
355   ///   previous block is free.
356   /// * If the `last` flag is set, the block is the sentinel last block. It is
357   ///   summarily considered used and has no next block.
358 
359 public:
360   /// Only for testing.
361   static constexpr size_t PREV_FIELD_SIZE = sizeof(prev_);
362 };
363 
364 static_assert(alignof(Block) >= 4,
365               "at least 2 bits must be available in block sizes for flags");
366 
367 LIBC_INLINE
368 optional<Block *> Block::init(ByteSpan region) {
369   if (!region.data())
370     return {};
371 
372   uintptr_t start = reinterpret_cast<uintptr_t>(region.data());
373   uintptr_t end = start + region.size();
374   if (end < start)
375     return {};
376 
377   uintptr_t block_start = next_possible_block_start(start);
378   if (block_start < start)
379     return {};
380 
381   uintptr_t last_start = prev_possible_block_start(end);
382   if (last_start >= end)
383     return {};
384 
385   if (block_start + sizeof(Block) > last_start)
386     return {};
387 
388   auto *last_start_ptr = reinterpret_cast<cpp::byte *>(last_start);
389   Block *block =
390       as_block({reinterpret_cast<cpp::byte *>(block_start), last_start_ptr});
391   make_last_block(last_start_ptr);
392   block->mark_free();
393   return block;
394 }
395 
396 LIBC_INLINE
397 Block::BlockInfo Block::allocate(Block *block, size_t alignment, size_t size) {
398   LIBC_ASSERT(alignment % alignof(max_align_t) == 0 &&
399               "alignment must be a multiple of max_align_t");
400 
401   BlockInfo info{block, /*prev=*/nullptr, /*next=*/nullptr};
402 
403   if (!info.block->is_usable_space_aligned(alignment)) {
404     Block *original = info.block;
405     // The padding block has no minimum size requirement.
406     optional<Block *> maybe_aligned_block = original->split(0, alignment);
407     LIBC_ASSERT(maybe_aligned_block.has_value() &&
408                 "it should always be possible to split for alignment");
409 
410     if (Block *prev = original->prev_free()) {
411       // If there is a free block before this, we can merge the current one with
412       // the newly created one.
413       prev->merge_next();
414     } else {
415       info.prev = original;
416     }
417 
418     Block *aligned_block = *maybe_aligned_block;
419     LIBC_ASSERT(aligned_block->is_usable_space_aligned(alignment) &&
420                 "The aligned block isn't aligned somehow.");
421     info.block = aligned_block;
422   }
423 
424   // Now get a block for the requested size.
425   if (optional<Block *> next = info.block->split(size))
426     info.next = *next;
427 
428   return info;
429 }
430 
431 LIBC_INLINE
432 optional<Block *> Block::split(size_t new_inner_size,
433                                size_t usable_space_alignment) {
434   LIBC_ASSERT(usable_space_alignment % alignof(max_align_t) == 0 &&
435               "alignment must be a multiple of max_align_t");
436   if (used())
437     return {};
438 
439   // Compute the minimum outer size that produces a block of at least
440   // `new_inner_size`.
441   size_t min_outer_size = outer_size(cpp::max(new_inner_size, sizeof(prev_)));
442 
443   uintptr_t start = reinterpret_cast<uintptr_t>(this);
444   uintptr_t next_block_start =
445       next_possible_block_start(start + min_outer_size, usable_space_alignment);
446   if (next_block_start < start)
447     return {};
448   size_t new_outer_size = next_block_start - start;
449   LIBC_ASSERT(new_outer_size % alignof(max_align_t) == 0 &&
450               "new size must be aligned to max_align_t");
451 
452   if (outer_size() < new_outer_size ||
453       outer_size() - new_outer_size < sizeof(Block))
454     return {};
455 
456   ByteSpan new_region = region().subspan(new_outer_size);
457   next_ &= ~SIZE_MASK;
458   next_ |= new_outer_size;
459 
460   Block *new_block = as_block(new_region);
461   mark_free(); // Free status for this block is now stored in new_block.
462   new_block->next()->prev_ = new_region.size();
463 
464   LIBC_ASSERT(new_block->is_usable_space_aligned(usable_space_alignment) &&
465               "usable space must have requested alignment");
466   return new_block;
467 }
468 
469 LIBC_INLINE
470 bool Block::merge_next() {
471   if (used() || next()->used())
472     return false;
473   size_t new_size = outer_size() + next()->outer_size();
474   next_ &= ~SIZE_MASK;
475   next_ |= new_size;
476   next()->prev_ = new_size;
477   return true;
478 }
479 
480 } // namespace LIBC_NAMESPACE_DECL
481 
482 #endif // LLVM_LIBC_SRC___SUPPORT_BLOCK_H
483