21#include "pw_allocator/block/alignable.h"
22#include "pw_allocator/block/allocatable.h"
23#include "pw_allocator/block/basic.h"
24#include "pw_allocator/block/contiguous.h"
25#include "pw_allocator/block/iterable.h"
26#include "pw_allocator/block/poisonable.h"
27#include "pw_allocator/block/result.h"
28#include "pw_allocator/block/with_layout.h"
29#include "pw_allocator/hardening.h"
30#include "pw_allocator/layout.h"
31#include "pw_assert/assert.h"
32#include "pw_bytes/span.h"
33#include "pw_status/status.h"
35namespace pw::allocator {
46template <
typename OffsetType_,
typename WhenFree>
48 using OffsetType = std::make_unsigned_t<OffsetType_>;
49 static constexpr Layout kLayoutWhenFree = Layout::Of<WhenFree>();
52template <
typename OffsetType_>
54 using OffsetType = std::make_unsigned_t<OffsetType_>;
78template <
typename Parameters>
80 :
public BasicBlock<DetailedBlockImpl<Parameters>>,
92 using OffsetType =
typename Parameters::OffsetType;
99 next_ = outer_size / Basic::kAlignment;
101 info_.alignment = Basic::kAlignment;
106 static constexpr size_t DefaultAlignment() {
107 return std::max(
alignof(OffsetType),
108 Parameters::kLayoutWhenFree.alignment());
110 static constexpr size_t BlockOverhead() {
return sizeof(
BlockType); }
111 static constexpr size_t MinInnerSize() {
return 1; }
112 static constexpr size_t ReservedWhenFree() {
113 return Parameters::kLayoutWhenFree.size();
115 constexpr size_t OuterSizeUnchecked()
const;
118 constexpr bool DoCheckInvariants(
bool strict)
const;
124 static constexpr size_t MaxAddressableSize() {
126 static_cast<size_t>(std::numeric_limits<OffsetType>::max());
127 auto kSizeMax =
static_cast<size_t>(std::numeric_limits<size_t>::max());
128 return std::min(kSizeMax / Basic::kAlignment, kOffsetMax) *
132 constexpr bool IsLastUnchecked()
const {
return info_.last != 0; }
133 static constexpr BlockType* AsBlock(ByteSpan bytes);
134 constexpr void SetNext(
size_t outer_size,
BlockType* next);
135 constexpr size_t PrevOuterSizeUnchecked()
const;
138 constexpr BlockType* DoSplitFirst(
size_t new_inner_size);
139 constexpr BlockType* DoSplitLast(
size_t new_inner_size);
140 constexpr void DoMergeNext();
145 constexpr bool IsFreeUnchecked()
const {
return info_.used == 0; }
146 constexpr void SetFree(
bool is_free);
157 bool shifted =
false);
163 constexpr size_t RequestedSize()
const {
166 constexpr size_t RequestedAlignment()
const {
return info_.alignment; }
167 constexpr void SetRequestedSize(
size_t size);
168 constexpr void SetRequestedAlignment(
size_t alignment);
173 constexpr bool IsPoisonedUnchecked()
const {
return info_.poisoned != 0; }
174 constexpr void SetPoisoned(
bool is_poisoned) { info_.poisoned = is_poisoned; }
178 OffsetType prev_ = 0;
183 OffsetType next_ = 0;
197 uint16_t poisoned : 1;
199 uint16_t alignment : 13;
204 uint16_t padding_ = 0;
208template <
typename OffsetType = u
intptr_t,
typename WhenFree =
void>
216template <
typename Parameters>
218 size_t outer_size = next_;
219 Hardening::Multiply(outer_size, Basic::kAlignment);
223template <
typename Parameters>
224constexpr bool DetailedBlockImpl<Parameters>::DoCheckInvariants(
226 return Basic::DoCheckInvariants(strict) &&
227 Contiguous::DoCheckInvariants(strict) &&
228 Poisonable::DoCheckInvariants(strict);
233template <
typename Parameters>
234constexpr DetailedBlockImpl<Parameters>* DetailedBlockImpl<Parameters>::AsBlock(
236 return ::new (bytes.data()) DetailedBlockImpl(bytes.size());
239template <typename Parameters>
240constexpr
void DetailedBlockImpl<Parameters>::SetNext(
size_t outer_size,
242 next_ = outer_size / Basic::kAlignment;
243 if (next ==
nullptr) {
251template <
typename Parameters>
252constexpr size_t DetailedBlockImpl<Parameters>::PrevOuterSizeUnchecked()
const {
253 size_t outer_size = prev_;
254 Hardening::Multiply(outer_size, Basic::kAlignment);
258template <
typename Parameters>
259constexpr DetailedBlockImpl<Parameters>*
260DetailedBlockImpl<Parameters>::DoSplitFirst(
size_t new_inner_size) {
261 return Poisonable::DoSplitFirst(new_inner_size);
264template <
typename Parameters>
265constexpr DetailedBlockImpl<Parameters>*
266DetailedBlockImpl<Parameters>::DoSplitLast(
size_t new_inner_size) {
267 return Poisonable::DoSplitLast(new_inner_size);
270template <
typename Parameters>
271constexpr void DetailedBlockImpl<Parameters>::DoMergeNext() {
272 Poisonable::DoMergeNext();
277template <
typename Parameters>
278constexpr void DetailedBlockImpl<Parameters>::SetFree(
bool is_free) {
279 info_.used = !is_free;
280 Poisonable::SetFree(is_free);
285template <
typename Parameters>
286constexpr StatusWithSize DetailedBlockImpl<Parameters>::DoCanAlloc(
287 Layout layout)
const {
288 return Alignable::DoCanAlloc(layout);
291template <
typename Parameters>
292constexpr BlockResult<DetailedBlockImpl<Parameters>>
293DetailedBlockImpl<Parameters>::DoAllocFirst(DetailedBlockImpl*&& block,
295 return WithLayout::DoAllocFirst(std::move(block), layout);
298template <
typename Parameters>
299constexpr BlockResult<DetailedBlockImpl<Parameters>>
300DetailedBlockImpl<Parameters>::DoAllocLast(DetailedBlockImpl*&& block,
302 return WithLayout::DoAllocLast(std::move(block), layout);
305template <
typename Parameters>
306constexpr BlockResult<DetailedBlockImpl<Parameters>>
307DetailedBlockImpl<Parameters>::DoResize(
size_t new_inner_size,
bool shifted) {
308 return WithLayout::DoResize(new_inner_size, shifted);
311template <
typename Parameters>
312constexpr BlockResult<DetailedBlockImpl<Parameters>>
313DetailedBlockImpl<Parameters>::DoFree(DetailedBlockImpl*&& block) {
314 return WithLayout::DoFree(std::move(block));
319template <
typename Parameters>
320constexpr void DetailedBlockImpl<Parameters>::SetRequestedSize(
size_t size) {
321 size_t inner_size = Basic::InnerSize();
322 size_t padding = inner_size;
323 Hardening::Decrement(padding, size);
324 if constexpr (Hardening::kIncludesDebugChecks) {
325 PW_ASSERT(padding <= std::numeric_limits<uint16_t>::max());
327 padding_ =
static_cast<uint16_t
>(padding);
330template <
typename Parameters>
331constexpr void DetailedBlockImpl<Parameters>::SetRequestedAlignment(
333 if constexpr (Hardening::kIncludesDebugChecks) {
334 PW_ASSERT((alignment & (alignment - 1)) == 0);
335 PW_ASSERT(alignment < 0x2000);
337 info_.alignment = alignment;
Definition: status_with_size.h:49
Definition: alignable.h:42
Definition: allocatable.h:49
constexpr size_t InnerSize() const
Definition: basic.h:284
Definition: with_layout.h:48
Definition: contiguous.h:45
Definition: detailed_block.h:86
Definition: iterable.h:50
Definition: iterable.h:74
Definition: iterable.h:33
Definition: poisonable.h:51
Definition: detailed_block.h:47