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 {
48template <
typename OffsetType_,
typename WhenFree>
50 using OffsetType = std::make_unsigned_t<OffsetType_>;
51 static constexpr Layout kLayoutWhenFree = Layout::Of<WhenFree>();
54template <
typename OffsetType_>
56 using OffsetType = std::make_unsigned_t<OffsetType_>;
80template <
typename Parameters>
82 :
public BasicBlock<DetailedBlockImpl<Parameters>>,
94 using OffsetType =
typename Parameters::OffsetType;
101 next_ =
static_cast<OffsetType
>(outer_size / Basic::kAlignment);
103 info_.alignment = Basic::kAlignment;
108 static constexpr size_t DefaultAlignment() {
109 return std::max(
alignof(OffsetType),
110 Parameters::kLayoutWhenFree.alignment());
112 static constexpr size_t BlockOverhead() {
return sizeof(
BlockType); }
113 static constexpr size_t MinInnerSize() {
return 1; }
114 static constexpr size_t ReservedWhenFree() {
115 return Parameters::kLayoutWhenFree.size();
117 constexpr size_t OuterSizeUnchecked()
const;
120 constexpr bool DoCheckInvariants(
bool strict)
const;
126 static constexpr size_t MaxAddressableSize() {
128 static_cast<size_t>(std::numeric_limits<OffsetType>::max());
129 auto kSizeMax =
static_cast<size_t>(std::numeric_limits<size_t>::max());
130 return std::min(kSizeMax / Basic::kAlignment, kOffsetMax) *
134 constexpr bool IsLastUnchecked()
const {
return info_.last != 0; }
136 constexpr void SetNext(
size_t outer_size,
BlockType* next);
137 constexpr size_t PrevOuterSizeUnchecked()
const;
140 constexpr BlockType* DoSplitFirst(
size_t new_inner_size);
141 constexpr BlockType* DoSplitLast(
size_t new_inner_size);
142 constexpr void DoMergeNext();
147 constexpr bool IsFreeUnchecked()
const {
return info_.used == 0; }
148 constexpr void SetFree(
bool is_free);
159 bool shifted =
false);
165 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>
218template <
typename Parameters>
220 size_t outer_size = next_;
221 Hardening::Multiply(outer_size, Basic::kAlignment);
225template <
typename Parameters>
226constexpr bool DetailedBlockImpl<Parameters>::DoCheckInvariants(
228 return Basic::DoCheckInvariants(strict) &&
229 Contiguous::DoCheckInvariants(strict) &&
230 Poisonable::DoCheckInvariants(strict);
235template <
typename Parameters>
236constexpr DetailedBlockImpl<Parameters>* DetailedBlockImpl<Parameters>::AsBlock(
238 return ::new (bytes.data()) DetailedBlockImpl(bytes.size());
241template <typename Parameters>
242constexpr
void DetailedBlockImpl<Parameters>::SetNext(
size_t outer_size,
244 next_ =
static_cast<OffsetType
>(outer_size / Basic::kAlignment);
245 if (next ==
nullptr) {
253template <
typename Parameters>
254constexpr size_t DetailedBlockImpl<Parameters>::PrevOuterSizeUnchecked()
const {
255 size_t outer_size = prev_;
256 Hardening::Multiply(outer_size, Basic::kAlignment);
260template <
typename Parameters>
261constexpr DetailedBlockImpl<Parameters>*
262DetailedBlockImpl<Parameters>::DoSplitFirst(
size_t new_inner_size) {
263 return Poisonable::DoSplitFirst(new_inner_size);
266template <
typename Parameters>
267constexpr DetailedBlockImpl<Parameters>*
268DetailedBlockImpl<Parameters>::DoSplitLast(
size_t new_inner_size) {
269 return Poisonable::DoSplitLast(new_inner_size);
272template <
typename Parameters>
273constexpr void DetailedBlockImpl<Parameters>::DoMergeNext() {
274 Poisonable::DoMergeNext();
279template <
typename Parameters>
280constexpr void DetailedBlockImpl<Parameters>::SetFree(
bool is_free) {
281 info_.used = !is_free;
283 Poisonable::SetFree(is_free);
288template <
typename Parameters>
289constexpr StatusWithSize DetailedBlockImpl<Parameters>::DoCanAlloc(
290 Layout layout)
const {
291 return Alignable::DoCanAlloc(layout);
294template <
typename Parameters>
295constexpr BlockResult<DetailedBlockImpl<Parameters>>
296DetailedBlockImpl<Parameters>::DoAllocFirst(DetailedBlockImpl*&& block,
298 return WithLayout::DoAllocFirst(std::move(block), layout);
301template <
typename Parameters>
302constexpr BlockResult<DetailedBlockImpl<Parameters>>
303DetailedBlockImpl<Parameters>::DoAllocLast(DetailedBlockImpl*&& block,
305 return WithLayout::DoAllocLast(std::move(block), layout);
308template <
typename Parameters>
309constexpr BlockResult<DetailedBlockImpl<Parameters>>
310DetailedBlockImpl<Parameters>::DoResize(
size_t new_inner_size,
bool shifted) {
311 return WithLayout::DoResize(new_inner_size, shifted);
314template <
typename Parameters>
315constexpr BlockResult<DetailedBlockImpl<Parameters>>
316DetailedBlockImpl<Parameters>::DoFree(DetailedBlockImpl*&& block) {
317 return WithLayout::DoFree(std::move(block));
322template <
typename Parameters>
323constexpr size_t DetailedBlockImpl<Parameters>::RequestedSize()
const {
324 if constexpr (Hardening::kIncludesDebugChecks) {
325 PW_ASSERT(padding_ <= Basic::InnerSize());
327 return Basic::InnerSize() - padding_;
330template <
typename Parameters>
331constexpr void DetailedBlockImpl<Parameters>::SetRequestedSize(
size_t size) {
332 size_t inner_size = Basic::InnerSize();
333 size_t padding = inner_size;
334 Hardening::Decrement(padding, size);
335 if constexpr (Hardening::kIncludesDebugChecks) {
336 PW_ASSERT(padding <= std::numeric_limits<uint16_t>::max());
338 padding_ =
static_cast<uint16_t
>(padding);
341template <
typename Parameters>
342constexpr void DetailedBlockImpl<Parameters>::SetRequestedAlignment(
344 if constexpr (Hardening::kIncludesDebugChecks) {
345 PW_ASSERT((alignment & (alignment - 1)) == 0);
346 PW_ASSERT(alignment < 0x2000);
348 info_.alignment =
static_cast<uint16_t
>(alignment);
Definition: status_with_size.h:51
Definition: alignable.h:44
Definition: allocatable.h:51
Definition: with_layout.h:50
Definition: contiguous.h:47
Definition: detailed_block.h:88
Definition: iterable.h:52
Definition: iterable.h:76
Definition: iterable.h:35
Definition: poisonable.h:53
Definition: detailed_block.h:49