1#ifndef HALIDE_RUNTIME_MEMORY_ARENA_H
2#define HALIDE_RUNTIME_MEMORY_ARENA_H
48 void reclaim(
void *user_context,
void *ptr);
49 bool collect(
void *user_context);
50 void destroy(
void *user_context);
69 void *entries =
nullptr;
76 Block *create_block(
void *user_context);
77 bool collect_block(
void *user_context, Block *block);
78 void destroy_block(
void *user_context, Block *block);
79 Block *lookup_block(
void *user_context,
uint32_t index);
81 void *create_entry(
void *user_context, Block *block,
uint32_t index);
82 void destroy_entry(
void *user_context, Block *block,
uint32_t index);
83 void *lookup_entry(
void *user_context, Block *block,
uint32_t index);
93 blocks(user_context, {
sizeof(MemoryArena::Block), 32, 32}, alloc) {
106 if (result ==
nullptr) {
107 halide_error(user_context,
"MemoryArena: Failed to create instance! Out of memory!\n");
111 result->
initialize(user_context, cfg, system_allocator);
118 instance->
destroy(user_context);
120 system_allocator.
deallocate(user_context, instance);
127 blocks.
initialize(user_context, {
sizeof(MemoryArena::Block), 32, 32}, system_allocator);
132 if (!blocks.
empty()) {
133 for (
size_t i = blocks.
size(); i--;) {
134 Block *block = lookup_block(user_context, i);
136 destroy_block(user_context, block);
144 for (
size_t i = blocks.
size(); i--;) {
145 Block *block = lookup_block(user_context, i);
147 if (collect_block(user_context, block)) {
148 blocks.
remove(user_context, i);
157 for (
size_t i = blocks.
size(); i--;) {
158 Block *block = lookup_block(user_context, i);
160 if (block->free_index != invalid_entry) {
161 return create_entry(user_context, block, block->free_index);
166 halide_error(user_context,
"MemoryArena: Failed to reserve new entry! Maxmimum blocks reached!\n");
172 Block *block = create_block(user_context);
173 void *entry_ptr = create_entry(user_context, block, index);
183 for (
size_t i = blocks.
size(); i--;) {
184 Block *block = lookup_block(user_context, i);
191 if ((entry_ptr >= base_ptr) && (entry_ptr < end_ptr)) {
194 destroy_entry(user_context, block, index);
198 halide_error(user_context,
"MemoryArena: Pointer address doesn't belong to this memory pool!\n");
201typename MemoryArena::Block *MemoryArena::create_block(
void *user_context) {
204 if (!blocks.
empty()) {
205 const Block *last_block =
static_cast<Block *
>(blocks.
back());
206 new_capacity = (last_block->capacity * 3 / 2);
216 for (
uint32_t i = 0; i < new_capacity - 1; ++i) {
217 new_indices[i] = i + 1;
221 new_indices[new_capacity - 1] = invalid_entry;
224 const Block new_block = {new_entries, new_indices, new_status, new_capacity, 0};
225 blocks.
append(user_context, &new_block);
226 return static_cast<Block *
>(blocks.
back());
229void MemoryArena::destroy_block(
void *user_context, Block *block) {
231 if (block->entries !=
nullptr) {
236 block->entries =
nullptr;
237 block->indices =
nullptr;
238 block->status =
nullptr;
242bool MemoryArena::collect_block(
void *user_context, Block *block) {
244 if (block->entries !=
nullptr) {
245 bool can_collect =
true;
246 for (
size_t i = block->capacity; i--;) {
253 destroy_block(user_context, block);
260MemoryArena::Block *MemoryArena::lookup_block(
void *user_context,
uint32_t index) {
261 return static_cast<Block *
>(blocks[index]);
264void *MemoryArena::lookup_entry(
void *user_context, Block *block,
uint32_t index) {
270void *MemoryArena::create_entry(
void *user_context, Block *block,
uint32_t index) {
271 void *entry_ptr = lookup_entry(user_context, block, index);
272 block->free_index = block->indices[index];
274#ifdef DEBUG_RUNTIME_INTERNAL
280void MemoryArena::destroy_entry(
void *user_context, Block *block,
uint32_t index) {
282 block->indices[index] = block->free_index;
283 block->free_index = index;
286const typename MemoryArena::Config &
This file declares the routines used by Halide internally in its runtime.
void halide_error(void *user_context, const char *)
Halide calls this function on runtime errors (for example bounds checking failures).
void destroy(void *user_context)
void remove(void *user_context, size_t index)
void initialize(void *user_context, const Config &cfg, const SystemMemoryAllocatorFns &sma=default_allocator())
static const SystemMemoryAllocatorFns & default_allocator()
const SystemMemoryAllocatorFns & current_allocator() const
void append(void *user_context, const void *entry_ptr)
void initialize(void *user_context, const Config &config, const SystemMemoryAllocatorFns &allocator=default_allocator())
void * reserve(void *user_context, bool initialize=false)
static MemoryArena * create(void *user_context, const Config &config, const SystemMemoryAllocatorFns &allocator=default_allocator())
const Config & current_config() const
static constexpr uint32_t default_capacity
const SystemMemoryAllocatorFns & current_allocator() const
static const Config & default_config()
static void destroy(void *user_context, MemoryArena *arena)
MemoryArena(const MemoryArena &)=delete
void reclaim(void *user_context, void *ptr)
bool collect(void *user_context)
MemoryArena & operator=(const MemoryArena &)=delete
static const SystemMemoryAllocatorFns & default_allocator()
ALWAYS_INLINE const void * offset_address(const void *address, size_t byte_offset)
This file defines the class FunctionDAG, which is our representation of a Halide pipeline,...
@ Internal
Not visible externally, similar to 'static' linkage in C.
#define halide_debug_assert(user_context, cond)
halide_debug_assert() is like halide_assert(), but only expands into a check when DEBUG_RUNTIME is de...
unsigned __INT8_TYPE__ uint8_t
void * memset(void *s, int val, size_t n)
unsigned __INT32_TYPE__ uint32_t
uint32_t maximum_block_count
uint32_t minimum_block_capacity
DeallocateSystemFn deallocate
AllocateSystemFn allocate