Pigweed
|
#include <block.h>
Classes | |
class | Iterator |
class | Range |
class | ReverseIterator |
class | ReverseRange |
Public Types | |
using | offset_type = OffsetType |
Public Member Functions | |
Block (const Block &other)=delete | |
Block & | operator= (const Block &other)=delete |
size_t | OuterSize () const |
size_t | InnerSize () const |
size_t | RequestedSize () const |
std::byte * | UsableSpace () |
const std::byte * | UsableSpace () const |
StatusWithSize | CanAllocLast (Layout layout) const |
Block * | Next () const |
Block * | Prev () const |
size_t | Alignment () const |
Returns the current alignment of a block. | |
bool | Used () const |
bool | Last () const |
void | MarkUsed () |
Marks this block as in use. | |
void | MarkFree () |
Marks this block as free. | |
void | MarkLast () |
Marks this block as the last one in the chain. | |
void | ClearLast () |
Clears the last bit from this block. | |
void | Poison (bool should_poison=true) |
bool | IsValid () const |
Checks if a block is valid. | |
void | CrashIfInvalid () const |
Crashes with an informtaional message if a block is invalid. | |
Static Public Member Functions | |
static Result< Block * > | Init (ByteSpan region) |
Creates the first block for a given memory region. | |
template<int &... DeducedTypesOnly, typename PtrType , bool is_const_ptr = std::is_const_v<std::remove_pointer_t<PtrType>>, typename BytesPtr = std::conditional_t<is_const_ptr, const std::byte*, std::byte*>, typename BlockPtr = std::conditional_t<is_const_ptr, const Block*, Block*>> | |
static BlockPtr | FromUsableSpace (PtrType usable_space) |
static Status | AllocFirst (Block *&block, Layout layout) |
static Status | AllocLast (Block *&block, Layout layout) |
static void | Free (Block *&block) |
static Status | Resize (Block *&block, size_t new_inner_size) |
static Block * | NextBlock (const Block *block) |
static Block * | PrevBlock (const Block *block) |
Static Public Attributes | |
static constexpr size_t | kAlignment = std::max(kAlign, alignof(offset_type)) |
static constexpr size_t | kBlockOverhead = AlignUp(sizeof(Block), kAlignment) |
Memory region with links to adjacent blocks.
The blocks do not encode their size directly. Instead, they encode offsets to the next and previous blocks using the type given by the OffsetType
template parameter. The encoded offsets are simply the offsets divded by the minimum block alignment, kAlignment
.
The kAlignment
constant provided by the derived block is typically the minimum value of alignof(OffsetType)
. Since the addressable range of a block is given by std::numeric_limits<OffsetType>::max() * kAlignment
, it may be advantageous to set a higher alignment if it allows using a smaller offset type, even if this wastes some bytes in order to align block headers.
Blocks will always be aligned to a kAlignment
boundary. Block sizes will always be rounded up to a multiple of kAlignment
.
If kCanPoison
is set, allocators may call Poison
to overwrite the contents of a block with a poison pattern. This pattern will subsequently be checked when allocating blocks, and can detect memory corruptions such as use-after-frees.
As an example, the diagram below represents two contiguous Block<uint32_t, true, 8>
s. The indices indicate byte offsets:
The overall size of the block (e.g. 280 bytes) is given by its next offset multiplied by the alignment (e.g. 0x106 * 4). Also, the next offset of a block matches the previous offset of its next block. The first block in a list is denoted by having a previous offset of 0
.
OffsetType | Unsigned integral type used to encode offsets. Larger types can address more memory, but consume greater overhead. |
kCanPoison | Indicates whether to enable poisoning free blocks. |
kAlign | Sets the overall alignment for blocks. Minimum is alignof(OffsetType) (the default). Larger values can address more memory, but consume greater overhead. |
|
static |
Splits an aligned block from the start of the block, and marks it as used.
If successful, block
will be replaced by a block that has an inner size of at least inner_size
, and whose starting address is aligned to an alignment
boundary. If unsuccessful, block
will be unmodified.
This method is static in order to consume and replace the given block pointer with a pointer to the new, smaller block. In total, up to two additional blocks may be created: one to pad the returned block to an alignment boundary and one for the trailing space.
embed:rst:leading-asterisk * * .. pw-status-codes:: * * OK: The split completed successfully. * * FAILED_PRECONDITION: This block is in use and cannot be split. * * OUT_OF_RANGE: The requested size plus padding needed for alignment * is greater than the current size. * *
|
static |
Splits an aligned block from the end of the block, and marks it as used.
If successful, block
will be replaced by a block that has an inner size of at least inner_size
, and whose starting address is aligned to an alignment
boundary. If unsuccessful, block
will be unmodified.
This method is static in order to consume and replace the given block pointer with a pointer to the new, smaller block. An additional block may be created for the leading space.
embed:rst:leading-asterisk * * .. pw-status-codes:: * * OK: The split completed successfully. * * FAILED_PRECONDITION: This block is in use and cannot be split. * * OUT_OF_RANGE: The requested size is greater than the current size. * * RESOURCE_EXHAUSTED: The remaining space is too small to hold a new * block. * *
StatusWithSize pw::allocator::Block< OffsetType, kAlign, kCanPoison >::CanAllocLast | ( | Layout | layout | ) | const |
Checks if an aligned block could be split from the end of the block.
On error, this method will return the same status as AllocLast
without performing any modifications.
embed:rst:leading-asterisk * * .. pw-status-codes:: * * OK: Returns the number of bytes to shift this block in order to align * its usable space. * * FAILED_PRECONDITION: This block is in use and cannot be split. * * OUT_OF_RANGE: The requested size is greater than the current size. * * RESOURCE_EXHAUSTED: The remaining space is too small to hold a * new block. * *
void pw::allocator::Block< OffsetType, kAlign, kCanPoison >::CrashIfInvalid |
Crashes with an informtaional message if a block is invalid.
Does nothing if the block is valid.
|
static |
Marks the block as free and merges it with any free neighbors.
This method is static in order to consume and replace the given block pointer. If neither member is free, the returned pointer will point to the original block. Otherwise, it will point to the new, larger block created by merging adjacent free blocks together.
|
inlinestatic |
Block
, given a pointer to the start of the usable space inside the block.This is the inverse of UsableSpace()
.
|
static |
Creates the first block for a given memory region.
embed:rst:leading-asterisk * * .. pw-status-codes:: * * OK: Returns a block representing the region. * * INVALID_ARGUMENT: The region is null. * * RESOURCE_EXHAUSTED: The region is too small for a block. * * OUT_OF_RANGE: The region is too big to be addressed using * ``OffsetType``. * *
|
inline |
|
inline |
Checks if a block is valid.
true
if and only if the following conditions are met:
|
inline |
Block< OffsetType, kAlign, kCanPoison > * pw::allocator::Block< OffsetType, kAlign, kCanPoison >::Next |
Fetches the block immediately after this one.
For performance, this always returns a block pointer, even if the returned pointer is invalid. The pointer is valid if and only if Last()
is false.
Typically, after calling Init
callers may save a pointer past the end of the list using Next()
. This makes it easy to subsequently iterate over the list:
|
inlinestatic |
|
inline |
void pw::allocator::Block< OffsetType, kAlign, kCanPoison >::Poison | ( | bool | should_poison = true | ) |
Poisons the block's usable space.
This method does nothing if kCanPoison
is false, or if the block is in use, or if should_poison
is false. The decision to poison a block is deferred to the allocator to allow for more nuanced strategies than simply all or nothing. For example, an allocator may want to balance security and performance by only poisoning every n-th free block.
should_poison | Indicates tha block should be poisoned, if poisoning is enabled. |
Block< OffsetType, kAlign, kCanPoison > * pw::allocator::Block< OffsetType, kAlign, kCanPoison >::Prev |
|
inlinestatic |
|
inline |
|
static |
Grows or shrinks the block.
If successful, block
may be merged with the block after it in order to provide additional memory (when growing) or to merge released memory (when shrinking). If unsuccessful, block
will be unmodified.
This method is static in order to consume and replace the given block pointer with a pointer to the new, smaller block.
embed:rst:leading-asterisk * * .. pw-status-codes:: * * OK: The resize completed successfully. * * FAILED_PRECONDITION: This block is not in use. * * OUT_OF_RANGE: The requested size is greater than the available space. * *
|
inline |
|
inline |
Indicates whether the block is in use.
true
if the block is in use or false
if not.