1#ifndef HALIDE_RUNTIME_BLOCK_ALLOCATOR_H
2#define HALIDE_RUNTIME_BLOCK_ALLOCATOR_H
111 size_t constrain_requested_size(
size_t size)
const;
129 if (result ==
nullptr) {
130 error(
user_context) <<
"BlockAllocator: Failed to create instance! Out of memory\n";
146void BlockAllocator::initialize(
void *
user_context,
const Config &cfg,
const MemoryAllocators &ma) {
156#ifdef DEBUG_RUNTIME_INTERNAL
161 <<
"dedicated=" << (request.
dedicated ?
"true" :
"false") <<
" "
168 if (block_entry ==
nullptr) {
169 error(
user_context) <<
"BlockAllocator: Failed to allocate new empty block of requested size ("
180 if (result ==
nullptr) {
183 block_entry = create_block_entry(
user_context, request);
184 if (block_entry ==
nullptr) {
185 error(
user_context) <<
"BlockAllocator: Out of memory! Failed to allocate empty block of size ("
201 if (memory_region ==
nullptr) {
212 if (memory_region ==
nullptr) {
223 if (memory_region ==
nullptr) {
236 while (block_entry !=
nullptr) {
240 block_entry = prev_entry;
244#ifdef DEBUG_RUNTIME_INTERNAL
250#ifdef DEBUG_RUNTIME_INTERNAL
252 <<
"block=" << (
void *)block <<
" "
263 block_entry = prev_entry;
270 while (block_entry !=
nullptr) {
273 block_entry = prev_entry;
280 while (block_entry !=
nullptr) {
283 block_entry = prev_entry;
291 if (result ==
nullptr) {
292#ifdef DEBUG_RUNTIME_INTERNAL
293 debug(
user_context) <<
"BlockAllocator: Failed to allocate region of size ("
305bool BlockAllocator::is_block_suitable_for_request(
void *
user_context,
const BlockResource *block,
const MemoryRequest &request)
const {
306 if (!is_compatible_block(block, request.properties)) {
307#ifdef DEBUG_RUNTIME_INTERNAL
308 debug(
user_context) <<
"BlockAllocator: skipping block ... incompatible properties! ("
309 <<
"block_resource=" << (
void *)block <<
" "
310 <<
"block_size=" << (
uint32_t)block->memory.size <<
" "
311 <<
"block_reserved=" << (
uint32_t)block->reserved <<
" "
315 <<
"request_size=" << (
uint32_t)request.size <<
" "
324 if (request.dedicated && (block->reserved > 0)) {
325#ifdef DEBUG_RUNTIME_INTERNAL
326 debug(
user_context) <<
"BlockAllocator: skipping block ... can be used for dedicated allocation! ("
327 <<
"block_resource=" << (
void *)block <<
" "
328 <<
"block_size=" << (
uint32_t)block->memory.size <<
" "
329 <<
"block_reserved=" << (
uint32_t)block->reserved <<
")";
334 }
else if (block->memory.dedicated && (block->reserved > 0)) {
335#ifdef DEBUG_RUNTIME_INTERNAL
336 debug(
user_context) <<
"BlockAllocator: skipping block ... already dedicated to an allocation! ("
337 <<
"block_resource=" << (
void *)block <<
" "
338 <<
"block_size=" << (
uint32_t)block->memory.size <<
" "
339 <<
"block_reserved=" << (
uint32_t)block->reserved <<
")";
345 size_t available = (block->memory.size - block->reserved);
346 if (available >= request.size) {
353BlockAllocator::BlockEntry *
354BlockAllocator::find_block_entry(
void *
user_context,
const MemoryRequest &request) {
355 BlockEntry *block_entry = block_list.
back();
356 while (block_entry !=
nullptr) {
357 BlockEntry *prev_entry = block_entry->
prev_ptr;
358 const BlockResource *block =
static_cast<BlockResource *
>(block_entry->value);
359 if (is_block_suitable_for_request(
user_context, block, request)) {
360#ifdef DEBUG_RUNTIME_INTERNAL
361 debug(
user_context) <<
"BlockAllocator: found suitable block ("
363 <<
"block_resource=" << (
void *)block <<
" "
364 <<
"block_size=" << (
uint32_t)block->memory.size <<
" "
365 <<
"block_reserved=" << (
uint32_t)block->reserved <<
" "
366 <<
"request_size=" << (
uint32_t)request.size <<
" "
367 <<
"request_dedicated=" << (request.dedicated ?
"true" :
"false") <<
" "
374 block_entry = prev_entry;
377 if (block_entry ==
nullptr) {
378#ifdef DEBUG_RUNTIME_INTERNAL
379 debug(
user_context) <<
"BlockAllocator: couldn't find suitable block! ("
381 <<
"request_size=" << (
uint32_t)request.size <<
" "
382 <<
"request_dedicated=" << (request.dedicated ?
"true" :
"false") <<
" "
391BlockAllocator::BlockEntry *
392BlockAllocator::reserve_block_entry(
void *
user_context,
const MemoryRequest &request) {
393#ifdef DEBUG_RUNTIME_INTERNAL
394 debug(
user_context) <<
"BlockAllocator: reserving block ... ! ("
395 <<
"requested_size=" << (
uint32_t)request.size <<
" "
396 <<
"requested_is_dedicated=" << (request.dedicated ?
"true" :
"false") <<
" "
401 BlockEntry *block_entry = find_block_entry(
user_context, request);
402 if (block_entry ==
nullptr) {
403#ifdef DEBUG_RUNTIME_INTERNAL
404 debug(
user_context) <<
"BlockAllocator: creating block ... ! ("
405 <<
"requested_size=" << (
uint32_t)request.size <<
" "
406 <<
"requested_is_dedicated=" << (request.dedicated ?
"true" :
"false") <<
" "
411 block_entry = create_block_entry(
user_context, request);
415 BlockResource *block =
static_cast<BlockResource *
>(block_entry->value);
416 if (block->allocator ==
nullptr) {
417 block->allocator = create_region_allocator(
user_context, block);
424BlockAllocator::create_region_allocator(
void *
user_context, BlockResource *block) {
425#ifdef DEBUG_RUNTIME_INTERNAL
426 debug(
user_context) <<
"BlockAllocator: Creating region allocator ("
428 <<
"block_resource=" << (
void *)(block) <<
")...";
434 if (region_allocator ==
nullptr) {
435 error(
user_context) <<
"BlockAllocator: Failed to create new region allocator\n";
439 return region_allocator;
442int BlockAllocator::destroy_region_allocator(
void *
user_context, RegionAllocator *region_allocator) {
443#ifdef DEBUG_RUNTIME_INTERNAL
444 debug(
user_context) <<
"BlockAllocator: Destroying region allocator ("
446 <<
"region_allocator=" << (
void *)(region_allocator) <<
")...";
448 if (region_allocator ==
nullptr) {
454BlockAllocator::BlockEntry *
455BlockAllocator::create_block_entry(
void *
user_context,
const MemoryRequest &request) {
457 error(
user_context) <<
"BlockAllocator: No free blocks found! Maximum pool size reached ("
464 error(
user_context) <<
"BlockAllocator: No free blocks found! Maximum block count reached ("
470 if (block_entry ==
nullptr) {
471#ifdef DEBUG_RUNTIME_INTERNAL
472 debug(
user_context) <<
"BlockAllocator: Failed to allocate new block entry\n";
477#ifdef DEBUG_RUNTIME_INTERNAL
478 debug(
user_context) <<
"BlockAllocator: Creating block entry ("
479 <<
"block_entry=" << (
void *)(block_entry) <<
" "
480 <<
"block=" << (
void *)(block_entry->value) <<
" "
481 <<
"allocator=" << (
void *)(allocators.
block.
allocate) <<
")...";
485 MemoryRequest block_request = request;
489 BlockResource *block =
static_cast<BlockResource *
>(block_entry->value);
490 block->memory.size = block_request.size;
491 block->memory.handle =
nullptr;
492 block->memory.properties = block_request.properties;
493 block->memory.dedicated = block_request.dedicated;
495 block->allocator = create_region_allocator(
user_context, block);
498#ifdef DEBUG_RUNTIME_INTERNAL
499 debug(
user_context) <<
"BlockAllocator: Failed to allocate memory block\n";
507int BlockAllocator::release_block_entry(
void *
user_context, BlockAllocator::BlockEntry *block_entry) {
508#ifdef DEBUG_RUNTIME_INTERNAL
509 debug(
user_context) <<
"BlockAllocator: Releasing block entry ("
510 <<
"block_entry=" << (
void *)(block_entry) <<
" "
511 <<
"block=" << (
void *)(block_entry->value) <<
")...";
513 BlockResource *block =
static_cast<BlockResource *
>(block_entry->value);
514 if (block->allocator) {
520int BlockAllocator::destroy_block_entry(
void *
user_context, BlockAllocator::BlockEntry *block_entry) {
521#ifdef DEBUG_RUNTIME_INTERNAL
522 debug(
user_context) <<
"BlockAllocator: Destroying block entry ("
523 <<
"block_entry=" << (
void *)(block_entry) <<
" "
524 <<
"block=" << (
void *)(block_entry->value) <<
" "
527 BlockResource *block =
static_cast<BlockResource *
>(block_entry->value);
528 if (block->allocator) {
529 destroy_region_allocator(
user_context, block->allocator);
530 block->allocator =
nullptr;
537int BlockAllocator::alloc_memory_block(
void *
user_context, BlockResource *block) {
538#ifdef DEBUG_RUNTIME_INTERNAL
539 debug(
user_context) <<
"BlockAllocator: Allocating block (ptr=" << (
void *)block <<
" allocator=" << (
void *)allocators.
block.
allocate <<
")...";
542 MemoryBlock *memory_block = &(block->memory);
548int BlockAllocator::free_memory_block(
void *
user_context, BlockResource *block) {
549#ifdef DEBUG_RUNTIME_INTERNAL
550 debug(
user_context) <<
"BlockAllocator: Deallocating block (ptr=" << (
void *)block <<
" allocator=" << (
void *)allocators.
block.
deallocate <<
")...";
553 MemoryBlock *memory_block = &(block->memory);
555 memory_block->handle =
nullptr;
557 block->memory.size = 0;
561size_t BlockAllocator::constrain_requested_size(
size_t size)
const {
562 size_t actual_size = size;
586 request->
size = (((request->
size + nm - 1) / nm) * nm);
643 return block_list.
size();
647 size_t total_size = 0;
649 for (block_entry = block_list.
front(); block_entry !=
nullptr; block_entry = block_entry->
next_ptr) {
651 if (block !=
nullptr) {
This file declares the routines used by Halide internally in its runtime.
@ halide_error_code_internal_error
There is a bug in the Halide compiler.
Allocator class interface for managing large contiguous blocks of memory, which are then sub-allocate...
BlockAllocator(const BlockAllocator &)=delete
const Config & default_config() const
bool collect(void *user_context)
size_t block_count() const
MemoryRegion * reserve(void *user_context, const MemoryRequest &request)
int release(void *user_context, MemoryRegion *region)
const Config & current_config() const
int retain(void *user_context, MemoryRegion *region)
static void destroy(void *user_context, BlockAllocator *block_allocator)
static BlockAllocator * create(void *user_context, const Config &config, const MemoryAllocators &allocators)
int reclaim(void *user_context, MemoryRegion *region)
int conform(void *user_context, MemoryRequest *request) const
BlockAllocator & operator=(const BlockAllocator &)=delete
const MemoryAllocators & current_allocators() const
void initialize(void *user_context, uint32_t entry_size, uint32_t capacity=default_capacity, const SystemMemoryAllocatorFns &allocator=default_allocator())
EntryType * append(void *user_context)
void remove(void *user_context, EntryType *entry_ptr)
void destroy(void *user_context)
Allocator class interface for sub-allocating a contiguous memory block into smaller regions of memory...
static int destroy(void *user_context, RegionAllocator *region_allocator)
static RegionAllocator * find_allocator(void *user_context, MemoryRegion *memory_region)
bool collect(void *user_context)
static RegionAllocator * create(void *user_context, BlockResource *block, const MemoryAllocators &ma)
WEAK const char * halide_memory_caching_name(MemoryCaching value)
WEAK const char * halide_memory_usage_name(MemoryUsage value)
WEAK const char * halide_memory_visibility_name(MemoryVisibility value)
This file defines the class FunctionDAG, which is our representation of a Halide pipeline,...
@ Internal
Not visible externally, similar to 'static' linkage in C.
Expr max(const FuncRef &a, const FuncRef &b)
unsigned __INT64_TYPE__ uint64_t
signed __INT32_TYPE__ int32_t
unsigned __INT32_TYPE__ uint32_t
#define halide_abort_if_false(user_context, cond)
size_t maximum_block_count
size_t minimum_block_size
size_t maximum_block_size
MemoryRegionAllocatorFns region
MemoryBlockAllocatorFns block
SystemMemoryAllocatorFns system
RegionAllocator * allocator
DeallocateBlockFn deallocate
ConformBlockRequestFn conform
MemoryProperties properties
MemoryVisibility visibility
MemoryProperties properties
DeallocateSystemFn deallocate
AllocateSystemFn allocate
VulkanMemoryAllocator * allocator