//===-- Implementation header for a block of memory -------------*- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// #ifndef LLVM_LIBC_SRC___SUPPORT_BLOCK_H #define LLVM_LIBC_SRC___SUPPORT_BLOCK_H #include "src/__support/CPP/algorithm.h" #include "src/__support/CPP/cstddef.h" #include "src/__support/CPP/limits.h" #include "src/__support/CPP/new.h" #include "src/__support/CPP/optional.h" #include "src/__support/CPP/span.h" #include "src/__support/CPP/type_traits.h" #include "src/__support/libc_assert.h" #include "src/__support/macros/config.h" #include <stdint.h> namespace LIBC_NAMESPACE_DECL { namespace internal { // Types of corrupted blocks, and functions to crash with an error message // corresponding to each type. enum class BlockStatus { … }; } // namespace internal /// Returns the value rounded down to the nearest multiple of alignment. LIBC_INLINE constexpr size_t align_down(size_t value, size_t alignment) { … } /// Returns the value rounded down to the nearest multiple of alignment. template <typename T> LIBC_INLINE constexpr T *align_down(T *value, size_t alignment) { … } /// Returns the value rounded up to the nearest multiple of alignment. LIBC_INLINE constexpr size_t align_up(size_t value, size_t alignment) { … } /// Returns the value rounded up to the nearest multiple of alignment. template <typename T> LIBC_INLINE constexpr T *align_up(T *value, size_t alignment) { … } ByteSpan; optional; /// Memory region with links to adjacent blocks. /// /// The blocks store their offsets to the previous and next blocks. The latter /// is also the block's size. /// /// The `ALIGNMENT` constant provided by the derived block is typically the /// minimum value of `alignof(OffsetType)`. Blocks will always be aligned to a /// `ALIGNMENT` boundary. Block sizes will always be rounded up to a multiple of /// `ALIGNMENT`. /// /// As an example, the diagram below represents two contiguous /// `Block<uint32_t, 8>`s. The indices indicate byte offsets: /// /// @code{.unparsed} /// Block 1: /// +---------------------+--------------+ /// | Header | Usable space | /// +----------+----------+--------------+ /// | prev | next | | /// | 0......3 | 4......7 | 8........227 | /// | 00000000 | 00000230 | <app data> | /// +----------+----------+--------------+ /// Block 2: /// +---------------------+--------------+ /// | Header | Usable space | /// +----------+----------+--------------+ /// | prev | next | | /// | 0......3 | 4......7 | 8........827 | /// | 00000230 | 00000830 | f7f7....f7f7 | /// +----------+----------+--------------+ /// @endcode /// /// As a space optimization, when a block is allocated, it consumes the prev /// field of the following block: /// /// Block 1 (used): /// +---------------------+--------------+ /// | Header | Usable space | /// +----------+----------+--------------+ /// | prev | next | | /// | 0......3 | 4......7 | 8........230 | /// | 00000000 | 00000230 | <app data> | /// +----------+----------+--------------+ /// Block 2: /// +---------------------+--------------+ /// | B1 | Header | Usable space | /// +----------+----------+--------------+ /// | | next | | /// | 0......3 | 4......7 | 8........827 | /// | xxxxxxxx | 00000830 | f7f7....f7f7 | /// +----------+----------+--------------+ /// /// The next offset of a block matches the previous offset of its next block. /// The first block in a list is denoted by having a previous offset of `0`. /// /// @tparam OffsetType Unsigned integral type used to encode offsets. Larger /// types can address more memory, but consume greater /// overhead. /// @tparam kAlign Sets the overall alignment for blocks. Minimum is /// `alignof(OffsetType)`, but the default is max_align_t, /// since the usable space will then already be /// aligned to max_align_t if the size of OffsetType is no /// less than half of max_align_t. Larger values cause /// greater overhead. template <typename OffsetType = uintptr_t, size_t kAlign = alignof(max_align_t)> class Block { … } __attribute__((packed, aligned …)); // Public template method implementations. LIBC_INLINE ByteSpan get_aligned_subspan(ByteSpan bytes, size_t alignment) { … } template <typename OffsetType, size_t kAlign> optional<Block<OffsetType, kAlign> *> Block<OffsetType, kAlign>::init(ByteSpan region) { … } template <typename OffsetType, size_t kAlign> bool Block<OffsetType, kAlign>::can_allocate(size_t alignment, size_t size) const { … } template <typename OffsetType, size_t kAlign> typename Block<OffsetType, kAlign>::BlockInfo Block<OffsetType, kAlign>::allocate(Block *block, size_t alignment, size_t size) { … } template <typename OffsetType, size_t kAlign> optional<Block<OffsetType, kAlign> *> Block<OffsetType, kAlign>::split(size_t new_inner_size) { … } template <typename OffsetType, size_t kAlign> Block<OffsetType, kAlign> * Block<OffsetType, kAlign>::split_impl(size_t new_inner_size) { … } template <typename OffsetType, size_t kAlign> bool Block<OffsetType, kAlign>::merge_next() { … } template <typename OffsetType, size_t kAlign> Block<OffsetType, kAlign> *Block<OffsetType, kAlign>::next() const { … } template <typename OffsetType, size_t kAlign> Block<OffsetType, kAlign> *Block<OffsetType, kAlign>::prev_free() const { … } // Private template method implementations. template <typename OffsetType, size_t kAlign> constexpr Block<OffsetType, kAlign>::Block(size_t outer_size) : … { … } template <typename OffsetType, size_t kAlign> Block<OffsetType, kAlign> *Block<OffsetType, kAlign>::as_block(ByteSpan bytes) { … } } // namespace LIBC_NAMESPACE_DECL #endif // LLVM_LIBC_SRC___SUPPORT_BLOCK_H