21#include "lib/stdcompat/bit.h"
22#include "pw_allocator/hardening.h"
23#include "pw_bytes/alignment.h"
24#include "pw_result/result.h"
25#include "pw_status/status.h"
27namespace pw::allocator {
31template <
typename From,
typename To>
33 using type = std::conditional_t<std::is_const_v<From>,
35 std::remove_const_t<To>>;
38template <
typename From,
typename To>
39using copy_const_t =
typename CopyConst<From, To>::type;
41template <
typename From,
typename To>
42using copy_const_ptr_t =
43 std::add_pointer_t<typename CopyConst<std::remove_pointer_t<From>,
44 std::remove_pointer_t<To>>::type>;
94template <
typename Derived>
97 static constexpr size_t kAlignment = Derived::DefaultAlignment();
98 static constexpr size_t kBlockOverhead =
99 AlignUp(Derived::BlockOverhead(), kAlignment);
100 static constexpr size_t kMinOuterSize =
101 kBlockOverhead +
AlignUp(Derived::MinInnerSize(), kAlignment);
125 template <
typename Ptr>
132 constexpr std::byte* UsableSpaceUnchecked() {
133 return UsableSpaceUncheckedImpl(
this);
135 constexpr const std::byte* UsableSpaceUnchecked()
const {
136 return UsableSpaceUncheckedImpl(
this);
150 constexpr size_t InnerSizeUnchecked()
const;
168 constexpr const Derived* derived()
const {
169 return static_cast<const Derived*
>(
this);
173 template <
typename Ptr>
174 static constexpr internal::copy_const_ptr_t<Ptr, std::byte*>
175 UsableSpaceUncheckedImpl(Ptr block);
181struct is_block : std::is_base_of<internal::BasicBase, T> {};
193void CheckMisaligned(
const void* block,
bool is_aligned);
199template <
typename Derived>
202 if (region.size() <= Derived::kBlockOverhead) {
205 if (region.size() > Derived::MaxAddressableSize()) {
208 auto* block = Derived::AsBlock(region);
209 if constexpr (Hardening::kIncludesDebugChecks) {
210 block->CheckInvariants();
215template <
typename Derived>
216template <
typename Ptr>
217constexpr internal::copy_const_ptr_t<Ptr, Derived*>
219 using BlockPtr = internal::copy_const_ptr_t<Ptr, Derived*>;
220 auto addr = cpp20::bit_cast<uintptr_t>(usable_space);
221 Hardening::Decrement(addr, kBlockOverhead);
222 auto* block = std::launder(
reinterpret_cast<BlockPtr
>(addr));
223 if constexpr (Hardening::kIncludesBasicChecks) {
224 block->CheckInvariants();
229template <
typename Derived>
231 if constexpr (Hardening::kIncludesDebugChecks) {
234 return UsableSpaceUnchecked();
237template <
typename Derived>
239 if constexpr (Hardening::kIncludesDebugChecks) {
242 return UsableSpaceUnchecked();
245template <
typename Derived>
246template <
typename Ptr>
247constexpr internal::copy_const_ptr_t<Ptr, std::byte*>
248BasicBlock<Derived>::UsableSpaceUncheckedImpl(Ptr block) {
249 using BytePtr = internal::copy_const_ptr_t<Derived, std::byte*>;
250 auto addr = cpp20::bit_cast<uintptr_t>(block);
251 Hardening::Increment(addr, kBlockOverhead);
252 return cpp20::bit_cast<BytePtr>(addr);
255template <
typename Derived>
258 size_t outer_size = inner_size;
259 Hardening::Increment(outer_size, kBlockOverhead);
263template <
typename Derived>
266 size_t inner_size = outer_size;
267 Hardening::Decrement(inner_size, kBlockOverhead);
271template <
typename Derived>
273 if constexpr (Hardening::kIncludesDebugChecks) {
276 return derived()->OuterSizeUnchecked();
279template <
typename Derived>
281 if constexpr (Hardening::kIncludesDebugChecks) {
284 return InnerSizeUnchecked();
287template <
typename Derived>
289 return InnerSizeFromOuterSize(derived()->OuterSizeUnchecked());
292template <
typename Derived>
294 return derived()->DoCheckInvariants(
false);
297template <
typename Derived>
299 return derived()->DoCheckInvariants(
true);
302template <
typename Derived>
304 bool is_aligned = (cpp20::bit_cast<uintptr_t>(
this) % kAlignment) == 0;
305 if constexpr (Hardening::kIncludesDebugChecks) {
306 internal::CheckMisaligned(
this, is_aligned || !strict);
static constexpr Status OutOfRange()
Definition: status.h:267
static constexpr Status ResourceExhausted()
Definition: status.h:230
constexpr bool CheckInvariants() const
Like IsValid, but crashes if invalid.
Definition: basic.h:298
constexpr size_t OuterSize() const
Definition: basic.h:272
static constexpr Result< Derived * > Init(ByteSpan region)
Creates the first block for a given memory region.
Definition: basic.h:200
constexpr size_t InnerSize() const
Definition: basic.h:280
static constexpr size_t OuterSizeFromInnerSize(size_t inner_size)
Definition: basic.h:256
constexpr bool IsValid() const
Definition: basic.h:293
static constexpr size_t InnerSizeFromOuterSize(size_t outer_size)
Definition: basic.h:264
constexpr bool DoCheckInvariants(bool strict) const
Definition: basic.h:303
constexpr std::byte * UsableSpace()
Definition: basic.h:230
static constexpr internal::copy_const_ptr_t< Ptr, Derived * > FromUsableSpace(Ptr usable_space)
Definition: basic.h:218
constexpr bool is_block_v
Helper variable template for is_block<T>::value.
Definition: basic.h:185
ByteSpan GetAlignedSubspan(ByteSpan bytes, size_t alignment)
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
Helper type that copies const-qualifers between types.
Definition: basic.h:32