1 #ifndef HALIDE_RUNTIME_MEMORY_ARENA_H 2 #define HALIDE_RUNTIME_MEMORY_ARENA_H 4 #include "../HalideRuntime.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");
201 typename 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());
229 void 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;
242 bool 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);
260 MemoryArena::Block *MemoryArena::lookup_block(
void *user_context,
uint32_t index) {
261 return static_cast<Block *
>(blocks[index]);
264 void *MemoryArena::lookup_entry(
void *user_context, Block *block,
uint32_t index) {
270 void *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 280 void MemoryArena::destroy_entry(
void *user_context, Block *block,
uint32_t index) {
282 block->indices[index] = block->free_index;
283 block->free_index = index;
286 const typename MemoryArena::Config &
313 #endif // HALIDE_RUNTIME_MEMORY_ARENA_H static const SystemMemoryAllocatorFns & default_allocator()
void initialize(void *user_context, const Config &cfg, const SystemMemoryAllocatorFns &sma=default_allocator())
void halide_error(void *user_context, const char *)
Halide calls this function on runtime errors (for example bounds checking failures).
static MemoryArena * create(void *user_context, const Config &config, const SystemMemoryAllocatorFns &allocator=default_allocator())
static const Config & default_config()
static void destroy(void *user_context, MemoryArena *arena)
void reclaim(void *user_context, void *ptr)
DeallocateSystemFn deallocate
#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...
This file defines the class FunctionDAG, which is our representation of a Halide pipeline, and contains methods to using Halide's bounds tools to query properties of it.
unsigned __INT8_TYPE__ uint8_t
uint32_t minimum_block_capacity
void destroy(void *user_context)
unsigned __INT32_TYPE__ uint32_t
MemoryArena & operator=(const MemoryArena &)=delete
Not visible externally, similar to 'static' linkage in C.
const SystemMemoryAllocatorFns & current_allocator() const
AllocateSystemFn allocate
MemoryArena(const MemoryArena &)=delete
ALWAYS_INLINE const void * offset_address(const void *address, size_t byte_offset)
void remove(void *user_context, size_t index)
const Config & current_config() const
void append(void *user_context, const void *entry_ptr)
void * memset(void *s, int val, size_t n)
static constexpr uint32_t default_capacity
uint32_t maximum_block_count
static const SystemMemoryAllocatorFns & default_allocator()
bool collect(void *user_context)
const SystemMemoryAllocatorFns & current_allocator() const
void initialize(void *user_context, const Config &config, const SystemMemoryAllocatorFns &allocator=default_allocator())
void * reserve(void *user_context, bool initialize=false)