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 {
168 constexpr size_t RequestedAlignment()
const {
return info_.alignment; }
169 constexpr void SetRequestedSize(
size_t size);
170 constexpr void SetRequestedAlignment(
size_t alignment);
175 constexpr bool IsPoisonedUnchecked()
const {
return info_.poisoned != 0; }
176 constexpr void SetPoisoned(
bool is_poisoned) { info_.poisoned = is_poisoned; }
180 OffsetType prev_ = 0;
185 OffsetType next_ = 0;
199 uint16_t poisoned : 1;
201 uint16_t alignment : 13;
206 uint16_t padding_ = 0;
210template <
typename OffsetType = u
intptr_t,
typename WhenFree =
void>
220template <
typename Parameters>
222 size_t outer_size = next_;
223 Hardening::Multiply(outer_size, Basic::kAlignment);
227template <
typename Parameters>
228constexpr bool DetailedBlockImpl<Parameters>::DoCheckInvariants(
230 return Basic::DoCheckInvariants(strict) &&
231 Contiguous::DoCheckInvariants(strict) &&
232 Poisonable::DoCheckInvariants(strict);
237template <
typename Parameters>
238constexpr DetailedBlockImpl<Parameters>* DetailedBlockImpl<Parameters>::AsBlock(
240 return ::new (bytes.data()) DetailedBlockImpl(bytes.size());
243template <typename Parameters>
244constexpr
void DetailedBlockImpl<Parameters>::SetNext(
size_t outer_size,
246 next_ =
static_cast<OffsetType
>(outer_size / Basic::kAlignment);
247 if (next ==
nullptr) {
255template <
typename Parameters>
256constexpr size_t DetailedBlockImpl<Parameters>::PrevOuterSizeUnchecked()
const {
257 size_t outer_size = prev_;
258 Hardening::Multiply(outer_size, Basic::kAlignment);
262template <
typename Parameters>
263constexpr DetailedBlockImpl<Parameters>*
264DetailedBlockImpl<Parameters>::DoSplitFirst(
size_t new_inner_size) {
265 return Poisonable::DoSplitFirst(new_inner_size);
268template <
typename Parameters>
269constexpr DetailedBlockImpl<Parameters>*
270DetailedBlockImpl<Parameters>::DoSplitLast(
size_t new_inner_size) {
271 return Poisonable::DoSplitLast(new_inner_size);
274template <
typename Parameters>
275constexpr void DetailedBlockImpl<Parameters>::DoMergeNext() {
276 Poisonable::DoMergeNext();
281template <
typename Parameters>
282constexpr void DetailedBlockImpl<Parameters>::SetFree(
bool is_free) {
283 info_.used = !is_free;
284 Poisonable::SetFree(is_free);
289template <
typename Parameters>
290constexpr StatusWithSize DetailedBlockImpl<Parameters>::DoCanAlloc(
291 Layout layout)
const {
292 return Alignable::DoCanAlloc(layout);
295template <
typename Parameters>
296constexpr BlockResult<DetailedBlockImpl<Parameters>>
297DetailedBlockImpl<Parameters>::DoAllocFirst(DetailedBlockImpl*&& block,
299 return WithLayout::DoAllocFirst(std::move(block), layout);
302template <
typename Parameters>
303constexpr BlockResult<DetailedBlockImpl<Parameters>>
304DetailedBlockImpl<Parameters>::DoAllocLast(DetailedBlockImpl*&& block,
306 return WithLayout::DoAllocLast(std::move(block), layout);
309template <
typename Parameters>
310constexpr BlockResult<DetailedBlockImpl<Parameters>>
311DetailedBlockImpl<Parameters>::DoResize(
size_t new_inner_size,
bool shifted) {
312 return WithLayout::DoResize(new_inner_size, shifted);
315template <
typename Parameters>
316constexpr BlockResult<DetailedBlockImpl<Parameters>>
317DetailedBlockImpl<Parameters>::DoFree(DetailedBlockImpl*&& block) {
318 return WithLayout::DoFree(std::move(block));
323template <
typename Parameters>
324constexpr void DetailedBlockImpl<Parameters>::SetRequestedSize(
size_t size) {
325 size_t inner_size = Basic::InnerSize();
326 size_t padding = inner_size;
327 Hardening::Decrement(padding, size);
328 if constexpr (Hardening::kIncludesDebugChecks) {
329 PW_ASSERT(padding <= std::numeric_limits<uint16_t>::max());
331 padding_ =
static_cast<uint16_t
>(padding);
334template <
typename Parameters>
335constexpr void DetailedBlockImpl<Parameters>::SetRequestedAlignment(
337 if constexpr (Hardening::kIncludesDebugChecks) {
338 PW_ASSERT((alignment & (alignment - 1)) == 0);
339 PW_ASSERT(alignment < 0x2000);
341 info_.alignment =
static_cast<uint16_t
>(alignment);
Definition: status_with_size.h:51
Definition: alignable.h:44
Definition: allocatable.h:51
constexpr size_t InnerSize() const
Definition: basic.h:288
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