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);
133 template <
typename Ptr>
140 constexpr std::byte* UsableSpaceUnchecked() {
141 return UsableSpaceUncheckedImpl(
this);
143 constexpr const std::byte* UsableSpaceUnchecked()
const {
144 return UsableSpaceUncheckedImpl(
this);
158 constexpr size_t InnerSizeUnchecked()
const;
176 constexpr const Derived* derived()
const {
177 return static_cast<const Derived*
>(
this);
181 template <
typename Ptr>
182 static constexpr internal::copy_const_ptr_t<Ptr, std::byte*>
183 UsableSpaceUncheckedImpl(Ptr block);
189struct is_block : std::is_base_of<internal::BasicBase, T> {};
201void CheckMisaligned(
const void* block,
bool is_aligned);
207template <
typename Derived>
210 if (region.size() <= Derived::kBlockOverhead) {
211 return Status::ResourceExhausted();
213 if (region.size() > Derived::MaxAddressableSize()) {
214 return Status::OutOfRange();
216 auto* block = Derived::AsBlock(region);
217 if constexpr (Hardening::kIncludesDebugChecks) {
218 block->CheckInvariants();
223template <
typename Derived>
224template <
typename Ptr>
225constexpr internal::copy_const_ptr_t<Ptr, Derived*>
227 using BlockPtr = internal::copy_const_ptr_t<Ptr, Derived*>;
228 auto addr = cpp20::bit_cast<uintptr_t>(usable_space);
229 Hardening::Decrement(addr, kBlockOverhead);
230 auto* block = std::launder(
reinterpret_cast<BlockPtr
>(addr));
231 if constexpr (Hardening::kIncludesBasicChecks) {
232 block->CheckInvariants();
237template <
typename Derived>
239 if constexpr (Hardening::kIncludesDebugChecks) {
242 return UsableSpaceUnchecked();
245template <
typename Derived>
247 if constexpr (Hardening::kIncludesDebugChecks) {
250 return UsableSpaceUnchecked();
253template <
typename Derived>
254template <
typename Ptr>
255constexpr internal::copy_const_ptr_t<Ptr, std::byte*>
256BasicBlock<Derived>::UsableSpaceUncheckedImpl(Ptr block) {
257 using BytePtr = internal::copy_const_ptr_t<Derived, std::byte*>;
258 auto addr = cpp20::bit_cast<uintptr_t>(block);
259 Hardening::Increment(addr, kBlockOverhead);
260 return cpp20::bit_cast<BytePtr>(addr);
263template <
typename Derived>
266 size_t outer_size = inner_size;
267 Hardening::Increment(outer_size, kBlockOverhead);
271template <
typename Derived>
274 size_t inner_size = outer_size;
275 Hardening::Decrement(inner_size, kBlockOverhead);
279template <
typename Derived>
281 if constexpr (Hardening::kIncludesDebugChecks) {
284 return derived()->OuterSizeUnchecked();
287template <
typename Derived>
289 if constexpr (Hardening::kIncludesDebugChecks) {
292 return InnerSizeUnchecked();
295template <
typename Derived>
297 return InnerSizeFromOuterSize(derived()->OuterSizeUnchecked());
300template <
typename Derived>
302 return derived()->DoCheckInvariants(
false);
305template <
typename Derived>
307 return derived()->DoCheckInvariants(
true);
310template <
typename Derived>
312 bool is_aligned = (cpp20::bit_cast<uintptr_t>(
this) % kAlignment) == 0;
313 if constexpr (Hardening::kIncludesDebugChecks) {
314 internal::CheckMisaligned(
this, is_aligned || !strict);
constexpr bool CheckInvariants() const
Like IsValid, but crashes if invalid.
Definition: basic.h:306
constexpr size_t OuterSize() const
Definition: basic.h:280
static constexpr Result< Derived * > Init(ByteSpan region)
Creates the first block for a given memory region.
Definition: basic.h:208
constexpr size_t InnerSize() const
Definition: basic.h:288
static constexpr size_t OuterSizeFromInnerSize(size_t inner_size)
Definition: basic.h:264
constexpr bool IsValid() const
Definition: basic.h:301
static constexpr size_t InnerSizeFromOuterSize(size_t outer_size)
Definition: basic.h:272
constexpr bool DoCheckInvariants(bool strict) const
Definition: basic.h:311
constexpr std::byte * UsableSpace()
Definition: basic.h:238
static constexpr internal::copy_const_ptr_t< Ptr, Derived * > FromUsableSpace(Ptr usable_space)
Definition: basic.h:226
constexpr bool is_block_v
Helper variable template for is_block<T>::value.
Definition: basic.h:193
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:52
Helper type that copies const-qualifers between types.
Definition: basic.h:32