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