21#include "lib/stdcompat/bit.h"
22#include "pw_allocator/block/contiguous.h"
23#include "pw_allocator/config.h"
25namespace pw::allocator {
52template <
typename Derived>
56 static_assert(is_contiguous_v<Derived>,
57 "Types derived from PoisonableBlock must also derive from "
62 static constexpr size_t kPoisonOffset = Derived::ReservedWhenFree();
66 return derived()->DoGetPoisonWord();
81 constexpr uintptr_t DoGetPoisonWord()
const {
83 return static_cast<uintptr_t
>(0xAD5bE10DDCCEFADEULL);
102 constexpr Derived* derived() {
return static_cast<Derived*
>(
this); }
103 constexpr const Derived* derived()
const {
104 return static_cast<const Derived*
>(
this);
109 constexpr uintptr_t* PoisonableBegin()
const;
113 constexpr uintptr_t* PoisonableEnd()
const;
117template <
typename BlockType>
118struct is_poisonable : std::is_base_of<internal::PoisonableBase, BlockType> {};
121template <
typename BlockType>
130void CheckPoisonedWhileInUse(
const void* block,
bool is_free);
134void CheckPoisonCorrupted(
const void* block,
bool pattern_is_intact);
140template <
typename Derived>
142 if constexpr (Hardening::kIncludesDebugChecks) {
143 derived()->CheckInvariants();
145 return derived()->IsPoisonedUnchecked();
148template <
typename Derived>
150 if constexpr (Hardening::kIncludesDebugChecks) {
151 derived()->CheckInvariants();
153 auto* begin = PoisonableBegin();
154 auto* end = PoisonableEnd();
156 std::fill(begin, end, derived()->GetPoisonWord());
157 derived()->SetPoisoned(
true);
159 if constexpr (Hardening::kIncludesDebugChecks) {
160 derived()->CheckInvariants();
164template <
typename Derived>
166 size_t new_inner_size) {
167 bool should_poison = derived()->IsPoisoned();
168 derived()->SetPoisoned(
false);
170 derived()->ContiguousBlock<Derived>::DoSplitFirst(new_inner_size);
172 trailing->SetPoisoned(
true);
177template <
typename Derived>
179 size_t new_inner_size) {
180 bool should_poison = derived()->IsPoisoned();
181 derived()->SetPoisoned(
false);
183 derived()->ContiguousBlock<Derived>::DoSplitLast(new_inner_size);
185 derived()->SetPoisoned(
true);
190template <
typename Derived>
193 derived()->SetPoisoned(
false);
194 derived()->ContiguousBlock<Derived>::DoMergeNext();
197template <
typename Derived>
199 if (!derived()->IsPoisonedUnchecked()) {
203 bool valid = derived()->IsFreeUnchecked();
204 if constexpr (Hardening::kIncludesDebugChecks) {
205 internal::CheckPoisonedWhileInUse(
this, valid || !strict);
208 auto* begin = PoisonableBegin();
209 auto* end = PoisonableEnd();
211 valid &= std::all_of(
212 begin, end, [
this](uintptr_t word) {
return word == GetPoisonWord(); });
214 if constexpr (Hardening::kIncludesDebugChecks) {
215 internal::CheckPoisonCorrupted(
this, valid || !strict);
221template <
typename Derived>
224 derived()->SetPoisoned(
false);
228template <
typename Derived>
230 auto addr = cpp20::bit_cast<uintptr_t>(derived()->UsableSpaceUnchecked());
231 addr =
AlignUp(addr + kPoisonOffset,
sizeof(uintptr_t*));
232 return cpp20::bit_cast<uintptr_t*>(addr);
235template <
typename Derived>
236constexpr uintptr_t* PoisonableBlock<Derived>::PoisonableEnd()
const {
237 auto addr = cpp20::bit_cast<uintptr_t>(derived()->UsableSpaceUnchecked());
238 addr =
AlignDown(addr + derived()->InnerSizeUnchecked(),
sizeof(uintptr_t*));
239 return cpp20::bit_cast<uintptr_t*>(addr);
Definition: poisonable.h:53
constexpr void SetFree(bool is_free)
Clears the poisoned state if a block is not free.
Definition: poisonable.h:222
constexpr Derived * DoSplitLast(size_t new_inner_size)
Definition: poisonable.h:178
constexpr void DoMergeNext()
Definition: poisonable.h:191
constexpr bool DoCheckInvariants(bool strict) const
Like IsValid, but crashes if invalid.
Definition: poisonable.h:198
constexpr Derived * DoSplitFirst(size_t new_inner_size)
Definition: poisonable.h:165
constexpr void Poison()
Definition: poisonable.h:149
constexpr uintptr_t GetPoisonWord() const
Returns the value written to a block's usable space when poisoning.
Definition: poisonable.h:65
constexpr bool IsPoisoned() const
Returns whether this block has been poisoned.
Definition: poisonable.h:141
constexpr bool is_poisonable_v
Helper variable template for is_poisonable<BlockType>::value.
Definition: poisonable.h:122
constexpr size_t AlignUp(uintptr_t value, size_t alignment)
Returns the value rounded up to the nearest multiple of alignment.
Definition: alignment.h:54
constexpr size_t AlignDown(uintptr_t value, size_t alignment)
Returns the value rounded down to the nearest multiple of alignment.
Definition: alignment.h:42
Definition: poisonable.h:29
Trait type that allow interrogating a block as to whether it is poisonable.
Definition: poisonable.h:118