21#include "lib/stdcompat/bit.h"
22#include "pw_allocator/block/contiguous.h"
23#include "pw_allocator/config.h"
25namespace pw::allocator {
50template <
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 {
110 auto addr = cpp20::bit_cast<uintptr_t>(derived()->UsableSpaceUnchecked());
111 addr =
AlignUp(addr + kPoisonOffset,
sizeof(uintptr_t*));
112 return cpp20::bit_cast<uintptr_t*>(addr);
117 constexpr uintptr_t* PoisonableEnd()
const {
118 auto addr = cpp20::bit_cast<uintptr_t>(derived()->UsableSpaceUnchecked());
120 AlignDown(addr + derived()->InnerSizeUnchecked(),
sizeof(uintptr_t*));
121 return cpp20::bit_cast<uintptr_t*>(addr);
126template <
typename BlockType>
127struct is_poisonable : std::is_base_of<internal::PoisonableBase, BlockType> {};
130template <
typename BlockType>
137void CheckPoisonedWhileInUse(
const void* block,
bool is_free);
141void CheckPoisonCorrupted(
const void* block,
bool pattern_is_intact);
147template <
typename Derived>
149 if constexpr (Hardening::kIncludesDebugChecks) {
150 derived()->CheckInvariants();
152 return derived()->IsPoisonedUnchecked();
155template <
typename Derived>
157 if constexpr (Hardening::kIncludesDebugChecks) {
158 derived()->CheckInvariants();
160 auto* begin = PoisonableBegin();
161 auto* end = PoisonableEnd();
163 std::fill(begin, end, derived()->GetPoisonWord());
164 derived()->SetPoisoned(
true);
166 if constexpr (Hardening::kIncludesDebugChecks) {
167 derived()->CheckInvariants();
171template <
typename Derived>
173 size_t new_inner_size) {
174 bool should_poison = derived()->IsPoisoned();
175 derived()->SetPoisoned(
false);
177 derived()->ContiguousBlock<Derived>::DoSplitFirst(new_inner_size);
179 trailing->SetPoisoned(
true);
184template <
typename Derived>
186 size_t new_inner_size) {
187 bool should_poison = derived()->IsPoisoned();
188 derived()->SetPoisoned(
false);
190 derived()->ContiguousBlock<Derived>::DoSplitLast(new_inner_size);
192 derived()->SetPoisoned(
true);
197template <
typename Derived>
200 derived()->SetPoisoned(
false);
201 derived()->ContiguousBlock<Derived>::DoMergeNext();
204template <
typename Derived>
206 if (!derived()->IsPoisonedUnchecked()) {
210 bool valid = derived()->IsFreeUnchecked();
211 if constexpr (Hardening::kIncludesDebugChecks) {
212 internal::CheckPoisonedWhileInUse(
this, valid || !strict);
215 auto* begin = PoisonableBegin();
216 auto* end = PoisonableEnd();
218 valid &= std::all_of(
219 begin, end, [
this](uintptr_t word) {
return word == GetPoisonWord(); });
221 if constexpr (Hardening::kIncludesDebugChecks) {
222 internal::CheckPoisonCorrupted(
this, valid || !strict);
228template <
typename Derived>
231 derived()->SetPoisoned(
false);
Definition: poisonable.h:51
constexpr void SetFree(bool is_free)
Clears the poisoned state if a block is not free.
Definition: poisonable.h:229
constexpr Derived * DoSplitLast(size_t new_inner_size)
Definition: poisonable.h:185
constexpr void DoMergeNext()
Definition: poisonable.h:198
constexpr bool DoCheckInvariants(bool strict) const
Like IsValid, but crashes if invalid.
Definition: poisonable.h:205
constexpr Derived * DoSplitFirst(size_t new_inner_size)
Definition: poisonable.h:172
constexpr void Poison()
Definition: poisonable.h:156
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:148
constexpr size_t AlignUp(uintptr_t value, size_t alignment)
Returns the value rounded up to the nearest multiple of alignment.
Definition: alignment.h:52
constexpr size_t AlignDown(uintptr_t value, size_t alignment)
Returns the value rounded down to the nearest multiple of alignment.
Definition: alignment.h:39
Definition: poisonable.h:29
Trait type that allow interrogating a block as to whether it is poisonable.
Definition: poisonable.h:127