From fb1582b89d4766fdf521a91c4cd9d032e3bed29a Mon Sep 17 00:00:00 2001 From: Sven Bieg Date: Tue, 16 Apr 2024 17:54:14 +0200 Subject: [PATCH] Moved to MemMang Very good idea, my first intention. --- CMakeLists.txt | 19 +- portable/Heap/block_map.c | 721 ------------- portable/Heap/block_map.h | 170 --- portable/Heap/cluster_group.c | 31 - portable/Heap/cluster_group.h | 120 --- portable/Heap/heap.c | 420 -------- portable/Heap/heap.h | 126 --- portable/Heap/heap_block.c | 87 -- portable/Heap/heap_block.h | 83 -- portable/Heap/offset_index.c | 605 ----------- portable/Heap/offset_index.h | 129 --- portable/Heap/parent_group.c | 112 -- portable/Heap/parent_group.h | 53 - portable/MemMang/heap_6.c | 1875 +++++++++++++++++++++++++++++++++ portable/MemMang/heap_6.h | 556 ++++++++++ 15 files changed, 2435 insertions(+), 2672 deletions(-) delete mode 100644 portable/Heap/block_map.c delete mode 100644 portable/Heap/block_map.h delete mode 100644 portable/Heap/cluster_group.c delete mode 100644 portable/Heap/cluster_group.h delete mode 100644 portable/Heap/heap.c delete mode 100644 portable/Heap/heap.h delete mode 100644 portable/Heap/heap_block.c delete mode 100644 portable/Heap/heap_block.h delete mode 100644 portable/Heap/offset_index.c delete mode 100644 portable/Heap/offset_index.h delete mode 100644 portable/Heap/parent_group.c delete mode 100644 portable/Heap/parent_group.h create mode 100644 portable/MemMang/heap_6.c create mode 100644 portable/MemMang/heap_6.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 23703af26..25147221e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -250,21 +250,10 @@ target_sources(freertos_kernel PRIVATE if (DEFINED FREERTOS_HEAP ) # User specified a heap implementation add heap implementation to freertos_kernel. - if(FREERTOS_HEAP STREQUAL "6") - target_sources(freertos_kernel PRIVATE - portable/heap/block_map.c - portable/heap/cluster_group.c - portable/heap/heap.c - portable/heap/heap_block.c - portable/heap/offset_index.c - portable/heap/parent_group.c - ) - else() - target_sources(freertos_kernel PRIVATE - # If FREERTOS_HEAP is digit between 1 .. 5 - it is heap number, otherwise - it is path to custom heap source file - $>,${FREERTOS_HEAP},portable/MemMang/heap_${FREERTOS_HEAP}.c> - ) - endif() + target_sources(freertos_kernel PRIVATE + # If FREERTOS_HEAP is digit between 1 .. 5 - it is heap number, otherwise - it is path to custom heap source file + $>,${FREERTOS_HEAP},portable/MemMang/heap_${FREERTOS_HEAP}.c> + ) endif() diff --git a/portable/Heap/block_map.c b/portable/Heap/block_map.c deleted file mode 100644 index 0c22243aa..000000000 --- a/portable/Heap/block_map.c +++ /dev/null @@ -1,721 +0,0 @@ -//============= -// block_map.c -//============= - -// Copyright 2024, Sven Bieg (svenbieg@web.de) -// http://github.com/svenbieg/Heap - - -//======= -// Using -//======= - -#include "block_map.h" -#include "parent_group.h" - - -//======= -// Group -//======= - - -// Access - -size_t block_map_group_get_first_size(block_map_group_t* group) -{ -if(cluster_group_get_level(group)==0) - return block_map_item_group_get_first_size((block_map_item_group_t*)group); -return ((block_map_parent_group_t*)group)->first_size; -} - -block_map_item_t* block_map_group_get_item(block_map_group_t* group, size_t size) -{ -if(cluster_group_get_level(group)==0) - return block_map_item_group_get_item((block_map_item_group_t*)group, size); -return block_map_parent_group_get_item((block_map_parent_group_t*)group, size); -} - -size_t block_map_group_get_last_size(block_map_group_t* group) -{ -if(group==NULL) - return 0; -if(cluster_group_get_level(group)==0) - return block_map_item_group_get_last_size((block_map_item_group_t*)group); -return ((block_map_parent_group_t*)group)->last_size; -} - - -// Modification - -bool block_map_group_add_block(heap_handle_t heap, block_map_group_t* group, heap_block_info_t const* info, bool again) -{ -cluster_group_set_locked((cluster_group_t*)group, true); -bool added=false; -if(cluster_group_get_level(group)==0) - { - added=block_map_item_group_add_block(heap, (block_map_item_group_t*)group, info); - } -else - { - added=block_map_parent_group_add_block(heap, (block_map_parent_group_t*)group, info, again); - } -cluster_group_set_locked((cluster_group_t*)group, false); -return added; -} - -bool block_map_group_get_block(heap_handle_t heap, block_map_group_t* group, size_t min_size, heap_block_info_t* info) -{ -bool passive=cluster_group_is_locked((cluster_group_t*)group); -if(cluster_group_get_level(group)==0) - return block_map_item_group_get_block(heap, (block_map_item_group_t*)group, min_size, info, passive); -return block_map_parent_group_get_block(heap, (block_map_parent_group_t*)group, min_size, info, passive); -} - -bool block_map_group_remove_block(heap_handle_t heap, block_map_group_t* group, heap_block_info_t const* info) -{ -if(cluster_group_get_level(group)==0) - return block_map_item_group_remove_block(heap, (block_map_item_group_t*)group, info); -return block_map_parent_group_remove_block(heap, (block_map_parent_group_t*)group, info); -} - - -//============ -// Item-group -//============ - -// Con-/Destructors - -block_map_item_group_t* block_map_item_group_create(heap_handle_t heap) -{ -block_map_item_group_t* group=(block_map_item_group_t*)heap_alloc_internal(heap, sizeof(block_map_item_group_t)); -if(group==NULL) - return NULL; -cluster_group_init((cluster_group_t*)group, 0, 0); -return group; -} - - -// Access - -size_t block_map_item_group_get_first_size(block_map_item_group_t* group) -{ -uint16_t child_count=cluster_group_get_child_count((cluster_group_t*)group); -if(child_count==0) - return 0; -return group->items[0].size; -} - -block_map_item_t* block_map_item_group_get_item(block_map_item_group_t* group, size_t size) -{ -bool exists=false; -int16_t pos=block_map_item_group_get_item_pos(group, size, &exists); -configASSERT(exists); -return &group->items[pos]; -} - -block_map_item_t* block_map_item_group_get_item_at(block_map_item_group_t* group, uint16_t at) -{ -configASSERT(atitems[at]; -} - -uint16_t block_map_item_group_get_item_pos(block_map_item_group_t* group, size_t size, bool* exists_ptr) -{ -uint16_t child_count=cluster_group_get_child_count((cluster_group_t*)group); -for(uint16_t pos=0; positems[pos]; - if(item->entry==0) - continue; - if(item->size==size) - { - *exists_ptr=true; - return pos; - } - if(item->size>size) - return pos; - } -return child_count; -} - -size_t block_map_item_group_get_last_size(block_map_item_group_t* group) -{ -uint16_t child_count=cluster_group_get_child_count((cluster_group_t*)group); -if(child_count==0) - return 0; -return group->items[child_count-1].size; -} - - -// Modification - -bool block_map_item_group_add_block(heap_handle_t heap, block_map_item_group_t* group, heap_block_info_t const* info) -{ -bool exists=false; -uint16_t pos=block_map_item_group_get_item_pos(group, info->size, &exists); -if(!exists) - return block_map_item_group_add_item(group, info, pos); -block_map_item_t* item=block_map_item_group_get_item_at(group, pos); -bool added=false; -if(item->single) - { - offset_index_t index; - offset_index_init(&index); - added=offset_index_add_offset(heap, &index, info->offset); - if(!added) - return false; - if(item->offset) - offset_index_add_offset(heap, &index, item->offset); - item->index=index; - } -else - { - added=offset_index_add_offset(heap, &item->index, info->offset); - } -if(cluster_group_is_dirty((cluster_group_t*)group)) - { - block_map_item_group_cleanup(group); - cluster_group_set_dirty((cluster_group_t*)group, false); - } -return added; -} - -bool block_map_item_group_add_item(block_map_item_group_t* group, heap_block_info_t const* info, uint16_t at) -{ -uint16_t child_count=cluster_group_get_child_count((cluster_group_t*)group); -if(child_count==CLUSTER_GROUP_SIZE) - return false; -for(uint16_t u=child_count; u>at; u--) - group->items[u]=group->items[u-1]; -group->items[at].size=info->size; -group->items[at].offset=info->offset; -group->items[at].single=true; -cluster_group_set_child_count((cluster_group_t*)group, child_count+1); -return true; -} - -void block_map_item_group_append_items(block_map_item_group_t* group, block_map_item_t const* items, uint16_t count) -{ -uint16_t child_count=cluster_group_get_child_count((cluster_group_t*)group); -for(uint16_t u=0; uitems[child_count+u]=items[u]; -cluster_group_set_child_count((cluster_group_t*)group, child_count+count); -} - -void block_map_item_group_cleanup(block_map_item_group_t* group) -{ -uint16_t child_count=cluster_group_get_child_count((cluster_group_t*)group); -for(uint16_t pos=0; positems[pos].offset==0) - { - for(uint16_t u=pos; u+1items[u]=group->items[u+1]; - child_count--; - } - else - { - pos++; - } - } -cluster_group_set_child_count((cluster_group_t*)group, child_count); -} - -bool block_map_item_group_get_block(heap_handle_t heap, block_map_item_group_t* group, size_t min_size, heap_block_info_t* info, bool passive) -{ -uint16_t child_count=cluster_group_get_child_count((cluster_group_t*)group); -bool exists=false; -uint16_t pos=block_map_item_group_get_item_pos(group, min_size, &exists); -if(pos==child_count) - return false; -block_map_item_t* item=block_map_item_group_get_item_at(group, pos); -configASSERT(item->offset!=0); -info->size=item->size; -if(item->single) - { - info->offset=item->offset; - block_map_item_group_remove_item_at(group, pos, passive); - } -else - { - info->offset=offset_index_remove_offset_at(heap, &item->index, 0); - if(!item->offset) - block_map_item_group_remove_item_at(group, pos, passive); - } -return true; -} - -void block_map_item_group_insert_items(block_map_item_group_t* group, uint16_t pos, block_map_item_t const* items, uint16_t count) -{ -uint16_t child_count=cluster_group_get_child_count((cluster_group_t*)group); -for(uint16_t u=child_count+count-1; u>=pos+count; u--) - group->items[u]=group->items[u-count]; -for(uint16_t u=0; uitems[pos+u]=items[u]; -cluster_group_set_child_count((cluster_group_t*)group, child_count+count); -} - -bool block_map_item_group_remove_block(heap_handle_t heap, block_map_item_group_t* group, heap_block_info_t const* info) -{ -bool exists=false; -uint16_t pos=block_map_item_group_get_item_pos(group, info->size, &exists); -configASSERT(exists); -block_map_item_t* item=block_map_item_group_get_item_at(group, pos); -if(item->single) - { - configASSERT(item->offset==info->offset); - block_map_item_group_remove_item_at(group, pos, false); - } -else - { - offset_index_remove_offset(heap, &item->index, info->offset); - if(!item->offset) - block_map_item_group_remove_item_at(group, pos, false); - } -return true; -} - -size_t block_map_item_group_remove_item_at(block_map_item_group_t* group, size_t at, bool passive) -{ -uint16_t child_count=cluster_group_get_child_count((cluster_group_t*)group); -configASSERT(atitems[pos].offset; -if(passive) - { - group->items[pos].entry=0; - cluster_group_set_dirty((cluster_group_t*)group, true); - } -else - { - for(uint16_t u=pos; u+1items[u]=group->items[u+1]; - cluster_group_set_child_count((cluster_group_t*)group, child_count-1); - } -return offset; -} - -void block_map_item_group_remove_items(block_map_item_group_t* group, uint16_t pos, uint16_t count) -{ -uint16_t child_count=cluster_group_get_child_count((cluster_group_t*)group); -for(uint16_t u=pos; u+countitems[u]=group->items[u+count]; -cluster_group_set_child_count((cluster_group_t*)group, child_count-count); -} - - -//============== -// Parent-group -//============== - -// Con-/Destructors - -block_map_parent_group_t* block_map_parent_group_create(heap_handle_t heap, uint16_t level) -{ -block_map_parent_group_t* group=(block_map_parent_group_t*)heap_alloc_internal(heap, sizeof(block_map_parent_group_t)); -if(group==NULL) - return NULL; -cluster_group_init((cluster_group_t*)group, level, 0); -group->first_size=0; -group->last_size=0; -group->item_count=0; -return group; -} - -block_map_parent_group_t* block_map_parent_group_create_with_child(heap_handle_t heap, block_map_group_t* child) -{ -block_map_parent_group_t* group=(block_map_parent_group_t*)heap_alloc_internal(heap, sizeof(block_map_parent_group_t)); -if(group==NULL) - return NULL; -uint16_t child_level=cluster_group_get_level((cluster_group_t*)child); -cluster_group_init((cluster_group_t*)group, child_level+1, 1); -group->first_size=block_map_group_get_first_size(child); -group->last_size=block_map_group_get_last_size(child); -group->item_count=cluster_group_get_item_count((cluster_group_t*)child); -group->children[0]=child; -return group; -} - - -// Access - -block_map_item_t* block_map_parent_group_get_item(block_map_parent_group_t* group, size_t size) -{ -uint16_t pos=0; -uint16_t count=block_map_parent_group_get_item_pos(group, size, &pos, true); -configASSERT(count>0); -return block_map_group_get_item(group->children[pos], size); -} - -uint16_t block_map_parent_group_get_item_pos(block_map_parent_group_t* group, size_t size, uint16_t* pos_ptr, bool must_exist) -{ -uint16_t child_count=cluster_group_get_child_count((cluster_group_t*)group); -uint16_t pos=0; -for(; poschildren[pos]); - if(sizechildren[pos]); - if(size>last_size) - continue; - *pos_ptr=pos; - return 1; - } -if(must_exist) - return 0; -if(child_count==1) - pos=0; -if(pos==0) - { - *pos_ptr=pos; - return 1; - } -if(pos==child_count) - { - pos--; - *pos_ptr=pos; - return 1; - } -pos--; -*pos_ptr=pos; -return 2; -} - - -// Modification - -bool block_map_parent_group_add_block(heap_handle_t heap, block_map_parent_group_t* group, heap_block_info_t const* info, bool again) -{ -if(!block_map_parent_group_add_block_internal(heap, group, info, again)) - return false; -group->item_count++; -block_map_parent_group_update_bounds(group); -if(cluster_group_is_dirty((cluster_group_t*)group)) - { - block_map_parent_group_combine_children(heap, group); - cluster_group_set_dirty((cluster_group_t*)group, false); - } -return true; -} - -bool block_map_parent_group_add_block_internal(heap_handle_t heap, block_map_parent_group_t* group, heap_block_info_t const* info, bool again) -{ -uint16_t pos=0; -uint16_t count=block_map_parent_group_get_item_pos(group, info->size, &pos, false); -if(!again) - { - for(uint16_t u=0; uchildren[pos+u], info, false)) - return true; - } - if(block_map_parent_group_shift_children(group, pos, count)) - { - count=block_map_parent_group_get_item_pos(group, info->size, &pos, false); - for(uint16_t u=0; uchildren[pos+u], info, false)) - return true; - } - } - } -if(!block_map_parent_group_split_child(heap, group, pos)) - return false; -count=block_map_parent_group_get_item_pos(group, info->size, &pos, false); -for(uint16_t u=0; uchildren[pos+u], info, true)) - return true; - } -return false; -} - -void block_map_parent_group_append_groups(block_map_parent_group_t* group, block_map_group_t* const* append, uint16_t count) -{ -parent_group_append_groups((parent_group_t*)group, (cluster_group_t* const*)append, count); -block_map_parent_group_update_bounds(group); -} - -bool block_map_parent_group_combine_child(heap_handle_t heap, block_map_parent_group_t* group, uint16_t pos) -{ -uint16_t count=cluster_group_get_child_count(group->children[pos]); -if(count==0) - { - parent_group_remove_group(heap, (parent_group_t*)group, pos); - return true; - } -if(pos>0) - { - uint16_t before=cluster_group_get_child_count(group->children[pos-1]); - if(count+before<=CLUSTER_GROUP_SIZE) - { - block_map_parent_group_move_children(group, pos, pos-1, count); - parent_group_remove_group(heap, (parent_group_t*)group, pos); - return true; - } - } -uint16_t child_count=cluster_group_get_child_count((cluster_group_t*)group); -if(pos+1children[pos+1]); - if(count+after<=CLUSTER_GROUP_SIZE) - { - block_map_parent_group_move_children(group, pos+1, pos, after); - parent_group_remove_group(heap, (parent_group_t*)group, pos+1); - return true; - } - } -return false; -} - -void block_map_parent_group_combine_children(heap_handle_t heap, block_map_parent_group_t* group) -{ -uint16_t child_count=cluster_group_get_child_count((cluster_group_t*)group); -for(uint16_t pos=0; pos0); -if(count==2) - pos++; -if(!block_map_group_get_block(heap, group->children[pos], min_size, info)) - return false; -if(passive) - { - cluster_group_set_dirty((cluster_group_t*)group, true); - } -else - { - block_map_parent_group_combine_child(heap, group, pos); - } -group->item_count--; -block_map_parent_group_update_bounds(group); -return true; -} - -void block_map_parent_group_insert_groups(block_map_parent_group_t* group, uint16_t at, block_map_group_t* const* insert, uint16_t count) -{ -parent_group_insert_groups((parent_group_t*)group, at, (cluster_group_t* const*)insert, count); -block_map_parent_group_update_bounds(group); -} - -void block_map_parent_group_move_children(block_map_parent_group_t* group, uint16_t from, uint16_t to, uint16_t count) -{ -uint16_t level=cluster_group_get_level((cluster_group_t*)group); -if(level>1) - { - block_map_parent_group_t* src=(block_map_parent_group_t*)group->children[from]; - block_map_parent_group_t* dst=(block_map_parent_group_t*)group->children[to]; - if(from>to) - { - block_map_parent_group_append_groups(dst, src->children, count); - block_map_parent_group_remove_groups(src, 0, count); - } - else - { - uint16_t src_count=cluster_group_get_child_count((cluster_group_t*)src); - block_map_parent_group_insert_groups(dst, 0, &src->children[src_count-count], count); - block_map_parent_group_remove_groups(src, src_count-count, count); - } - } -else - { - block_map_item_group_t* src=(block_map_item_group_t*)group->children[from]; - block_map_item_group_t* dst=(block_map_item_group_t*)group->children[to]; - if(from>to) - { - block_map_item_group_append_items(dst, src->items, count); - block_map_item_group_remove_items(src, 0, count); - } - else - { - uint16_t src_count=cluster_group_get_child_count((cluster_group_t*)src); - block_map_item_group_insert_items(dst, 0, &src->items[src_count-count], count); - block_map_item_group_remove_items(src, src_count-count, count); - } - } -} - -void block_map_parent_group_move_empty_slot(block_map_parent_group_t* group, uint16_t from, uint16_t to) -{ -if(fromto; u--) - block_map_parent_group_move_children(group, u-1, u, 1); - } -} - -bool block_map_parent_group_remove_block(heap_handle_t heap, block_map_parent_group_t* group, heap_block_info_t const* info) -{ -uint16_t pos=0; -uint16_t count=block_map_parent_group_get_item_pos(group, info->size, &pos, true); -configASSERT(count==1); -if(block_map_group_remove_block(heap, group->children[pos], info)) - { - group->item_count--; - block_map_parent_group_combine_child(heap, group, pos); - block_map_parent_group_update_bounds(group); - return true; - } -return false; -} - -void block_map_parent_group_remove_groups(block_map_parent_group_t* group, uint16_t at, uint16_t count) -{ -parent_group_remove_groups((parent_group_t*)group, at, count); -block_map_parent_group_update_bounds(group); -} - -bool block_map_parent_group_shift_children(block_map_parent_group_t* group, uint16_t at, uint16_t count) -{ -int16_t space=parent_group_get_nearest_space((parent_group_t*)group, at); -if(space<0) - return false; -if(count>1&&space>at) - at++; -block_map_parent_group_move_empty_slot(group, space, at); -return true; -} - -bool block_map_parent_group_split_child(heap_handle_t heap, block_map_parent_group_t* group, uint16_t at) -{ -uint16_t child_count=cluster_group_get_child_count((cluster_group_t*)group); -if(child_count==CLUSTER_GROUP_SIZE) - return false; -block_map_group_t* child=NULL; -uint16_t level=cluster_group_get_level((cluster_group_t*)group); -if(level>1) - { - child=(block_map_group_t*)block_map_parent_group_create(heap, level-1); - } -else - { - child=(block_map_group_t*)block_map_item_group_create(heap); - } -if(!child) - return false; -for(uint16_t u=child_count; u>at+1; u--) - group->children[u]=group->children[u-1]; -group->children[at+1]=child; -cluster_group_set_child_count((cluster_group_t*)group, child_count+1); -block_map_parent_group_move_children(group, at, at+1, 1); -return true; -} - -void block_map_parent_group_update_bounds(block_map_parent_group_t* group) -{ -uint16_t child_count=cluster_group_get_child_count((cluster_group_t*)group); -if(child_count==0) - { - group->first_size=0; - group->last_size=0; - return; - } -for(uint16_t pos=0; posfirst_size=block_map_group_get_first_size(group->children[pos]); - if(group->first_size!=0) - break; - } -for(uint16_t pos=child_count; pos>0; pos--) - { - group->last_size=block_map_group_get_last_size(group->children[pos-1]); - if(group->last_size!=0) - break; - } -} - - -//===== -// Map -//===== - - -// Modification - -bool block_map_add_block(heap_handle_t heap, block_map_t* map, heap_block_info_t const* info) -{ -heap_t* heap_ptr=(heap_t*)heap; -configASSERT(info->offset>=(size_t)heap+sizeof(heap_t)); -configASSERT(info->offset<(size_t)heap+heap_ptr->used); -if(!map->root) - { - map->root=(block_map_group_t*)block_map_item_group_create(heap); - if(!map->root) - return false; - } -if(block_map_group_add_block(heap, map->root, info, false)) - { - block_map_drop_root(heap, map); - return true; - } -if(!block_map_lift_root(heap, map)) - return false; -if(!block_map_group_add_block(heap, map->root, info, true)) - return false; -block_map_drop_root(heap, map); -return true; -} - -bool block_map_drop_root(heap_handle_t heap, block_map_t* map) -{ -block_map_group_t* root=map->root; -if(cluster_group_is_locked((cluster_group_t*)root)) - return false; -uint16_t child_count=cluster_group_get_child_count((cluster_group_t*)root); -uint16_t level=cluster_group_get_level((cluster_group_t*)root); -if(level==0) - return false; -if(child_count>1) - return false; -block_map_parent_group_t* parent_group=(block_map_parent_group_t*)root; -map->root=parent_group->children[0]; -heap_free_to_cache(heap, root); -return true; -} - -bool block_map_get_block(heap_handle_t heap, block_map_t* map, size_t min_size, heap_block_info_t* info) -{ -if(!map->root) - return false; -if(block_map_group_get_block(heap, map->root, min_size, info)) - { - block_map_drop_root(heap, map); - return true; - } -return false; -} - -bool block_map_lift_root(heap_handle_t heap, block_map_t* map) -{ -block_map_parent_group_t* root=block_map_parent_group_create_with_child(heap, map->root); -if(!root) - return false; -map->root=(block_map_group_t*)root; -return true; -} - -void block_map_remove_block(heap_handle_t heap, block_map_t* map, heap_block_info_t const* info) -{ -if(block_map_group_remove_block(heap, map->root, info)) - block_map_drop_root(heap, map); -} diff --git a/portable/Heap/block_map.h b/portable/Heap/block_map.h deleted file mode 100644 index 8e34340bc..000000000 --- a/portable/Heap/block_map.h +++ /dev/null @@ -1,170 +0,0 @@ -//============= -// block_map.h -//============= - -// Map to free memory-blocks sorted by size - -// Copyright 2024, Sven Bieg (svenbieg@web.de) -// http://github.com/svenbieg/Heap - - -#ifndef _BLOCK_MAP_H -#define _BLOCK_MAP_H - - -//======= -// Using -//======= - -#include "cluster_group.h" -#include "heap_block.h" -#include "offset_index.h" - - -//====== -// Item -//====== - -typedef struct -{ -size_t size; -union - { - struct - { - size_t offset: SIZE_BITS-1; - size_t single: 1; - }; - size_t entry; - offset_index_t index; - }; -}block_map_item_t; - - -//======= -// Group -//======= - -typedef cluster_group_t block_map_group_t; - -// Access -size_t block_map_group_get_first_size(block_map_group_t* group); -block_map_item_t* block_map_group_get_item(block_map_group_t* group, size_t size); -size_t block_map_group_get_last_size(block_map_group_t* group); - -// Modification -bool block_map_group_add_block(heap_handle_t heap, block_map_group_t* group, heap_block_info_t const* info, bool again); -bool block_map_group_get_block(heap_handle_t heap, block_map_group_t* group, size_t min_size, heap_block_info_t* info); -bool block_map_group_remove_block(heap_handle_t heap, block_map_group_t* group, heap_block_info_t const* info); - - -//============ -// Item-group -//============ - -typedef struct -{ -cluster_group_t header; -block_map_item_t items[CLUSTER_GROUP_SIZE]; -}block_map_item_group_t; - -// Con-/Destructors -block_map_item_group_t* block_map_item_group_create(heap_handle_t heap); - -// Access -size_t block_map_item_group_get_first_size(block_map_item_group_t* group); -block_map_item_t* block_map_item_group_get_item(block_map_item_group_t* group, size_t size); -block_map_item_t* block_map_item_group_get_item_at(block_map_item_group_t* group, uint16_t at); -uint16_t block_map_item_group_get_item_pos(block_map_item_group_t* group, size_t size, bool* exists_ptr); -size_t block_map_item_group_get_last_size(block_map_item_group_t* group); - -// Modification -bool block_map_item_group_add_block(heap_handle_t heap, block_map_item_group_t* group, heap_block_info_t const* info); -bool block_map_item_group_add_item(block_map_item_group_t* group, heap_block_info_t const* info, uint16_t pos); -void block_map_item_group_append_items(block_map_item_group_t* group, block_map_item_t const* items, uint16_t count); -void block_map_item_group_cleanup(block_map_item_group_t* group); -bool block_map_item_group_get_block(heap_handle_t heap, block_map_item_group_t* group, size_t min_size, heap_block_info_t* info, bool passive); -void block_map_item_group_insert_items(block_map_item_group_t* group, uint16_t pos, block_map_item_t const* items, uint16_t count); -bool block_map_item_group_remove_block(heap_handle_t heap, block_map_item_group_t* group, heap_block_info_t const* info); -size_t block_map_item_group_remove_item_at(block_map_item_group_t* group, size_t at, bool passive); -void block_map_item_group_remove_items(block_map_item_group_t* group, uint16_t at, uint16_t count); - - -//============== -// Parent-group -//============== - -typedef struct -{ -cluster_group_t header; -size_t item_count; -size_t first_size; -size_t last_size; -block_map_group_t* children[CLUSTER_GROUP_SIZE]; -}block_map_parent_group_t; - -// Con-/Destructors -block_map_parent_group_t* block_map_parent_group_create(heap_handle_t heap, uint16_t level); -block_map_parent_group_t* block_map_parent_group_create_with_child(heap_handle_t heap, block_map_group_t* child); - -// Access -block_map_item_t* block_map_parent_group_get_item(block_map_parent_group_t* group, size_t size); -uint16_t block_map_parent_group_get_item_pos(block_map_parent_group_t* group, size_t size, uint16_t* pos_ptr, bool must_exist); - -// Modification -bool block_map_parent_group_add_block(heap_handle_t heap, block_map_parent_group_t* group, heap_block_info_t const* info, bool again); -bool block_map_parent_group_add_block_internal(heap_handle_t heap, block_map_parent_group_t* group, heap_block_info_t const* info, bool again); -void block_map_parent_group_append_groups(block_map_parent_group_t* group, block_map_group_t* const* append, uint16_t count); -bool block_map_parent_group_combine_child(heap_handle_t heap, block_map_parent_group_t* group, uint16_t pos); -void block_map_parent_group_combine_children(heap_handle_t heap, block_map_parent_group_t* group); -bool block_map_parent_group_get_block(heap_handle_t heap, block_map_parent_group_t* group, size_t min_size, heap_block_info_t* info, bool passive); -void block_map_parent_group_insert_groups(block_map_parent_group_t* group, uint16_t at, block_map_group_t* const* insert, uint16_t count); -void block_map_parent_group_move_children(block_map_parent_group_t* group, uint16_t from, uint16_t to, uint16_t count); -void block_map_parent_group_move_empty_slot(block_map_parent_group_t* group, uint16_t from, uint16_t to); -bool block_map_parent_group_remove_block(heap_handle_t heap, block_map_parent_group_t* group, heap_block_info_t const* info); -void block_map_parent_group_remove_groups(block_map_parent_group_t* group, uint16_t at, uint16_t count); -bool block_map_parent_group_shift_children(block_map_parent_group_t* group, uint16_t at, uint16_t count); -bool block_map_parent_group_split_child(heap_handle_t heap, block_map_parent_group_t* group, uint16_t at); -void block_map_parent_group_update_bounds(block_map_parent_group_t* group); - - -//===== -// Map -//===== - -typedef struct -{ -block_map_group_t* root; -}block_map_t; - -// Con-/Destructors -static inline void block_map_init(block_map_t* map) -{ -map->root=NULL; -} - - -// Access -static inline size_t block_map_get_item_count(block_map_t* map) -{ -if(map==NULL) - return 0; -return cluster_group_get_item_count((cluster_group_t*)map->root); -} - -static inline size_t block_map_get_last_size(block_map_t* map) -{ -if(map==NULL) - return 0; -return block_map_group_get_last_size(map->root); -} - - -// Modification -bool block_map_add_block(heap_handle_t heap, block_map_t* map, heap_block_info_t const* info); -bool block_map_drop_root(heap_handle_t heap, block_map_t* map); -bool block_map_get_block(heap_handle_t heap, block_map_t* map, size_t min_size, heap_block_info_t* info); -bool block_map_lift_root(heap_handle_t heap, block_map_t* map); -void block_map_remove_block(heap_handle_t heap, block_map_t* map, heap_block_info_t const* info); - -#endif // _BLOCK_MAP_H diff --git a/portable/Heap/cluster_group.c b/portable/Heap/cluster_group.c deleted file mode 100644 index 80dc21a29..000000000 --- a/portable/Heap/cluster_group.c +++ /dev/null @@ -1,31 +0,0 @@ -//================= -// cluster_group.c -//================= - -// Copyright 2024, Sven Bieg (svenbieg@web.de) -// http://github.com/svenbieg/Heap - - -//======= -// Using -//======= - -#include "cluster_group.h" -#include "parent_group.h" - - -//======== -// Access -//======== - -size_t cluster_group_get_item_count(cluster_group_t* group) -{ -if(!group) - return 0; -cluster_group_t get; -get.value=group->value; -if(get.level==0) - return get.child_count; -parent_group_t* parent_group=(parent_group_t*)group; -return parent_group->item_count; -} diff --git a/portable/Heap/cluster_group.h b/portable/Heap/cluster_group.h deleted file mode 100644 index aae948fd6..000000000 --- a/portable/Heap/cluster_group.h +++ /dev/null @@ -1,120 +0,0 @@ -//================= -// cluster_group.h -//================= - -// Header of groups used for sorting. -// Memory-access needs to be 32 bit in IRAM. - -// Copyright 2024, Sven Bieg (svenbieg@web.de) -// http://github.com/svenbieg/Heap - - -#ifndef _CLUSTER_GROUP_H -#define _CLUSTER_GROUP_H - - -//======= -// Using -//======= - -#include "heap.h" - - -//======= -// Group -//======= - -typedef struct -{ -union - { - struct - { - uint32_t dirty: 1; - uint32_t locked: 1; - uint32_t level: 14; - uint32_t child_count: 16; - }; - uint32_t value; - }; -}cluster_group_t; - - -//================== -// Con-/Destructors -//================== - -static inline void cluster_group_init(cluster_group_t* group, uint16_t level, uint16_t child_count) -{ -cluster_group_t set={ 0 }; -set.level=level; -set.child_count=child_count; -group->value=set.value; -} - - -//======== -// Access -//======== - -static inline uint16_t cluster_group_get_child_count(cluster_group_t* group) -{ -cluster_group_t get; -get.value=group->value; -return (uint16_t)get.child_count; -} - -size_t cluster_group_get_item_count(cluster_group_t* group); - -static inline uint16_t cluster_group_get_level(cluster_group_t* group) -{ -cluster_group_t get; -get.value=group->value; -return (uint16_t)get.level; -} - -static inline bool cluster_group_is_dirty(cluster_group_t* group) -{ -cluster_group_t get; -get.value=group->value; -return (uint16_t)get.dirty; -} - -static inline bool cluster_group_is_locked(cluster_group_t* group) -{ -cluster_group_t get; -get.value=group->value; -return (uint16_t)get.locked; -} - - -//============== -// Modification -//============== - -static inline void cluster_group_set_child_count(cluster_group_t* group, uint16_t child_count) -{ -cluster_group_t set; -set.value=group->value; -set.child_count=child_count; -group->value=set.value; -} - -static inline void cluster_group_set_dirty(cluster_group_t* group, bool dirty) -{ -cluster_group_t set; -set.value=group->value; -set.dirty=dirty; -group->value=set.value; -} - -static inline void cluster_group_set_locked(cluster_group_t* group, bool lock) -{ -cluster_group_t set; -set.value=group->value; -configASSERT((bool)set.locked!=lock); -set.locked=lock; -group->value=set.value; -} - -#endif // _CLUSTER_GROUP_H diff --git a/portable/Heap/heap.c b/portable/Heap/heap.c deleted file mode 100644 index 6f9ca3f95..000000000 --- a/portable/Heap/heap.c +++ /dev/null @@ -1,420 +0,0 @@ -//======== -// heap.c -//======== - -// Memory-manager for real-time C++ applications. -// Allocations and deletions are done in constant low time. - -// Copyright 2024, Sven Bieg (svenbieg@web.de) -// http://github.com/svenbieg/Heap - - -//======= -// Using -//======= - -#include "block_map.h" -#include "semphr.h" - - -//======== -// Macros -//======== - -// These macros are from heap_5.c - -#if(configSUPPORT_DYNAMIC_ALLOCATION==0) -#error This file must not be used if configSUPPORT_DYNAMIC_ALLOCATION is 0 -#endif - -#if(configHEAP_CLEAR_MEMORY_ON_FREE==1) -#error Not supported with heap_6 -#endif - -#if(configENABLE_HEAP_PROTECTOR==1) -#error Not supported with heap_6 -#endif - -/* Check if multiplying a and b will result in overflow. */ -#define MULTIPLY_WILL_OVERFLOW(a, b) (((a)>0)&&((b)>(SIZE_MAX/(a)))) - -/* Check if adding a and b will result in overflow. */ -#define ADD_WILL_OVERFLOW(a, b) ((a)>(SIZE_MAX-(b))) - -/* Check if the subtraction operation (a-b) will result in underflow. */ -#define SUBTRACT_WILL_UNDERFLOW(a, b) ((a)<(b)) - - -static inline bool heap_lock() -{ -#if(configUSE_HEAP_IN_ISR==1) -vTaskSuspendAll(); -return true; -#else -taskENTER_CRITICAL(); -if(xSemaphoreTake(heap_mutex, portMAX_DELAY)==pdTRUE) - return true; -return false; -#endif -} - -static inline void heap_unlock(bool locked) -{ -#if(configUSE_HEAP_IN_ISR==1) -xTaskResumeAll(); -#else -if(locked) - xSemaphoreGive(heap_lock); -taskEXIT_CRITICAL(); -#endif -} - - -//========= -// Globals -//========= - -#if(configUSE_HEAP_IN_ISR==0) -static SemaphoreHandle_t heap_mutex=NULL; -static StaticSemaphore_t heap_mutex_buf; -#endif - -static heap_handle_t first_heap=NULL; -static heap_handle_t last_heap=NULL; - -static size_t xFreeBlocks=0; -static size_t xFreeBytes=0; -static size_t xMinimumFreeBytes=0; -static size_t xSuccessfulAllocations=0; -static size_t xSuccessfulDeletions=0; - -static inline void heap_reduce_free_bytes(size_t reduce) -{ -xFreeBytes-=reduce; -xMinimumFreeBytes=min(xMinimumFreeBytes, xFreeBytes); -} - - -//========== -// Creation -//========== - -heap_handle_t heap_create(heap_handle_t prev_heap, size_t offset, size_t size) -{ -offset=align_up(offset, sizeof(size_t)); -size=align_down(size, sizeof(size_t)); -configASSERT(size>sizeof(heap_t)); -size_t available=size-sizeof(heap_t); -heap_handle_t heap=(heap_t*)offset; -heap->free=available; -heap->used=sizeof(heap_t); -heap->size=size; -heap->free_block=0; -heap->next_heap=0; -block_map_init((block_map_t*)&heap->map_free); -if(prev_heap) - prev_heap->next_heap=(size_t)heap; -xFreeBlocks++; -xFreeBytes+=available; -xMinimumFreeBytes=xFreeBytes; -return heap; -} - - -//============ -// Allocation -//============ - -void* heap_alloc(heap_handle_t heap, size_t size) -{ -configASSERT(heap!=NULL); -configASSERT(size!=0); -size=heap_block_calc_size(size); -void* buf=heap_alloc_from_map(heap, size); -if(buf) - { - heap_free_cache(heap); - } -else - { - buf=heap_alloc_from_foot(heap, size); - } -return buf; -} - -void heap_free(heap_handle_t heap, void* buf) -{ -configASSERT(heap!=NULL); -if(!buf) - return; -heap_free_to_map(heap, buf); -heap_free_cache(heap); -} - - -//===================== -// Internal Allocation -//===================== - -void* heap_alloc_from_foot(heap_handle_t heap, size_t size) -{ -if(heap->used+size>heap->size) - return NULL; -heap_block_info_t info; -info.offset=(size_t)heap+heap->used; -info.size=size; -info.free=false; -heap->free-=size; -heap->used+=size; -heap_reduce_free_bytes(size); -return heap_block_init(heap, &info); -} - -void* heap_alloc_from_map(heap_handle_t heap, size_t size) -{ -heap_block_info_t info; -if(!block_map_get_block(heap, (block_map_t*)&heap->map_free, size, &info)) - return NULL; -heap->free-=info.size; -heap_reduce_free_bytes(info.size); -size_t free_size=info.size-size; -if(free_size>=BLOCK_SIZE_MIN) - { - heap_block_info_t free_info; - free_info.offset=info.offset+size; - free_info.size=free_size; - free_info.free=false; - void* free_buf=heap_block_init(heap, &free_info); - heap_free_to_cache(heap, free_buf); - info.size=size; - } -xFreeBlocks--; -info.free=false; -return heap_block_init(heap, &info); -} - -void* heap_alloc_internal(heap_handle_t heap, size_t size) -{ -size=heap_block_calc_size(size); -void* buf=heap_alloc_from_map(heap, size); -if(buf) - return buf; -return heap_alloc_from_foot(heap, size); -} - -void heap_free_cache(heap_handle_t heap) -{ -heap_t* heap_ptr=(heap_t*)heap; -size_t free_block=heap_ptr->free_block; -if(!free_block) - return; -size_t* buf=(size_t*)heap_block_get_pointer(free_block); -heap_ptr->free_block=*buf; -heap_free_to_map(heap, buf); -} - -void heap_free_to_cache(heap_handle_t heap, void* buf) -{ -size_t* body_ptr=(size_t*)buf; -*body_ptr=heap->free_block; -heap->free_block=heap_block_get_offset(buf); -} - -void heap_free_to_map(heap_handle_t heap, void* buf) -{ -heap_block_chain_t info; -heap_block_get_chain(heap, buf, &info); -size_t heap_end=(size_t)heap+heap->used; -size_t offset=info.current.offset; -size_t size=info.current.size; -configASSERT(offset>=(size_t)heap); -configASSERT(offsetmap_free, &info.previous); - heap->free-=info.previous.size; - xFreeBlocks--; - xFreeBytes-=info.previous.size; - } -if(!info.next.offset) - { - heap->free+=size; - heap->used-=size; - xFreeBytes+=size; - return; - } -if(info.next.free) - { - size+=info.next.size; - block_map_remove_block(heap, (block_map_t*)&heap->map_free, &info.next); - heap->free-=info.next.size; - xFreeBlocks--; - xFreeBytes-=info.next.size; - } -info.current.offset=offset; -info.current.size=size; -info.current.free=true; -heap_block_init(heap, &info.current); -bool added=block_map_add_block(heap, (block_map_t*)&heap->map_free, &info.current); -if(!added) - { - info.current.free=false; - heap_block_init(heap, &info.current); - buf=heap_block_get_pointer(info.current.offset); - heap_free_to_cache(heap, buf); - return; - } -heap->free+=size; -xFreeBlocks++; -xFreeBytes+=size; -} - - -//=========== -// Statistic -//=========== - -size_t heap_get_largest_free_block(heap_handle_t heap) -{ -size_t largest=0; -largest=block_map_get_last_size((block_map_t*)&heap->map_free); -largest=max(largest, heap->size-heap->used); -return largest; -} - - -//========== -// FreeRTOS -//========== - -void* pvPortCalloc(size_t xNum, size_t xSize) -{ -void* buf=NULL; -if(MULTIPLY_WILL_OVERFLOW(xNum, xSize)==0) - { - buf=pvPortMalloc(xNum*xSize); - if(buf!=NULL) - memset(buf, 0, xNum*xSize); - } -return buf; -} - -void* pvPortMalloc(size_t xWantedSize) -{ -void* buf=NULL; -bool locked=heap_lock(); -if(locked) - { - heap_handle_t heap=first_heap; - while(heap) - { - buf=heap_alloc(heap, xWantedSize); - if(buf!=NULL) - break; - heap=(heap_handle_t)heap->next_heap; - } - } -heap_unlock(locked); -if(buf!=NULL) - xSuccessfulAllocations++; -return buf; -} - -void vPortDefineHeapRegions(HeapRegion_t const* pxHeapRegions)PRIVILEGED_FUNCTION -{ -configASSERT(first_heap==NULL); -configASSERT(pxHeapRegions!=NULL); -HeapRegion_t const* region=pxHeapRegions; -while(region->xSizeInBytes>0) - { - size_t offset=(size_t)region->pucStartAddress; - size_t size=region->xSizeInBytes; - heap_handle_t heap=heap_create(last_heap, offset, size); - configASSERT(heap!=NULL); - if(first_heap==NULL) - first_heap=heap; - last_heap=heap; - region++; - } -#if(configUSE_HEAP_IN_ISR==0) -heap_mutex=xSemaphoreCreateMutexStatic(&heap_mutex_buf); -#endif -} - -void vPortFree(void* pv) -{ -if(pv==NULL) - return; -size_t offset=(size_t)pv; -bool locked=heap_lock(); -if(locked) - { - heap_handle_t heap=first_heap; - while(heap) - { - size_t heap_start=(size_t)heap; - size_t heap_end=heap_start+heap->size; - if(offset>heap_start&&offsetnext_heap; - } - } -heap_unlock(locked); -} - -void vPortGetHeapStats(HeapStats_t* pxHeapStats) -{ -configASSERT(pxHeapStats!=NULL); -memset(pxHeapStats, 0, sizeof(HeapStats_t)); -bool locked=heap_lock(); -if(locked) - { - size_t largest=0; - heap_handle_t heap=first_heap; - while(heap) - { - largest=max(largest, heap_get_largest_free_block(heap)); - heap=(heap_handle_t)heap->next_heap; - } - pxHeapStats->xAvailableHeapSpaceInBytes=xFreeBytes; - pxHeapStats->xMinimumEverFreeBytesRemaining=xMinimumFreeBytes; - pxHeapStats->xNumberOfFreeBlocks=xFreeBlocks; - pxHeapStats->xNumberOfSuccessfulAllocations=xSuccessfulAllocations; - pxHeapStats->xNumberOfSuccessfulFrees=xSuccessfulDeletions; - pxHeapStats->xSizeOfLargestFreeBlockInBytes=largest; - pxHeapStats->xSizeOfSmallestFreeBlockInBytes=BLOCK_SIZE_MIN; - } -heap_unlock(locked); -} - -void vPortHeapResetState(void) -{ -#if(configUSE_HEAP_IN_ISR==0) -vSemaphoreDelete(heap_mutex); -heap_mutex=NULL; -#endif -first_heap=NULL; -last_heap=NULL; -xFreeBlocks=0; -xFreeBytes=0; -xMinimumFreeBytes=0; -xSuccessfulAllocations=0; -xSuccessfulDeletions=0; -} - -size_t xPortGetFreeHeapSize(void) -{ -return xFreeBytes; -} - -size_t xPortGetMinimumEverFreeHeapSize(void) -{ -return xMinimumFreeBytes; -} diff --git a/portable/Heap/heap.h b/portable/Heap/heap.h deleted file mode 100644 index 1ba9724cd..000000000 --- a/portable/Heap/heap.h +++ /dev/null @@ -1,126 +0,0 @@ -//======== -// heap.h -//======== - -// Memory-manager for real-time C++ applications. -// Allocations and deletions are done in constant low time. - -// Copyright 2024, Sven Bieg (svenbieg@web.de) -// http://github.com/svenbieg/Heap - - -#ifndef _HEAP_H -#define _HEAP_H - - -//======= -// Using -//======= - -#include -#include -#include -#include - -#define MPU_WRAPPERS_INCLUDED_FROM_API_FILE - -#include "FreeRTOS.h" -#include "task.h" - -#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE - - -//========== -// Settings -//========== - -#define configUSE_HEAP_IN_ISR 1 - -#define CLUSTER_GROUP_SIZE 10 - - -//=========== -// Alignment -//=========== - -#define SIZE_BITS (sizeof(size_t)*8) -#define SIZE_BYTES sizeof(size_t) - -#define BLOCK_SIZE_MIN (4*SIZE_BYTES) - -static inline size_t align_down(size_t value, size_t align) -{ -return value&~(align-1); -} - -static inline size_t align_up(size_t value, size_t align) -{ -return value+(align-value%align)%align; -} - - -//====== -// Heap -//====== - -typedef struct _heap_t -{ -size_t free; -size_t used; -size_t size; -size_t free_block; -size_t next_heap; -size_t map_free; -}heap_t; - -typedef heap_t* heap_handle_t; - - -//========== -// Creation -//========== - -heap_handle_t heap_create(heap_handle_t prev_heap, size_t offset, size_t size); - - -//============ -// Allocation -//============ - -void* heap_alloc(heap_handle_t heap, size_t size); -void heap_free(heap_handle_t heap, void* buffer); - - -//===================== -// Internal Allocation -//===================== - -void* heap_alloc_from_foot(heap_handle_t heap, size_t size); -void* heap_alloc_from_map(heap_handle_t heap, size_t size); -void* heap_alloc_internal(heap_handle_t heap, size_t size); -void heap_free_cache(heap_handle_t heap); -void heap_free_to_cache(heap_handle_t heap, void* buf); -void heap_free_to_map(heap_handle_t heap, void* buf); - - -//=========== -// Statistic -//=========== - -size_t heap_get_largest_free_block(heap_handle_t heap); - - -//========== -// FreeRTOS -//========== - -void* pvPortCalloc(size_t xNum, size_t xSize); -void* pvPortMalloc(size_t xWantedSize); -void vPortDefineHeapRegions(HeapRegion_t const* pxHeapRegions)PRIVILEGED_FUNCTION; -void vPortFree(void* pv); -void vPortGetHeapStats(HeapStats_t* pxHeapStats); -void vPortHeapResetState(void); -size_t xPortGetFreeHeapSize(void); -size_t xPortGetMinimumEverFreeHeapSize(void); - -#endif // _HEAP_H diff --git a/portable/Heap/heap_block.c b/portable/Heap/heap_block.c deleted file mode 100644 index 3b015995c..000000000 --- a/portable/Heap/heap_block.c +++ /dev/null @@ -1,87 +0,0 @@ -//============== -// heap_block.c -//============== - -// Copyright 2024, Sven Bieg (svenbieg@web.de) -// http://github.com/svenbieg/Heap - - -//======= -// Using -//======= - -#include "heap_block.h" - - -//================== -// Con-/Destructors -//================== - -void* heap_block_init(heap_handle_t heap, heap_block_info_t const* info) -{ -heap_t* heap_ptr=(heap_t*)heap; -configASSERT(info->size%sizeof(size_t)==0); -configASSERT(info->offset>=(size_t)heap+sizeof(heap_t)); -configASSERT(info->offset+info->size<=(size_t)heap+heap_ptr->size); -size_t* head_ptr=(size_t*)info->offset; -*head_ptr=info->header; -head_ptr++; -size_t* foot_ptr=(size_t*)(info->offset+info->size); -foot_ptr--; -*foot_ptr=info->header; -return head_ptr; -} - - -//======== -// Access -//======== - -void heap_block_get_chain(heap_handle_t heap, void* ptr, heap_block_chain_t* info) -{ -heap_t* heap_ptr=(heap_t*)heap; -size_t heap_offset=(size_t)heap; -size_t heap_start=heap_offset+sizeof(heap_t); -size_t offset=heap_block_get_offset(ptr); -size_t* head_ptr=(size_t*)offset; -info->current.offset=offset; -info->current.header=*head_ptr; -if(offset>heap_start) - { - size_t* foot_ptr=(size_t*)offset; - foot_ptr--; - info->previous.header=*foot_ptr; - info->previous.offset=offset-info->previous.size; - } -else - { - info->previous.header=0; - info->previous.offset=0; - } -size_t heap_end=heap_offset+heap_ptr->used; -size_t next_offset=offset+info->current.size; -if(next_offsetnext.offset=next_offset; - info->next.header=*head_ptr; - } -else - { - info->next.header=0; - info->next.offset=0; - } -} - -void heap_block_get_info(heap_handle_t heap, void* ptr, heap_block_info_t* info) -{ -heap_t* heap_ptr=(heap_t*)heap; -info->offset=heap_block_get_offset(ptr); -configASSERT(info->offset>=(size_t)heap+sizeof(heap_t)); -configASSERT(info->offset<(size_t)heap+heap_ptr->used); -size_t* head_ptr=(size_t*)info->offset; -info->header=*head_ptr; -configASSERT(info->size>=3*sizeof(size_t)); -configASSERT(info->offset+info->size<=(size_t)heap+heap_ptr->used); -configASSERT(*((size_t*)(info->offset+info->size-sizeof(size_t)))==*head_ptr); -} diff --git a/portable/Heap/heap_block.h b/portable/Heap/heap_block.h deleted file mode 100644 index e913cfa49..000000000 --- a/portable/Heap/heap_block.h +++ /dev/null @@ -1,83 +0,0 @@ -//============== -// heap_block.h -//============== - -// Block of continuous memory on the heap. -// Size and flags are stored twice at the head and the foot. - -// Copyright 2024, Sven Bieg (svenbieg@web.de) -// http://github.com/svenbieg/Heap - - -#ifndef _HEAP_BLOCK_H -#define _HEAP_BLOCK_H - - -//======= -// Using -//======= - -#include "heap.h" - - -//====== -// Info -//====== - -typedef struct heap_block_info_t -{ -size_t offset; -union - { - struct - { - size_t size: SIZE_BITS-1; - size_t free: 1; - }; - size_t header; - }; -}heap_block_info_t; - -typedef struct -{ -heap_block_info_t previous; -heap_block_info_t current; -heap_block_info_t next; -}heap_block_chain_t; - - -//================== -// Con-/Destructors -//================== - -void* heap_block_init(heap_handle_t heap, heap_block_info_t const* info); - - -//======== -// Common -//======== - -static inline size_t heap_block_calc_size(size_t size) -{ -return align_up(size, sizeof(size_t))+2*sizeof(size_t); -} - -static inline size_t heap_block_get_offset(void* ptr) -{ -return (size_t)ptr-sizeof(size_t); -} - -static inline void* heap_block_get_pointer(size_t offset) -{ -return (void*)(offset+sizeof(size_t)); -} - - -//======== -// Access -//======== - -void heap_block_get_chain(heap_handle_t heap, void* ptr, heap_block_chain_t* info); -void heap_block_get_info(heap_handle_t heap, void* ptr, heap_block_info_t* info); - -#endif // _HEAP_BLOCK_H diff --git a/portable/Heap/offset_index.c b/portable/Heap/offset_index.c deleted file mode 100644 index 3e1bc7195..000000000 --- a/portable/Heap/offset_index.c +++ /dev/null @@ -1,605 +0,0 @@ -//================ -// offset_index.c -//================ - -// Copyright 2024, Sven Bieg (svenbieg@web.de) -// http://github.com/svenbieg/Heap - - -//======= -// Using -//======= - -#include "heap.h" -#include "offset_index.h" -#include "parent_group.h" - - -//======= -// Group -//======= - - -// Access - -size_t offset_index_group_get_first_offset(offset_index_group_t* group) -{ -if(cluster_group_get_level(group)==0) - return offset_index_item_group_get_first_offset((offset_index_item_group_t*)group); -return ((offset_index_parent_group_t*)group)->first_offset; -} - -size_t offset_index_group_get_last_offset(offset_index_group_t* group) -{ -if(cluster_group_get_level(group)==0) - return offset_index_item_group_get_last_offset((offset_index_item_group_t*)group); -return ((offset_index_parent_group_t*)group)->last_offset; -} - - -// Modification - -bool offset_index_group_add_offset(heap_handle_t heap, offset_index_group_t* group, size_t offset, bool again) -{ -cluster_group_set_locked((cluster_group_t*)group, true); -bool added=false; -if(cluster_group_get_level(group)==0) - { - added=offset_index_item_group_add_offset((offset_index_item_group_t*)group, offset); - } -else - { - added=offset_index_parent_group_add_offset(heap, (offset_index_parent_group_t*)group, offset, again); - } -cluster_group_set_locked((cluster_group_t*)group, false); -return added; -} - -void offset_index_group_remove_offset(heap_handle_t heap, offset_index_group_t* group, size_t offset) -{ -if(cluster_group_get_level(group)==0) - { - offset_index_item_group_remove_offset((offset_index_item_group_t*)group, offset); - } -else - { - offset_index_parent_group_remove_offset(heap, (offset_index_parent_group_t*)group, offset); - } -} - -size_t offset_index_group_remove_offset_at(heap_handle_t heap, offset_index_group_t* group, size_t at) -{ -bool passive=cluster_group_is_locked((cluster_group_t*)group); -if(cluster_group_get_level(group)==0) - return offset_index_item_group_remove_offset_at((offset_index_item_group_t*)group, at, passive); -return offset_index_parent_group_remove_offset_at(heap, (offset_index_parent_group_t*)group, at, passive); -} - - -//============ -// Item-Group -//============ - - -// Con-/Destructors - -offset_index_item_group_t* offset_index_item_group_create(heap_handle_t heap) -{ -offset_index_item_group_t* group=(offset_index_item_group_t*)heap_alloc_internal(heap, sizeof(offset_index_item_group_t)); -if(group==NULL) - return NULL; -cluster_group_init((cluster_group_t*)group, 0, 0); -return group; -} - - -// Access - -size_t offset_index_item_group_get_first_offset(offset_index_item_group_t* group) -{ -uint16_t child_count=cluster_group_get_child_count((cluster_group_t*)group); -if(child_count==0) - return 0; -return group->items[0]; -} - -uint16_t offset_index_item_group_get_item_pos(offset_index_item_group_t* group, size_t offset, bool* exists_ptr) -{ -uint16_t child_count=cluster_group_get_child_count((cluster_group_t*)group); -for(uint16_t pos=0; positems[pos]; - if(item==offset) - { - *exists_ptr=true; - return pos; - } - if(item>offset) - return pos; - } -return child_count; -} - -size_t offset_index_item_group_get_last_offset(offset_index_item_group_t* group) -{ -uint16_t child_count=cluster_group_get_child_count((cluster_group_t*)group); -if(child_count==0) - return 0; -return group->items[child_count-1]; -} - - -// Modification - -bool offset_index_item_group_add_offset(offset_index_item_group_t* group, size_t offset) -{ -bool exists=false; -uint16_t pos=offset_index_item_group_get_item_pos(group, offset, &exists); -configASSERT(!exists); -uint16_t child_count=cluster_group_get_child_count((cluster_group_t*)group); -if(child_count==CLUSTER_GROUP_SIZE) - return false; -for(uint16_t u=child_count; u>pos; u--) - group->items[u]=group->items[u-1]; -group->items[pos]=offset; -cluster_group_set_child_count((cluster_group_t*)group, child_count+1); -return true; -} - -void offset_index_item_group_append_items(offset_index_item_group_t* group, size_t const* append, uint16_t count) -{ -uint16_t child_count=cluster_group_get_child_count((cluster_group_t*)group); -configASSERT(child_count+count<=CLUSTER_GROUP_SIZE); -for(uint16_t u=0; uitems[child_count+u]=append[u]; -cluster_group_set_child_count((cluster_group_t*)group, child_count+count); -} - -void offset_index_item_group_insert_items(offset_index_item_group_t* group, uint16_t at, size_t const* insert, uint16_t count) -{ -uint16_t child_count=cluster_group_get_child_count((cluster_group_t*)group); -for(uint16_t u=child_count+count-1; u>=at+count; u--) - group->items[u]=group->items[u-count]; -for(uint16_t u=0; uitems[at+u]=insert[u]; -cluster_group_set_child_count((cluster_group_t*)group, child_count+count); -} - -size_t offset_index_item_group_remove_item(offset_index_item_group_t* group, uint16_t at) -{ -uint16_t child_count=cluster_group_get_child_count((cluster_group_t*)group); -size_t offset=group->items[at]; -for(uint16_t u=at; u+1items[u]=group->items[u+1]; -cluster_group_set_child_count((cluster_group_t*)group, child_count-1); -return offset; -} - -void offset_index_item_group_remove_offset(offset_index_item_group_t* group, size_t offset) -{ -bool exists=false; -uint16_t pos=offset_index_item_group_get_item_pos(group, offset, &exists); -configASSERT(exists); -offset_index_item_group_remove_item(group, pos); -} - -size_t offset_index_item_group_remove_offset_at(offset_index_item_group_t* group, size_t at, bool passive) -{ -configASSERT(!passive); -uint16_t child_count=cluster_group_get_child_count((cluster_group_t*)group); -configASSERT(atitems[u]=group->items[u+count]; -cluster_group_set_child_count((cluster_group_t*)group, child_count-count); -} - - -//============== -// Parent-group -//============== - - -// Con-/Destructors - -offset_index_parent_group_t* offset_index_parent_group_create(heap_handle_t heap, uint16_t level) -{ -offset_index_parent_group_t* group=(offset_index_parent_group_t*)heap_alloc_internal(heap, sizeof(offset_index_parent_group_t)); -if(group==NULL) - return NULL; -cluster_group_init((cluster_group_t*)group, level, 0); -group->first_offset=0; -group->last_offset=0; -group->item_count=0; -return group; -} - -offset_index_parent_group_t* offset_index_parent_group_create_with_child(heap_handle_t heap, offset_index_group_t* child) -{ -offset_index_parent_group_t* group=(offset_index_parent_group_t*)heap_alloc_internal(heap, sizeof(offset_index_parent_group_t)); -if(group==NULL) - return NULL; -uint16_t child_level=cluster_group_get_level(child); -cluster_group_init((cluster_group_t*)group, child_level+1, 1); -group->first_offset=offset_index_group_get_first_offset(child); -group->last_offset=offset_index_group_get_last_offset(child); -group->item_count=cluster_group_get_item_count((cluster_group_t*)child); -group->children[0]=child; -return group; -} - - -// Access - -uint16_t offset_index_parent_group_get_item_pos(offset_index_parent_group_t* group, size_t offset, uint16_t* pos_ptr, bool must_exist) -{ -uint16_t child_count=cluster_group_get_child_count((cluster_group_t*)group); -uint16_t pos=0; -for(; poschildren[pos]); - if(offsetchildren[pos]); - if(offset>last_offset) - continue; - *pos_ptr=pos; - return 1; - } -if(must_exist) - return 0; -if(pos==0) - { - *pos_ptr=pos; - return 1; - } -if(pos==child_count) - { - *pos_ptr=pos-1; - return 1; - } -*pos_ptr=pos-1; -return 2; -} - - -// Modification - -bool offset_index_parent_group_add_offset(heap_handle_t heap, offset_index_parent_group_t* group, size_t offset, bool again) -{ -if(!offset_index_parent_group_add_offset_internal(heap, group, offset, again)) - return false; -group->item_count++; -offset_index_parent_group_update_bounds(group); -return true; -} - -bool offset_index_parent_group_add_offset_internal(heap_handle_t heap, offset_index_parent_group_t* group, size_t offset, bool again) -{ -uint16_t child_count=cluster_group_get_child_count((cluster_group_t*)group); -if(!child_count) - return false; -uint16_t pos=0; -uint16_t count=offset_index_parent_group_get_item_pos(group, offset, &pos, false); -if(!again) - { - for(uint16_t u=0; uchildren[pos+u], offset, false)) - return true; - } - if(offset_index_parent_group_shift_children(group, pos, count)) - { - count=offset_index_parent_group_get_item_pos(group, offset, &pos, false); - for(uint16_t u=0; uchildren[pos+u], offset, false)) - return true; - } - } - } -if(!offset_index_parent_group_split_child(heap, group, pos)) - return false; -count=offset_index_parent_group_get_item_pos(group, offset, &pos, false); -for(uint16_t u=0; uchildren[pos+u], offset, true)) - return true; - } -return false; -} - -void offset_index_parent_group_append_groups(offset_index_parent_group_t* group, offset_index_group_t* const* append, uint16_t count) -{ -parent_group_append_groups((parent_group_t*)group, (cluster_group_t* const*)append, count); -offset_index_parent_group_update_bounds(group); -} - -bool offset_index_parent_group_combine_child(heap_handle_t heap, offset_index_parent_group_t* group, uint16_t at) -{ -uint16_t count=cluster_group_get_child_count((cluster_group_t*)group->children[at]); -if(count==0) - { - parent_group_remove_group(heap, (parent_group_t*)group, at); - return true; - } -if(at>0) - { - uint16_t before=cluster_group_get_child_count((cluster_group_t*)group->children[at-1]); - if(count+before<=CLUSTER_GROUP_SIZE) - { - offset_index_parent_group_move_children(group, at, at-1, count); - parent_group_remove_group(heap, (parent_group_t*)group, at); - return true; - } - } -uint16_t child_count=cluster_group_get_child_count((cluster_group_t*)group); -if(at+1children[at+1]); - if(count+after<=CLUSTER_GROUP_SIZE) - { - offset_index_parent_group_move_children(group, at+1, at, after); - parent_group_remove_group(heap, (parent_group_t*)group, at+1); - return true; - } - } -return false; -} - -void offset_index_parent_group_combine_children(heap_handle_t heap, offset_index_parent_group_t* group) -{ -uint16_t child_count=cluster_group_get_child_count((cluster_group_t*)group); -for(uint16_t pos=0; pos1) - { - offset_index_parent_group_t* src=(offset_index_parent_group_t*)group->children[from]; - offset_index_parent_group_t* dst=(offset_index_parent_group_t*)group->children[to]; - if(from>to) - { - offset_index_parent_group_append_groups(dst, src->children, count); - offset_index_parent_group_remove_groups(src, 0, count); - } - else - { - uint16_t src_count=cluster_group_get_child_count((cluster_group_t*)src); - offset_index_parent_group_insert_groups(dst, 0, &src->children[src_count-count], count); - offset_index_parent_group_remove_groups(src, src_count-count, count); - } - } -else - { - offset_index_item_group_t* src=(offset_index_item_group_t*)group->children[from]; - offset_index_item_group_t* dst=(offset_index_item_group_t*)group->children[to]; - if(from>to) - { - offset_index_item_group_append_items(dst, src->items, count); - offset_index_item_group_remove_items(src, 0, count); - } - else - { - uint16_t src_count=cluster_group_get_child_count((cluster_group_t*)src); - offset_index_item_group_insert_items(dst, 0, &src->items[src_count-count], count); - offset_index_item_group_remove_items(src, src_count-count, count); - } - } -} - -void offset_index_parent_group_move_empty_slot(offset_index_parent_group_t* group, uint16_t from, uint16_t to) -{ -if(fromto; u--) - offset_index_parent_group_move_children(group, u-1, u, 1); - } -} - -void offset_index_parent_group_remove_groups(offset_index_parent_group_t* group, uint16_t at, uint16_t count) -{ -parent_group_remove_groups((parent_group_t*)group, at, count); -offset_index_parent_group_update_bounds(group); -} - -void offset_index_parent_group_remove_offset(heap_handle_t heap, offset_index_parent_group_t* group, size_t offset) -{ -uint16_t pos=0; -uint16_t count=offset_index_parent_group_get_item_pos(group, offset, &pos, true); -configASSERT(count==1); -offset_index_group_remove_offset(heap, group->children[pos], offset); -offset_index_parent_group_combine_child(heap, group, pos); -group->item_count--; -offset_index_parent_group_update_bounds(group); -} - -size_t offset_index_parent_group_remove_offset_at(heap_handle_t heap, offset_index_parent_group_t* group, size_t at, bool passive) -{ -uint16_t pos=parent_group_get_group((parent_group_t*)group, &at); -configASSERT(poschildren[pos], at); -if(passive) - { - cluster_group_set_dirty((cluster_group_t*)group, true); - } -else - { - if(cluster_group_is_dirty((cluster_group_t*)group)) - { - offset_index_parent_group_combine_children(heap, group); - cluster_group_set_dirty((cluster_group_t*)group, false); - } - else - { - offset_index_parent_group_combine_child(heap, group, pos); - } - } -group->item_count--; -offset_index_parent_group_update_bounds(group); -return offset; -} - -bool offset_index_parent_group_shift_children(offset_index_parent_group_t* group, uint16_t at, uint16_t count) -{ -int16_t space=parent_group_get_nearest_space((parent_group_t*)group, at); -if(space<0) - return false; -if(count>1&&space>at) - at++; -offset_index_parent_group_move_empty_slot(group, space, at); -return true; -} - -bool offset_index_parent_group_split_child(heap_handle_t heap, offset_index_parent_group_t* group, uint16_t at) -{ -uint16_t child_count=cluster_group_get_child_count((cluster_group_t*)group); -if(child_count==CLUSTER_GROUP_SIZE) - return false; -offset_index_group_t* child=NULL; -uint16_t level=cluster_group_get_level((cluster_group_t*)group); -if(level>1) - { - child=(offset_index_group_t*)offset_index_parent_group_create(heap, level-1); - } -else - { - child=(offset_index_group_t*)offset_index_item_group_create(heap); - } -if(!child) - return false; -for(uint16_t u=child_count; u>at+1; u--) - group->children[u]=group->children[u-1]; -group->children[at+1]=child; -cluster_group_set_child_count((cluster_group_t*)group, child_count+1); -offset_index_parent_group_move_children(group, at, at+1, 1); -return true; -} - -void offset_index_parent_group_update_bounds(offset_index_parent_group_t* group) -{ -uint16_t child_count=cluster_group_get_child_count((cluster_group_t*)group); -if(child_count==0) - { - group->first_offset=0; - group->last_offset=0; - return; - } -for(uint16_t pos=0; posfirst_offset=offset_index_group_get_first_offset(group->children[pos]); - if(group->first_offset!=0) - break; - } -for(uint16_t pos=child_count; pos>0; pos--) - { - group->last_offset=offset_index_group_get_last_offset(group->children[pos-1]); - if(group->last_offset!=0) - break; - } -} - - -//======= -// Index -//======= - -// Con-/Destructors - -void offset_index_init(offset_index_t* index) -{ -index->root=NULL; -} - - -// Modification - -bool offset_index_add_offset(heap_handle_t heap, offset_index_t* index, size_t offset) -{ -if(!index->root) - { - index->root=(offset_index_group_t*)offset_index_item_group_create(heap); - if(!index->root) - return false; - } -if(offset_index_group_add_offset(heap, index->root, offset, false)) - return true; -if(!offset_index_lift_root(heap, index)) - return false; -return offset_index_group_add_offset(heap, index->root, offset, true); -} - -void offset_index_drop_root(heap_handle_t heap, offset_index_t* index) -{ -offset_index_group_t* root=index->root; -if(cluster_group_is_locked((cluster_group_t*)root)) - return; -uint16_t child_count=cluster_group_get_child_count((cluster_group_t*)root); -uint16_t level=cluster_group_get_level((cluster_group_t*)root); -if(level==0) - { - if(child_count==0) - { - index->root=NULL; - heap_free_to_cache(heap, root); - } - return; - } -if(child_count>1) - return; -offset_index_parent_group_t* parent_group=(offset_index_parent_group_t*)root; -index->root=parent_group->children[0]; -heap_free_to_cache(heap, root); -} - -bool offset_index_lift_root(heap_handle_t heap, offset_index_t* index) -{ -offset_index_parent_group_t* root=offset_index_parent_group_create_with_child(heap, index->root); -if(!root) - return false; -index->root=(offset_index_group_t*)root; -return true; -} - -void offset_index_remove_offset(heap_handle_t heap, offset_index_t* index, size_t offset) -{ -offset_index_group_remove_offset(heap, index->root, offset); -offset_index_drop_root(heap, index); -} - -size_t offset_index_remove_offset_at(heap_handle_t heap, offset_index_t* index, size_t at) -{ -configASSERT(index->root); -size_t offset=offset_index_group_remove_offset_at(heap, index->root, at); -offset_index_drop_root(heap, index); -return offset; -} diff --git a/portable/Heap/offset_index.h b/portable/Heap/offset_index.h deleted file mode 100644 index 883114ccc..000000000 --- a/portable/Heap/offset_index.h +++ /dev/null @@ -1,129 +0,0 @@ -//================ -// offset_index.h -//================ - -// Sorted offsets of free memory-blocks with the same size - -// Copyright 2024, Sven Bieg (svenbieg@web.de) -// http://github.com/svenbieg/Heap - - -#ifndef _OFFSET_INDEX_H -#define _OFFSET_INDEX_H - - -//======= -// Using -//======= - -#include "cluster_group.h" - - -//======= -// Group -//======= - -typedef cluster_group_t offset_index_group_t; - -// Access -size_t offset_index_group_get_first_offset(offset_index_group_t* group); -size_t offset_index_group_get_last_offset(offset_index_group_t* group); - -// Modification -bool offset_index_group_add_offset(heap_handle_t heap, offset_index_group_t* group, size_t offset, bool again); -void offset_index_group_remove_offset(heap_handle_t heap, offset_index_group_t* group, size_t offset); -size_t offset_index_group_remove_offset_at(heap_handle_t heap, offset_index_group_t* group, size_t at); - - -//============ -// Item-group -//============ - -typedef struct offset_index_item_group_t -{ -cluster_group_t header; -size_t items[CLUSTER_GROUP_SIZE]; -}offset_index_item_group_t; - -// Con-/Destructors -offset_index_item_group_t* offset_index_item_group_create(heap_handle_t heap); - -// Access -size_t offset_index_item_group_get_first_offset(offset_index_item_group_t* group); -uint16_t offset_index_item_group_get_item_pos(offset_index_item_group_t* group, size_t offset, bool* exists_ptr); -size_t offset_index_item_group_get_last_offset(offset_index_item_group_t* group); - -// Modification -bool offset_index_item_group_add_offset(offset_index_item_group_t* group, size_t offset); -void offset_index_item_group_append_items(offset_index_item_group_t* group, size_t const* items, uint16_t count); -void offset_index_item_group_insert_items(offset_index_item_group_t* group, uint16_t at, size_t const* insert, uint16_t count); -size_t offset_index_item_group_remove_item(offset_index_item_group_t* group, uint16_t at); -void offset_index_item_group_remove_offset(offset_index_item_group_t* group, size_t offset); -size_t offset_index_item_group_remove_offset_at(offset_index_item_group_t* group, size_t at, bool passive); -void offset_index_item_group_remove_items(offset_index_item_group_t* group, uint16_t at, uint16_t count); - - -//============== -// Parent-group -//============== - -typedef struct -{ -cluster_group_t header; -size_t item_count; -size_t first_offset; -size_t last_offset; -offset_index_group_t* children[CLUSTER_GROUP_SIZE]; -}offset_index_parent_group_t; - - -// Con-/Destructors -offset_index_parent_group_t* offset_index_parent_group_create(heap_handle_t heap, uint16_t level); -offset_index_parent_group_t* offset_index_parent_group_create_with_child(heap_handle_t heap, offset_index_group_t* child); - -// Access -uint16_t offset_index_parent_group_get_item_pos(offset_index_parent_group_t* group, size_t offset, uint16_t* pos_ptr, bool must_exist); - -// Modification -bool offset_index_parent_group_add_offset(heap_handle_t heap, offset_index_parent_group_t* group, size_t offset, bool again); -bool offset_index_parent_group_add_offset_internal(heap_handle_t heap, offset_index_parent_group_t* group, size_t offset, bool again); -void offset_index_parent_group_append_groups(offset_index_parent_group_t* group, offset_index_group_t* const* append, uint16_t count); -bool offset_index_parent_group_combine_child(heap_handle_t heap, offset_index_parent_group_t* group, uint16_t at); -void offset_index_parent_group_combine_children(heap_handle_t heap, offset_index_parent_group_t* group); -void offset_index_parent_group_insert_groups(offset_index_parent_group_t* group, uint16_t at, offset_index_group_t* const* insert, uint16_t count); -void offset_index_parent_group_move_children(offset_index_parent_group_t* group, uint16_t from, uint16_t to, uint16_t count); -void offset_index_parent_group_move_empty_slot(offset_index_parent_group_t* group, uint16_t from, uint16_t to); -void offset_index_parent_group_remove_groups(offset_index_parent_group_t* group, uint16_t at, uint16_t count); -void offset_index_parent_group_remove_offset(heap_handle_t heap, offset_index_parent_group_t* group, size_t offset); -size_t offset_index_parent_group_remove_offset_at(heap_handle_t heap, offset_index_parent_group_t* group, size_t at, bool passive); -bool offset_index_parent_group_shift_children(offset_index_parent_group_t* group, uint16_t at, uint16_t count); -bool offset_index_parent_group_split_child(heap_handle_t heap, offset_index_parent_group_t* group, uint16_t at); -void offset_index_parent_group_update_bounds(offset_index_parent_group_t* group); - - -//======= -// Index -//======= - -typedef struct -{ -offset_index_group_t* root; -}offset_index_t; - -// Con-/Destructors -void offset_index_init(offset_index_t* index); - -// Access -inline size_t offset_index_get_offset_count(offset_index_t* index) -{ -return cluster_group_get_item_count((cluster_group_t*)index->root); -} - -// Modification -bool offset_index_add_offset(heap_handle_t heap, offset_index_t* index, size_t offset); -void offset_index_drop_root(heap_handle_t heap, offset_index_t* index); -bool offset_index_lift_root(heap_handle_t heap, offset_index_t* index); -void offset_index_remove_offset(heap_handle_t heap, offset_index_t* index, size_t offset); -size_t offset_index_remove_offset_at(heap_handle_t heap, offset_index_t* index, size_t at); - -#endif // _OFFSET_INDEX_H diff --git a/portable/Heap/parent_group.c b/portable/Heap/parent_group.c deleted file mode 100644 index 9854e023a..000000000 --- a/portable/Heap/parent_group.c +++ /dev/null @@ -1,112 +0,0 @@ -//================ -// parent_group.c -//================ - -// Copyright 2024, Sven Bieg (svenbieg@web.de) -// http://github.com/svenbieg/Heap - - -//======= -// Using -//======= - -#include "parent_group.h" - - -//======== -// Access -//======== - -uint16_t parent_group_get_group(parent_group_t* group, size_t* pos) -{ -uint16_t child_count=cluster_group_get_child_count((cluster_group_t*)group); -for(uint16_t u=0; uchildren[u]); - if(*pos=0||after=0) - { - uint16_t count=cluster_group_get_child_count(group->children[before]); - if(countchildren[after]); - if(countchildren[child_count+u]=append[u]; - group->item_count+=cluster_group_get_item_count(append[u]); - } -cluster_group_set_child_count((cluster_group_t*)group, child_count+count); -} - -void parent_group_insert_groups(parent_group_t* group, uint16_t at, cluster_group_t* const* insert, uint16_t count) -{ -uint16_t child_count=cluster_group_get_child_count((cluster_group_t*)group); -configASSERT(at<=child_count); -configASSERT(child_count+count<=CLUSTER_GROUP_SIZE); -for(uint16_t u=child_count+count-1; u>=at+count; u--) - group->children[u]=group->children[u-count]; -for(uint16_t u=0; uchildren[at+u]=insert[u]; - group->item_count+=cluster_group_get_item_count(insert[u]); - } -cluster_group_set_child_count((cluster_group_t*)group, child_count+count); -} - -void parent_group_remove_group(heap_handle_t heap, parent_group_t* group, uint16_t at) -{ -uint16_t child_count=cluster_group_get_child_count((cluster_group_t*)group); -configASSERT(atchildren[at]; -configASSERT(cluster_group_get_child_count(child)==0); -configASSERT(cluster_group_get_item_count(child)==0); -for(uint16_t u=at; u+1children[u]=group->children[u+1]; -cluster_group_set_child_count((cluster_group_t*)group, child_count-1); -heap_free_to_cache(heap, child); -} - -void parent_group_remove_groups(parent_group_t* group, uint16_t at, uint16_t count) -{ -uint16_t child_count=cluster_group_get_child_count((cluster_group_t*)group); -configASSERT(at+count<=child_count); -for(uint16_t u=0; uitem_count-=cluster_group_get_item_count(group->children[at+u]); -for(uint16_t u=at; u+countchildren[u]=group->children[u+count]; -cluster_group_set_child_count((cluster_group_t*)group, child_count-count); -} diff --git a/portable/Heap/parent_group.h b/portable/Heap/parent_group.h deleted file mode 100644 index 1166fded6..000000000 --- a/portable/Heap/parent_group.h +++ /dev/null @@ -1,53 +0,0 @@ -//================ -// parent_group.h -//================ - -// Shared functions for block_map and offset_index. - -// Copyright 2024, Sven Bieg (svenbieg@web.de) -// http://github.com/svenbieg/Heap - - -#ifndef _PARENT_GROUP_H -#define _PARENT_GROUP_H - - -//======= -// Using -//======= - -#include "cluster_group.h" - - -//============== -// Parent-Group -//============== - -typedef struct -{ -cluster_group_t header; -size_t item_count; -size_t first; -size_t last; -cluster_group_t* children[CLUSTER_GROUP_SIZE]; -}parent_group_t; - - -//======== -// Access -//======== - -uint16_t parent_group_get_group(parent_group_t* group, size_t* at); -int16_t parent_group_get_nearest_space(parent_group_t* group, int16_t pos); - - -//============== -// Modification -//============== - -void parent_group_append_groups(parent_group_t* group, cluster_group_t* const* append, uint16_t count); -void parent_group_insert_groups(parent_group_t* group, uint16_t at, cluster_group_t* const* insert, uint16_t count); -void parent_group_remove_group(heap_handle_t heap, parent_group_t* group, uint16_t at); -void parent_group_remove_groups(parent_group_t* group, uint16_t at, uint16_t count); - -#endif // _PARENT_GROUP_H diff --git a/portable/MemMang/heap_6.c b/portable/MemMang/heap_6.c new file mode 100644 index 000000000..3b2200b04 --- /dev/null +++ b/portable/MemMang/heap_6.c @@ -0,0 +1,1875 @@ +//========== +// heap_6.c +//========== + +// Memory-manager for real-time C++ applications. +// Allocations and deletions are done in constant low time. + +// Copyright 2024, Sven Bieg (svenbieg@web.de) +// http://github.com/svenbieg/Heap + + +//======= +// Using +//======= + +#include "heap_6.h" +#include "semphr.h" + + +//============= +// Concurrency +//============= + +static inline bool heap_lock() +{ +#if(configUSE_HEAP_IN_ISR==1) +vTaskSuspendAll(); +return true; +#else +taskENTER_CRITICAL(); +if(xSemaphoreTake(heap_mutex, portMAX_DELAY)==pdTRUE) + return true; +return false; +#endif +} + +static inline void heap_unlock(bool locked) +{ +#if(configUSE_HEAP_IN_ISR==1) +xTaskResumeAll(); +#else +if(locked) + xSemaphoreGive(heap_lock); +taskEXIT_CRITICAL(); +#endif +} + + +//========= +// Globals +//========= + +#if(configUSE_HEAP_IN_ISR==0) +static SemaphoreHandle_t heap_mutex=NULL; +static StaticSemaphore_t heap_mutex_buf; +#endif + +static heap_handle_t first_heap=NULL; +static heap_handle_t last_heap=NULL; + +static size_t xFreeBlocks=0; +static size_t xFreeBytes=0; +static size_t xMinimumFreeBytes=0; +static size_t xSuccessfulAllocations=0; +static size_t xSuccessfulDeletions=0; + +static inline void heap_reduce_free_bytes(size_t reduce) +{ +xFreeBytes-=reduce; +xMinimumFreeBytes=min(xMinimumFreeBytes, xFreeBytes); +} + + +//====== +// Heap +//====== + +// Con-/Destructors + +heap_handle_t heap_create(heap_handle_t prev_heap, size_t offset, size_t size) +{ +offset=align_up(offset, sizeof(size_t)); +size=align_down(size, sizeof(size_t)); +configASSERT(size>sizeof(heap_t)); +size_t available=size-sizeof(heap_t); +heap_handle_t heap=(heap_t*)offset; +heap->free=available; +heap->used=sizeof(heap_t); +heap->size=size; +heap->free_block=0; +heap->next_heap=0; +block_map_init((block_map_t*)&heap->map_free); +if(prev_heap) + prev_heap->next_heap=(size_t)heap; +xFreeBlocks++; +xFreeBytes+=available; +xMinimumFreeBytes=xFreeBytes; +return heap; +} + + +// Allocation + +void* heap_alloc(heap_handle_t heap, size_t size) +{ +configASSERT(heap!=NULL); +configASSERT(size!=0); +size=heap_block_calc_size(size); +void* buf=heap_alloc_from_map(heap, size); +if(buf) + { + heap_free_cache(heap); + } +else + { + buf=heap_alloc_from_foot(heap, size); + } +return buf; +} + +void heap_free(heap_handle_t heap, void* buf) +{ +configASSERT(heap!=NULL); +if(!buf) + return; +heap_free_to_map(heap, buf); +heap_free_cache(heap); +} + + +// Internal Allocation + +void* heap_alloc_from_foot(heap_handle_t heap, size_t size) +{ +if(heap->used+size>heap->size) + return NULL; +heap_block_info_t info; +info.offset=(size_t)heap+heap->used; +info.size=size; +info.free=false; +heap->free-=size; +heap->used+=size; +heap_reduce_free_bytes(size); +return heap_block_init(heap, &info); +} + +void* heap_alloc_from_map(heap_handle_t heap, size_t size) +{ +heap_block_info_t info; +if(!block_map_get_block(heap, (block_map_t*)&heap->map_free, size, &info)) + return NULL; +heap->free-=info.size; +heap_reduce_free_bytes(info.size); +size_t free_size=info.size-size; +if(free_size>=BLOCK_SIZE_MIN) + { + heap_block_info_t free_info; + free_info.offset=info.offset+size; + free_info.size=free_size; + free_info.free=false; + void* free_buf=heap_block_init(heap, &free_info); + heap_free_to_cache(heap, free_buf); + info.size=size; + } +xFreeBlocks--; +info.free=false; +return heap_block_init(heap, &info); +} + +void* heap_alloc_internal(heap_handle_t heap, size_t size) +{ +size=heap_block_calc_size(size); +void* buf=heap_alloc_from_map(heap, size); +if(buf) + return buf; +return heap_alloc_from_foot(heap, size); +} + +void heap_free_cache(heap_handle_t heap) +{ +heap_t* heap_ptr=(heap_t*)heap; +size_t free_block=heap_ptr->free_block; +if(!free_block) + return; +size_t* buf=(size_t*)heap_block_get_pointer(free_block); +heap_ptr->free_block=*buf; +heap_free_to_map(heap, buf); +} + +void heap_free_to_cache(heap_handle_t heap, void* buf) +{ +size_t* body_ptr=(size_t*)buf; +*body_ptr=heap->free_block; +heap->free_block=heap_block_get_offset(buf); +} + +void heap_free_to_map(heap_handle_t heap, void* buf) +{ +heap_block_chain_t info; +heap_block_get_chain(heap, buf, &info); +size_t heap_end=(size_t)heap+heap->used; +size_t offset=info.current.offset; +size_t size=info.current.size; +configASSERT(offset>=(size_t)heap); +configASSERT(offsetmap_free, &info.previous); + heap->free-=info.previous.size; + xFreeBlocks--; + xFreeBytes-=info.previous.size; + } +if(!info.next.offset) + { + heap->free+=size; + heap->used-=size; + xFreeBytes+=size; + return; + } +if(info.next.free) + { + size+=info.next.size; + block_map_remove_block(heap, (block_map_t*)&heap->map_free, &info.next); + heap->free-=info.next.size; + xFreeBlocks--; + xFreeBytes-=info.next.size; + } +info.current.offset=offset; +info.current.size=size; +info.current.free=true; +heap_block_init(heap, &info.current); +bool added=block_map_add_block(heap, (block_map_t*)&heap->map_free, &info.current); +if(!added) + { + info.current.free=false; + heap_block_init(heap, &info.current); + buf=heap_block_get_pointer(info.current.offset); + heap_free_to_cache(heap, buf); + return; + } +heap->free+=size; +xFreeBlocks++; +xFreeBytes+=size; +} + + +// Statistic + +size_t heap_get_largest_free_block(heap_handle_t heap) +{ +size_t largest=0; +largest=block_map_get_last_size((block_map_t*)&heap->map_free); +largest=max(largest, heap->size-heap->used); +return largest; +} + + +//============ +// Heap-Block +//============ + +// Con-/Destructors + +void* heap_block_init(heap_handle_t heap, heap_block_info_t const* info) +{ +heap_t* heap_ptr=(heap_t*)heap; +configASSERT(info->size%sizeof(size_t)==0); +configASSERT(info->offset>=(size_t)heap+sizeof(heap_t)); +configASSERT(info->offset+info->size<=(size_t)heap+heap_ptr->size); +size_t* head_ptr=(size_t*)info->offset; +*head_ptr=info->header; +head_ptr++; +size_t* foot_ptr=(size_t*)(info->offset+info->size); +foot_ptr--; +*foot_ptr=info->header; +return head_ptr; +} + + +// Access + +void heap_block_get_chain(heap_handle_t heap, void* ptr, heap_block_chain_t* info) +{ +heap_t* heap_ptr=(heap_t*)heap; +size_t heap_offset=(size_t)heap; +size_t heap_start=heap_offset+sizeof(heap_t); +size_t offset=heap_block_get_offset(ptr); +size_t* head_ptr=(size_t*)offset; +info->current.offset=offset; +info->current.header=*head_ptr; +if(offset>heap_start) + { + size_t* foot_ptr=(size_t*)offset; + foot_ptr--; + info->previous.header=*foot_ptr; + info->previous.offset=offset-info->previous.size; + } +else + { + info->previous.header=0; + info->previous.offset=0; + } +size_t heap_end=heap_offset+heap_ptr->used; +size_t next_offset=offset+info->current.size; +if(next_offsetnext.offset=next_offset; + info->next.header=*head_ptr; + } +else + { + info->next.header=0; + info->next.offset=0; + } +} + +void heap_block_get_info(heap_handle_t heap, void* ptr, heap_block_info_t* info) +{ +heap_t* heap_ptr=(heap_t*)heap; +info->offset=heap_block_get_offset(ptr); +configASSERT(info->offset>=(size_t)heap+sizeof(heap_t)); +configASSERT(info->offset<(size_t)heap+heap_ptr->used); +size_t* head_ptr=(size_t*)info->offset; +info->header=*head_ptr; +configASSERT(info->size>=3*sizeof(size_t)); +configASSERT(info->offset+info->size<=(size_t)heap+heap_ptr->used); +configASSERT(*((size_t*)(info->offset+info->size-sizeof(size_t)))==*head_ptr); +} + + +//=============== +// Cluster-Group +//=============== + +// Access + +size_t cluster_group_get_item_count(cluster_group_t* group) +{ +if(!group) + return 0; +cluster_group_t get; +get.value=group->value; +if(get.level==0) + return get.child_count; +parent_group_t* parent_group=(parent_group_t*)group; +return parent_group->item_count; +} + + +//============== +// Parent-Group +//============== + +// Access + +uint16_t parent_group_get_group(parent_group_t* group, size_t* pos) +{ +uint16_t child_count=cluster_group_get_child_count((cluster_group_t*)group); +for(uint16_t u=0; uchildren[u]); + if(*pos=0||after=0) + { + uint16_t count=cluster_group_get_child_count(group->children[before]); + if(countchildren[after]); + if(countchildren[child_count+u]=append[u]; + group->item_count+=cluster_group_get_item_count(append[u]); + } +cluster_group_set_child_count((cluster_group_t*)group, child_count+count); +} + +void parent_group_insert_groups(parent_group_t* group, uint16_t at, cluster_group_t* const* insert, uint16_t count) +{ +uint16_t child_count=cluster_group_get_child_count((cluster_group_t*)group); +configASSERT(at<=child_count); +configASSERT(child_count+count<=CLUSTER_GROUP_SIZE); +for(uint16_t u=child_count+count-1; u>=at+count; u--) + group->children[u]=group->children[u-count]; +for(uint16_t u=0; uchildren[at+u]=insert[u]; + group->item_count+=cluster_group_get_item_count(insert[u]); + } +cluster_group_set_child_count((cluster_group_t*)group, child_count+count); +} + +void parent_group_remove_group(heap_handle_t heap, parent_group_t* group, uint16_t at) +{ +uint16_t child_count=cluster_group_get_child_count((cluster_group_t*)group); +configASSERT(atchildren[at]; +configASSERT(cluster_group_get_child_count(child)==0); +configASSERT(cluster_group_get_item_count(child)==0); +for(uint16_t u=at; u+1children[u]=group->children[u+1]; +cluster_group_set_child_count((cluster_group_t*)group, child_count-1); +heap_free_to_cache(heap, child); +} + +void parent_group_remove_groups(parent_group_t* group, uint16_t at, uint16_t count) +{ +uint16_t child_count=cluster_group_get_child_count((cluster_group_t*)group); +configASSERT(at+count<=child_count); +for(uint16_t u=0; uitem_count-=cluster_group_get_item_count(group->children[at+u]); +for(uint16_t u=at; u+countchildren[u]=group->children[u+count]; +cluster_group_set_child_count((cluster_group_t*)group, child_count-count); +} + + +//================= +// Block-Map-Group +//================= + +// Access + +size_t block_map_group_get_first_size(block_map_group_t* group) +{ +if(cluster_group_get_level(group)==0) + return block_map_item_group_get_first_size((block_map_item_group_t*)group); +return ((block_map_parent_group_t*)group)->first_size; +} + +block_map_item_t* block_map_group_get_item(block_map_group_t* group, size_t size) +{ +if(cluster_group_get_level(group)==0) + return block_map_item_group_get_item((block_map_item_group_t*)group, size); +return block_map_parent_group_get_item((block_map_parent_group_t*)group, size); +} + +size_t block_map_group_get_last_size(block_map_group_t* group) +{ +if(group==NULL) + return 0; +if(cluster_group_get_level(group)==0) + return block_map_item_group_get_last_size((block_map_item_group_t*)group); +return ((block_map_parent_group_t*)group)->last_size; +} + + +// Modification + +bool block_map_group_add_block(heap_handle_t heap, block_map_group_t* group, heap_block_info_t const* info, bool again) +{ +cluster_group_set_locked((cluster_group_t*)group, true); +bool added=false; +if(cluster_group_get_level(group)==0) + { + added=block_map_item_group_add_block(heap, (block_map_item_group_t*)group, info); + } +else + { + added=block_map_parent_group_add_block(heap, (block_map_parent_group_t*)group, info, again); + } +cluster_group_set_locked((cluster_group_t*)group, false); +return added; +} + +bool block_map_group_get_block(heap_handle_t heap, block_map_group_t* group, size_t min_size, heap_block_info_t* info) +{ +bool passive=cluster_group_is_locked((cluster_group_t*)group); +if(cluster_group_get_level(group)==0) + return block_map_item_group_get_block(heap, (block_map_item_group_t*)group, min_size, info, passive); +return block_map_parent_group_get_block(heap, (block_map_parent_group_t*)group, min_size, info, passive); +} + +bool block_map_group_remove_block(heap_handle_t heap, block_map_group_t* group, heap_block_info_t const* info) +{ +if(cluster_group_get_level(group)==0) + return block_map_item_group_remove_block(heap, (block_map_item_group_t*)group, info); +return block_map_parent_group_remove_block(heap, (block_map_parent_group_t*)group, info); +} + + +//====================== +// Block-Map-Item-Group +//====================== + +// Con-/Destructors + +block_map_item_group_t* block_map_item_group_create(heap_handle_t heap) +{ +block_map_item_group_t* group=(block_map_item_group_t*)heap_alloc_internal(heap, sizeof(block_map_item_group_t)); +if(group==NULL) + return NULL; +cluster_group_init((cluster_group_t*)group, 0, 0); +return group; +} + + +// Access + +size_t block_map_item_group_get_first_size(block_map_item_group_t* group) +{ +uint16_t child_count=cluster_group_get_child_count((cluster_group_t*)group); +if(child_count==0) + return 0; +return group->items[0].size; +} + +block_map_item_t* block_map_item_group_get_item(block_map_item_group_t* group, size_t size) +{ +bool exists=false; +int16_t pos=block_map_item_group_get_item_pos(group, size, &exists); +configASSERT(exists); +return &group->items[pos]; +} + +block_map_item_t* block_map_item_group_get_item_at(block_map_item_group_t* group, uint16_t at) +{ +configASSERT(atitems[at]; +} + +uint16_t block_map_item_group_get_item_pos(block_map_item_group_t* group, size_t size, bool* exists_ptr) +{ +uint16_t child_count=cluster_group_get_child_count((cluster_group_t*)group); +for(uint16_t pos=0; positems[pos]; + if(item->entry==0) + continue; + if(item->size==size) + { + *exists_ptr=true; + return pos; + } + if(item->size>size) + return pos; + } +return child_count; +} + +size_t block_map_item_group_get_last_size(block_map_item_group_t* group) +{ +uint16_t child_count=cluster_group_get_child_count((cluster_group_t*)group); +if(child_count==0) + return 0; +return group->items[child_count-1].size; +} + + +// Modification + +bool block_map_item_group_add_block(heap_handle_t heap, block_map_item_group_t* group, heap_block_info_t const* info) +{ +bool exists=false; +uint16_t pos=block_map_item_group_get_item_pos(group, info->size, &exists); +if(!exists) + return block_map_item_group_add_item(group, info, pos); +block_map_item_t* item=block_map_item_group_get_item_at(group, pos); +bool added=false; +if(item->single) + { + offset_index_t index; + offset_index_init(&index); + added=offset_index_add_offset(heap, &index, info->offset); + if(!added) + return false; + if(item->offset) + offset_index_add_offset(heap, &index, item->offset); + item->index=(size_t)index.root; + } +else + { + added=offset_index_add_offset(heap, &item->index, info->offset); + } +if(cluster_group_is_dirty((cluster_group_t*)group)) + { + block_map_item_group_cleanup(group); + cluster_group_set_dirty((cluster_group_t*)group, false); + } +return added; +} + +bool block_map_item_group_add_item(block_map_item_group_t* group, heap_block_info_t const* info, uint16_t at) +{ +uint16_t child_count=cluster_group_get_child_count((cluster_group_t*)group); +if(child_count==CLUSTER_GROUP_SIZE) + return false; +for(uint16_t u=child_count; u>at; u--) + group->items[u]=group->items[u-1]; +group->items[at].size=info->size; +group->items[at].offset=info->offset; +group->items[at].single=true; +cluster_group_set_child_count((cluster_group_t*)group, child_count+1); +return true; +} + +void block_map_item_group_append_items(block_map_item_group_t* group, block_map_item_t const* items, uint16_t count) +{ +uint16_t child_count=cluster_group_get_child_count((cluster_group_t*)group); +for(uint16_t u=0; uitems[child_count+u]=items[u]; +cluster_group_set_child_count((cluster_group_t*)group, child_count+count); +} + +void block_map_item_group_cleanup(block_map_item_group_t* group) +{ +uint16_t child_count=cluster_group_get_child_count((cluster_group_t*)group); +for(uint16_t pos=0; positems[pos].offset==0) + { + for(uint16_t u=pos; u+1items[u]=group->items[u+1]; + child_count--; + } + else + { + pos++; + } + } +cluster_group_set_child_count((cluster_group_t*)group, child_count); +} + +bool block_map_item_group_get_block(heap_handle_t heap, block_map_item_group_t* group, size_t min_size, heap_block_info_t* info, bool passive) +{ +uint16_t child_count=cluster_group_get_child_count((cluster_group_t*)group); +bool exists=false; +uint16_t pos=block_map_item_group_get_item_pos(group, min_size, &exists); +if(pos==child_count) + return false; +block_map_item_t* item=block_map_item_group_get_item_at(group, pos); +configASSERT(item->offset!=0); +info->size=item->size; +if(item->single) + { + info->offset=item->offset; + block_map_item_group_remove_item_at(group, pos, passive); + } +else + { + info->offset=offset_index_remove_offset_at(heap, &item->index, 0); + if(!item->offset) + block_map_item_group_remove_item_at(group, pos, passive); + } +return true; +} + +void block_map_item_group_insert_items(block_map_item_group_t* group, uint16_t pos, block_map_item_t const* items, uint16_t count) +{ +uint16_t child_count=cluster_group_get_child_count((cluster_group_t*)group); +for(uint16_t u=child_count+count-1; u>=pos+count; u--) + group->items[u]=group->items[u-count]; +for(uint16_t u=0; uitems[pos+u]=items[u]; +cluster_group_set_child_count((cluster_group_t*)group, child_count+count); +} + +bool block_map_item_group_remove_block(heap_handle_t heap, block_map_item_group_t* group, heap_block_info_t const* info) +{ +bool exists=false; +uint16_t pos=block_map_item_group_get_item_pos(group, info->size, &exists); +configASSERT(exists); +block_map_item_t* item=block_map_item_group_get_item_at(group, pos); +if(item->single) + { + configASSERT(item->offset==info->offset); + block_map_item_group_remove_item_at(group, pos, false); + } +else + { + offset_index_remove_offset(heap, &item->index, info->offset); + if(!item->offset) + block_map_item_group_remove_item_at(group, pos, false); + } +return true; +} + +size_t block_map_item_group_remove_item_at(block_map_item_group_t* group, size_t at, bool passive) +{ +uint16_t child_count=cluster_group_get_child_count((cluster_group_t*)group); +configASSERT(atitems[pos].offset; +if(passive) + { + group->items[pos].entry=0; + cluster_group_set_dirty((cluster_group_t*)group, true); + } +else + { + for(uint16_t u=pos; u+1items[u]=group->items[u+1]; + cluster_group_set_child_count((cluster_group_t*)group, child_count-1); + } +return offset; +} + +void block_map_item_group_remove_items(block_map_item_group_t* group, uint16_t pos, uint16_t count) +{ +uint16_t child_count=cluster_group_get_child_count((cluster_group_t*)group); +for(uint16_t u=pos; u+countitems[u]=group->items[u+count]; +cluster_group_set_child_count((cluster_group_t*)group, child_count-count); +} + + +//======================== +// Block-Map-Parent-Group +//======================== + +// Con-/Destructors + +block_map_parent_group_t* block_map_parent_group_create(heap_handle_t heap, uint16_t level) +{ +block_map_parent_group_t* group=(block_map_parent_group_t*)heap_alloc_internal(heap, sizeof(block_map_parent_group_t)); +if(group==NULL) + return NULL; +cluster_group_init((cluster_group_t*)group, level, 0); +group->first_size=0; +group->last_size=0; +group->item_count=0; +return group; +} + +block_map_parent_group_t* block_map_parent_group_create_with_child(heap_handle_t heap, block_map_group_t* child) +{ +block_map_parent_group_t* group=(block_map_parent_group_t*)heap_alloc_internal(heap, sizeof(block_map_parent_group_t)); +if(group==NULL) + return NULL; +uint16_t child_level=cluster_group_get_level((cluster_group_t*)child); +cluster_group_init((cluster_group_t*)group, child_level+1, 1); +group->first_size=block_map_group_get_first_size(child); +group->last_size=block_map_group_get_last_size(child); +group->item_count=cluster_group_get_item_count((cluster_group_t*)child); +group->children[0]=child; +return group; +} + + +// Access + +block_map_item_t* block_map_parent_group_get_item(block_map_parent_group_t* group, size_t size) +{ +uint16_t pos=0; +uint16_t count=block_map_parent_group_get_item_pos(group, size, &pos, true); +configASSERT(count>0); +return block_map_group_get_item(group->children[pos], size); +} + +uint16_t block_map_parent_group_get_item_pos(block_map_parent_group_t* group, size_t size, uint16_t* pos_ptr, bool must_exist) +{ +uint16_t child_count=cluster_group_get_child_count((cluster_group_t*)group); +uint16_t pos=0; +for(; poschildren[pos]); + if(sizechildren[pos]); + if(size>last_size) + continue; + *pos_ptr=pos; + return 1; + } +if(must_exist) + return 0; +if(child_count==1) + pos=0; +if(pos==0) + { + *pos_ptr=pos; + return 1; + } +if(pos==child_count) + { + pos--; + *pos_ptr=pos; + return 1; + } +pos--; +*pos_ptr=pos; +return 2; +} + + +// Modification + +bool block_map_parent_group_add_block(heap_handle_t heap, block_map_parent_group_t* group, heap_block_info_t const* info, bool again) +{ +if(!block_map_parent_group_add_block_internal(heap, group, info, again)) + return false; +group->item_count++; +block_map_parent_group_update_bounds(group); +if(cluster_group_is_dirty((cluster_group_t*)group)) + { + block_map_parent_group_combine_children(heap, group); + cluster_group_set_dirty((cluster_group_t*)group, false); + } +return true; +} + +bool block_map_parent_group_add_block_internal(heap_handle_t heap, block_map_parent_group_t* group, heap_block_info_t const* info, bool again) +{ +uint16_t pos=0; +uint16_t count=block_map_parent_group_get_item_pos(group, info->size, &pos, false); +if(!again) + { + for(uint16_t u=0; uchildren[pos+u], info, false)) + return true; + } + if(block_map_parent_group_shift_children(group, pos, count)) + { + count=block_map_parent_group_get_item_pos(group, info->size, &pos, false); + for(uint16_t u=0; uchildren[pos+u], info, false)) + return true; + } + } + } +if(!block_map_parent_group_split_child(heap, group, pos)) + return false; +count=block_map_parent_group_get_item_pos(group, info->size, &pos, false); +for(uint16_t u=0; uchildren[pos+u], info, true)) + return true; + } +return false; +} + +void block_map_parent_group_append_groups(block_map_parent_group_t* group, block_map_group_t* const* append, uint16_t count) +{ +parent_group_append_groups((parent_group_t*)group, (cluster_group_t* const*)append, count); +block_map_parent_group_update_bounds(group); +} + +bool block_map_parent_group_combine_child(heap_handle_t heap, block_map_parent_group_t* group, uint16_t pos) +{ +uint16_t count=cluster_group_get_child_count(group->children[pos]); +if(count==0) + { + parent_group_remove_group(heap, (parent_group_t*)group, pos); + return true; + } +if(pos>0) + { + uint16_t before=cluster_group_get_child_count(group->children[pos-1]); + if(count+before<=CLUSTER_GROUP_SIZE) + { + block_map_parent_group_move_children(group, pos, pos-1, count); + parent_group_remove_group(heap, (parent_group_t*)group, pos); + return true; + } + } +uint16_t child_count=cluster_group_get_child_count((cluster_group_t*)group); +if(pos+1children[pos+1]); + if(count+after<=CLUSTER_GROUP_SIZE) + { + block_map_parent_group_move_children(group, pos+1, pos, after); + parent_group_remove_group(heap, (parent_group_t*)group, pos+1); + return true; + } + } +return false; +} + +void block_map_parent_group_combine_children(heap_handle_t heap, block_map_parent_group_t* group) +{ +uint16_t child_count=cluster_group_get_child_count((cluster_group_t*)group); +for(uint16_t pos=0; pos0); +if(count==2) + pos++; +if(!block_map_group_get_block(heap, group->children[pos], min_size, info)) + return false; +if(passive) + { + cluster_group_set_dirty((cluster_group_t*)group, true); + } +else + { + block_map_parent_group_combine_child(heap, group, pos); + } +group->item_count--; +block_map_parent_group_update_bounds(group); +return true; +} + +void block_map_parent_group_insert_groups(block_map_parent_group_t* group, uint16_t at, block_map_group_t* const* insert, uint16_t count) +{ +parent_group_insert_groups((parent_group_t*)group, at, (cluster_group_t* const*)insert, count); +block_map_parent_group_update_bounds(group); +} + +void block_map_parent_group_move_children(block_map_parent_group_t* group, uint16_t from, uint16_t to, uint16_t count) +{ +uint16_t level=cluster_group_get_level((cluster_group_t*)group); +if(level>1) + { + block_map_parent_group_t* src=(block_map_parent_group_t*)group->children[from]; + block_map_parent_group_t* dst=(block_map_parent_group_t*)group->children[to]; + if(from>to) + { + block_map_parent_group_append_groups(dst, src->children, count); + block_map_parent_group_remove_groups(src, 0, count); + } + else + { + uint16_t src_count=cluster_group_get_child_count((cluster_group_t*)src); + block_map_parent_group_insert_groups(dst, 0, &src->children[src_count-count], count); + block_map_parent_group_remove_groups(src, src_count-count, count); + } + } +else + { + block_map_item_group_t* src=(block_map_item_group_t*)group->children[from]; + block_map_item_group_t* dst=(block_map_item_group_t*)group->children[to]; + if(from>to) + { + block_map_item_group_append_items(dst, src->items, count); + block_map_item_group_remove_items(src, 0, count); + } + else + { + uint16_t src_count=cluster_group_get_child_count((cluster_group_t*)src); + block_map_item_group_insert_items(dst, 0, &src->items[src_count-count], count); + block_map_item_group_remove_items(src, src_count-count, count); + } + } +} + +void block_map_parent_group_move_empty_slot(block_map_parent_group_t* group, uint16_t from, uint16_t to) +{ +if(fromto; u--) + block_map_parent_group_move_children(group, u-1, u, 1); + } +} + +bool block_map_parent_group_remove_block(heap_handle_t heap, block_map_parent_group_t* group, heap_block_info_t const* info) +{ +uint16_t pos=0; +uint16_t count=block_map_parent_group_get_item_pos(group, info->size, &pos, true); +configASSERT(count==1); +if(block_map_group_remove_block(heap, group->children[pos], info)) + { + group->item_count--; + block_map_parent_group_combine_child(heap, group, pos); + block_map_parent_group_update_bounds(group); + return true; + } +return false; +} + +void block_map_parent_group_remove_groups(block_map_parent_group_t* group, uint16_t at, uint16_t count) +{ +parent_group_remove_groups((parent_group_t*)group, at, count); +block_map_parent_group_update_bounds(group); +} + +bool block_map_parent_group_shift_children(block_map_parent_group_t* group, uint16_t at, uint16_t count) +{ +int16_t space=parent_group_get_nearest_space((parent_group_t*)group, at); +if(space<0) + return false; +if(count>1&&space>at) + at++; +block_map_parent_group_move_empty_slot(group, space, at); +return true; +} + +bool block_map_parent_group_split_child(heap_handle_t heap, block_map_parent_group_t* group, uint16_t at) +{ +uint16_t child_count=cluster_group_get_child_count((cluster_group_t*)group); +if(child_count==CLUSTER_GROUP_SIZE) + return false; +block_map_group_t* child=NULL; +uint16_t level=cluster_group_get_level((cluster_group_t*)group); +if(level>1) + { + child=(block_map_group_t*)block_map_parent_group_create(heap, level-1); + } +else + { + child=(block_map_group_t*)block_map_item_group_create(heap); + } +if(!child) + return false; +for(uint16_t u=child_count; u>at+1; u--) + group->children[u]=group->children[u-1]; +group->children[at+1]=child; +cluster_group_set_child_count((cluster_group_t*)group, child_count+1); +block_map_parent_group_move_children(group, at, at+1, 1); +return true; +} + +void block_map_parent_group_update_bounds(block_map_parent_group_t* group) +{ +uint16_t child_count=cluster_group_get_child_count((cluster_group_t*)group); +if(child_count==0) + { + group->first_size=0; + group->last_size=0; + return; + } +for(uint16_t pos=0; posfirst_size=block_map_group_get_first_size(group->children[pos]); + if(group->first_size!=0) + break; + } +for(uint16_t pos=child_count; pos>0; pos--) + { + group->last_size=block_map_group_get_last_size(group->children[pos-1]); + if(group->last_size!=0) + break; + } +} + + +//=========== +// Block-Map +//=========== + +// Modification + +bool block_map_add_block(heap_handle_t heap, block_map_t* map, heap_block_info_t const* info) +{ +configASSERT(info->offset>=(size_t)heap+sizeof(heap_t)); +configASSERT(info->offset<(size_t)heap+heap->used); +if(!map->root) + { + map->root=(block_map_group_t*)block_map_item_group_create(heap); + if(!map->root) + return false; + } +if(block_map_group_add_block(heap, map->root, info, false)) + { + block_map_drop_root(heap, map); + return true; + } +if(!block_map_lift_root(heap, map)) + return false; +if(!block_map_group_add_block(heap, map->root, info, true)) + return false; +block_map_drop_root(heap, map); +return true; +} + +bool block_map_drop_root(heap_handle_t heap, block_map_t* map) +{ +block_map_group_t* root=map->root; +if(cluster_group_is_locked((cluster_group_t*)root)) + return false; +uint16_t child_count=cluster_group_get_child_count((cluster_group_t*)root); +uint16_t level=cluster_group_get_level((cluster_group_t*)root); +if(level==0) + return false; +if(child_count>1) + return false; +block_map_parent_group_t* parent_group=(block_map_parent_group_t*)root; +map->root=parent_group->children[0]; +heap_free_to_cache(heap, root); +return true; +} + +bool block_map_get_block(heap_handle_t heap, block_map_t* map, size_t min_size, heap_block_info_t* info) +{ +if(!map->root) + return false; +if(block_map_group_get_block(heap, map->root, min_size, info)) + { + block_map_drop_root(heap, map); + return true; + } +return false; +} + +bool block_map_lift_root(heap_handle_t heap, block_map_t* map) +{ +block_map_parent_group_t* root=block_map_parent_group_create_with_child(heap, map->root); +if(!root) + return false; +map->root=(block_map_group_t*)root; +return true; +} + +void block_map_remove_block(heap_handle_t heap, block_map_t* map, heap_block_info_t const* info) +{ +if(block_map_group_remove_block(heap, map->root, info)) + block_map_drop_root(heap, map); +} + + +//==================== +// Offset-Index-Group +//==================== + +// Access + +size_t offset_index_group_get_first_offset(offset_index_group_t* group) +{ +if(cluster_group_get_level(group)==0) + return offset_index_item_group_get_first_offset((offset_index_item_group_t*)group); +return ((offset_index_parent_group_t*)group)->first_offset; +} + +size_t offset_index_group_get_last_offset(offset_index_group_t* group) +{ +if(cluster_group_get_level(group)==0) + return offset_index_item_group_get_last_offset((offset_index_item_group_t*)group); +return ((offset_index_parent_group_t*)group)->last_offset; +} + + +// Modification + +bool offset_index_group_add_offset(heap_handle_t heap, offset_index_group_t* group, size_t offset, bool again) +{ +cluster_group_set_locked((cluster_group_t*)group, true); +bool added=false; +if(cluster_group_get_level(group)==0) + { + added=offset_index_item_group_add_offset((offset_index_item_group_t*)group, offset); + } +else + { + added=offset_index_parent_group_add_offset(heap, (offset_index_parent_group_t*)group, offset, again); + } +cluster_group_set_locked((cluster_group_t*)group, false); +return added; +} + +void offset_index_group_remove_offset(heap_handle_t heap, offset_index_group_t* group, size_t offset) +{ +if(cluster_group_get_level(group)==0) + { + offset_index_item_group_remove_offset((offset_index_item_group_t*)group, offset); + } +else + { + offset_index_parent_group_remove_offset(heap, (offset_index_parent_group_t*)group, offset); + } +} + +size_t offset_index_group_remove_offset_at(heap_handle_t heap, offset_index_group_t* group, size_t at) +{ +bool passive=cluster_group_is_locked((cluster_group_t*)group); +if(cluster_group_get_level(group)==0) + return offset_index_item_group_remove_offset_at((offset_index_item_group_t*)group, at, passive); +return offset_index_parent_group_remove_offset_at(heap, (offset_index_parent_group_t*)group, at, passive); +} + + +//========================= +// Offset-Index-Item-Group +//========================= + +// Con-/Destructors + +offset_index_item_group_t* offset_index_item_group_create(heap_handle_t heap) +{ +offset_index_item_group_t* group=(offset_index_item_group_t*)heap_alloc_internal(heap, sizeof(offset_index_item_group_t)); +if(group==NULL) + return NULL; +cluster_group_init((cluster_group_t*)group, 0, 0); +return group; +} + + +// Access + +size_t offset_index_item_group_get_first_offset(offset_index_item_group_t* group) +{ +uint16_t child_count=cluster_group_get_child_count((cluster_group_t*)group); +if(child_count==0) + return 0; +return group->items[0]; +} + +uint16_t offset_index_item_group_get_item_pos(offset_index_item_group_t* group, size_t offset, bool* exists_ptr) +{ +uint16_t child_count=cluster_group_get_child_count((cluster_group_t*)group); +for(uint16_t pos=0; positems[pos]; + if(item==offset) + { + *exists_ptr=true; + return pos; + } + if(item>offset) + return pos; + } +return child_count; +} + +size_t offset_index_item_group_get_last_offset(offset_index_item_group_t* group) +{ +uint16_t child_count=cluster_group_get_child_count((cluster_group_t*)group); +if(child_count==0) + return 0; +return group->items[child_count-1]; +} + + +// Modification + +bool offset_index_item_group_add_offset(offset_index_item_group_t* group, size_t offset) +{ +bool exists=false; +uint16_t pos=offset_index_item_group_get_item_pos(group, offset, &exists); +configASSERT(!exists); +uint16_t child_count=cluster_group_get_child_count((cluster_group_t*)group); +if(child_count==CLUSTER_GROUP_SIZE) + return false; +for(uint16_t u=child_count; u>pos; u--) + group->items[u]=group->items[u-1]; +group->items[pos]=offset; +cluster_group_set_child_count((cluster_group_t*)group, child_count+1); +return true; +} + +void offset_index_item_group_append_items(offset_index_item_group_t* group, size_t const* append, uint16_t count) +{ +uint16_t child_count=cluster_group_get_child_count((cluster_group_t*)group); +configASSERT(child_count+count<=CLUSTER_GROUP_SIZE); +for(uint16_t u=0; uitems[child_count+u]=append[u]; +cluster_group_set_child_count((cluster_group_t*)group, child_count+count); +} + +void offset_index_item_group_insert_items(offset_index_item_group_t* group, uint16_t at, size_t const* insert, uint16_t count) +{ +uint16_t child_count=cluster_group_get_child_count((cluster_group_t*)group); +for(uint16_t u=child_count+count-1; u>=at+count; u--) + group->items[u]=group->items[u-count]; +for(uint16_t u=0; uitems[at+u]=insert[u]; +cluster_group_set_child_count((cluster_group_t*)group, child_count+count); +} + +size_t offset_index_item_group_remove_item(offset_index_item_group_t* group, uint16_t at) +{ +uint16_t child_count=cluster_group_get_child_count((cluster_group_t*)group); +size_t offset=group->items[at]; +for(uint16_t u=at; u+1items[u]=group->items[u+1]; +cluster_group_set_child_count((cluster_group_t*)group, child_count-1); +return offset; +} + +void offset_index_item_group_remove_offset(offset_index_item_group_t* group, size_t offset) +{ +bool exists=false; +uint16_t pos=offset_index_item_group_get_item_pos(group, offset, &exists); +configASSERT(exists); +offset_index_item_group_remove_item(group, pos); +} + +size_t offset_index_item_group_remove_offset_at(offset_index_item_group_t* group, size_t at, bool passive) +{ +configASSERT(!passive); +uint16_t child_count=cluster_group_get_child_count((cluster_group_t*)group); +configASSERT(atitems[u]=group->items[u+count]; +cluster_group_set_child_count((cluster_group_t*)group, child_count-count); +} + + +//=========================== +// Offset-Index-Parent-group +//=========================== + +// Con-/Destructors + +offset_index_parent_group_t* offset_index_parent_group_create(heap_handle_t heap, uint16_t level) +{ +offset_index_parent_group_t* group=(offset_index_parent_group_t*)heap_alloc_internal(heap, sizeof(offset_index_parent_group_t)); +if(group==NULL) + return NULL; +cluster_group_init((cluster_group_t*)group, level, 0); +group->first_offset=0; +group->last_offset=0; +group->item_count=0; +return group; +} + +offset_index_parent_group_t* offset_index_parent_group_create_with_child(heap_handle_t heap, offset_index_group_t* child) +{ +offset_index_parent_group_t* group=(offset_index_parent_group_t*)heap_alloc_internal(heap, sizeof(offset_index_parent_group_t)); +if(group==NULL) + return NULL; +uint16_t child_level=cluster_group_get_level(child); +cluster_group_init((cluster_group_t*)group, child_level+1, 1); +group->first_offset=offset_index_group_get_first_offset(child); +group->last_offset=offset_index_group_get_last_offset(child); +group->item_count=cluster_group_get_item_count((cluster_group_t*)child); +group->children[0]=child; +return group; +} + + +// Access + +uint16_t offset_index_parent_group_get_item_pos(offset_index_parent_group_t* group, size_t offset, uint16_t* pos_ptr, bool must_exist) +{ +uint16_t child_count=cluster_group_get_child_count((cluster_group_t*)group); +uint16_t pos=0; +for(; poschildren[pos]); + if(offsetchildren[pos]); + if(offset>last_offset) + continue; + *pos_ptr=pos; + return 1; + } +if(must_exist) + return 0; +if(pos==0) + { + *pos_ptr=pos; + return 1; + } +if(pos==child_count) + { + *pos_ptr=pos-1; + return 1; + } +*pos_ptr=pos-1; +return 2; +} + + +// Modification + +bool offset_index_parent_group_add_offset(heap_handle_t heap, offset_index_parent_group_t* group, size_t offset, bool again) +{ +if(!offset_index_parent_group_add_offset_internal(heap, group, offset, again)) + return false; +group->item_count++; +offset_index_parent_group_update_bounds(group); +return true; +} + +bool offset_index_parent_group_add_offset_internal(heap_handle_t heap, offset_index_parent_group_t* group, size_t offset, bool again) +{ +uint16_t child_count=cluster_group_get_child_count((cluster_group_t*)group); +if(!child_count) + return false; +uint16_t pos=0; +uint16_t count=offset_index_parent_group_get_item_pos(group, offset, &pos, false); +if(!again) + { + for(uint16_t u=0; uchildren[pos+u], offset, false)) + return true; + } + if(offset_index_parent_group_shift_children(group, pos, count)) + { + count=offset_index_parent_group_get_item_pos(group, offset, &pos, false); + for(uint16_t u=0; uchildren[pos+u], offset, false)) + return true; + } + } + } +if(!offset_index_parent_group_split_child(heap, group, pos)) + return false; +count=offset_index_parent_group_get_item_pos(group, offset, &pos, false); +for(uint16_t u=0; uchildren[pos+u], offset, true)) + return true; + } +return false; +} + +void offset_index_parent_group_append_groups(offset_index_parent_group_t* group, offset_index_group_t* const* append, uint16_t count) +{ +parent_group_append_groups((parent_group_t*)group, (cluster_group_t* const*)append, count); +offset_index_parent_group_update_bounds(group); +} + +bool offset_index_parent_group_combine_child(heap_handle_t heap, offset_index_parent_group_t* group, uint16_t at) +{ +uint16_t count=cluster_group_get_child_count((cluster_group_t*)group->children[at]); +if(count==0) + { + parent_group_remove_group(heap, (parent_group_t*)group, at); + return true; + } +if(at>0) + { + uint16_t before=cluster_group_get_child_count((cluster_group_t*)group->children[at-1]); + if(count+before<=CLUSTER_GROUP_SIZE) + { + offset_index_parent_group_move_children(group, at, at-1, count); + parent_group_remove_group(heap, (parent_group_t*)group, at); + return true; + } + } +uint16_t child_count=cluster_group_get_child_count((cluster_group_t*)group); +if(at+1children[at+1]); + if(count+after<=CLUSTER_GROUP_SIZE) + { + offset_index_parent_group_move_children(group, at+1, at, after); + parent_group_remove_group(heap, (parent_group_t*)group, at+1); + return true; + } + } +return false; +} + +void offset_index_parent_group_combine_children(heap_handle_t heap, offset_index_parent_group_t* group) +{ +uint16_t child_count=cluster_group_get_child_count((cluster_group_t*)group); +for(uint16_t pos=0; pos1) + { + offset_index_parent_group_t* src=(offset_index_parent_group_t*)group->children[from]; + offset_index_parent_group_t* dst=(offset_index_parent_group_t*)group->children[to]; + if(from>to) + { + offset_index_parent_group_append_groups(dst, src->children, count); + offset_index_parent_group_remove_groups(src, 0, count); + } + else + { + uint16_t src_count=cluster_group_get_child_count((cluster_group_t*)src); + offset_index_parent_group_insert_groups(dst, 0, &src->children[src_count-count], count); + offset_index_parent_group_remove_groups(src, src_count-count, count); + } + } +else + { + offset_index_item_group_t* src=(offset_index_item_group_t*)group->children[from]; + offset_index_item_group_t* dst=(offset_index_item_group_t*)group->children[to]; + if(from>to) + { + offset_index_item_group_append_items(dst, src->items, count); + offset_index_item_group_remove_items(src, 0, count); + } + else + { + uint16_t src_count=cluster_group_get_child_count((cluster_group_t*)src); + offset_index_item_group_insert_items(dst, 0, &src->items[src_count-count], count); + offset_index_item_group_remove_items(src, src_count-count, count); + } + } +} + +void offset_index_parent_group_move_empty_slot(offset_index_parent_group_t* group, uint16_t from, uint16_t to) +{ +if(fromto; u--) + offset_index_parent_group_move_children(group, u-1, u, 1); + } +} + +void offset_index_parent_group_remove_groups(offset_index_parent_group_t* group, uint16_t at, uint16_t count) +{ +parent_group_remove_groups((parent_group_t*)group, at, count); +offset_index_parent_group_update_bounds(group); +} + +void offset_index_parent_group_remove_offset(heap_handle_t heap, offset_index_parent_group_t* group, size_t offset) +{ +uint16_t pos=0; +uint16_t count=offset_index_parent_group_get_item_pos(group, offset, &pos, true); +configASSERT(count==1); +offset_index_group_remove_offset(heap, group->children[pos], offset); +offset_index_parent_group_combine_child(heap, group, pos); +group->item_count--; +offset_index_parent_group_update_bounds(group); +} + +size_t offset_index_parent_group_remove_offset_at(heap_handle_t heap, offset_index_parent_group_t* group, size_t at, bool passive) +{ +uint16_t pos=parent_group_get_group((parent_group_t*)group, &at); +configASSERT(poschildren[pos], at); +if(passive) + { + cluster_group_set_dirty((cluster_group_t*)group, true); + } +else + { + if(cluster_group_is_dirty((cluster_group_t*)group)) + { + offset_index_parent_group_combine_children(heap, group); + cluster_group_set_dirty((cluster_group_t*)group, false); + } + else + { + offset_index_parent_group_combine_child(heap, group, pos); + } + } +group->item_count--; +offset_index_parent_group_update_bounds(group); +return offset; +} + +bool offset_index_parent_group_shift_children(offset_index_parent_group_t* group, uint16_t at, uint16_t count) +{ +int16_t space=parent_group_get_nearest_space((parent_group_t*)group, at); +if(space<0) + return false; +if(count>1&&space>at) + at++; +offset_index_parent_group_move_empty_slot(group, space, at); +return true; +} + +bool offset_index_parent_group_split_child(heap_handle_t heap, offset_index_parent_group_t* group, uint16_t at) +{ +uint16_t child_count=cluster_group_get_child_count((cluster_group_t*)group); +if(child_count==CLUSTER_GROUP_SIZE) + return false; +offset_index_group_t* child=NULL; +uint16_t level=cluster_group_get_level((cluster_group_t*)group); +if(level>1) + { + child=(offset_index_group_t*)offset_index_parent_group_create(heap, level-1); + } +else + { + child=(offset_index_group_t*)offset_index_item_group_create(heap); + } +if(!child) + return false; +for(uint16_t u=child_count; u>at+1; u--) + group->children[u]=group->children[u-1]; +group->children[at+1]=child; +cluster_group_set_child_count((cluster_group_t*)group, child_count+1); +offset_index_parent_group_move_children(group, at, at+1, 1); +return true; +} + +void offset_index_parent_group_update_bounds(offset_index_parent_group_t* group) +{ +uint16_t child_count=cluster_group_get_child_count((cluster_group_t*)group); +if(child_count==0) + { + group->first_offset=0; + group->last_offset=0; + return; + } +for(uint16_t pos=0; posfirst_offset=offset_index_group_get_first_offset(group->children[pos]); + if(group->first_offset!=0) + break; + } +for(uint16_t pos=child_count; pos>0; pos--) + { + group->last_offset=offset_index_group_get_last_offset(group->children[pos-1]); + if(group->last_offset!=0) + break; + } +} + + +//============== +// Offset-Index +//============== + +// Con-/Destructors + +void offset_index_init(offset_index_t* index) +{ +index->root=NULL; +} + + +// Modification + +bool offset_index_add_offset(heap_handle_t heap, offset_index_t* index, size_t offset) +{ +if(!index->root) + { + index->root=(offset_index_group_t*)offset_index_item_group_create(heap); + if(!index->root) + return false; + } +if(offset_index_group_add_offset(heap, index->root, offset, false)) + return true; +if(!offset_index_lift_root(heap, index)) + return false; +return offset_index_group_add_offset(heap, index->root, offset, true); +} + +void offset_index_drop_root(heap_handle_t heap, offset_index_t* index) +{ +offset_index_group_t* root=index->root; +if(cluster_group_is_locked((cluster_group_t*)root)) + return; +uint16_t child_count=cluster_group_get_child_count((cluster_group_t*)root); +uint16_t level=cluster_group_get_level((cluster_group_t*)root); +if(level==0) + { + if(child_count==0) + { + index->root=NULL; + heap_free_to_cache(heap, root); + } + return; + } +if(child_count>1) + return; +offset_index_parent_group_t* parent_group=(offset_index_parent_group_t*)root; +index->root=parent_group->children[0]; +heap_free_to_cache(heap, root); +} + +bool offset_index_lift_root(heap_handle_t heap, offset_index_t* index) +{ +offset_index_parent_group_t* root=offset_index_parent_group_create_with_child(heap, index->root); +if(!root) + return false; +index->root=(offset_index_group_t*)root; +return true; +} + +void offset_index_remove_offset(heap_handle_t heap, offset_index_t* index, size_t offset) +{ +offset_index_group_remove_offset(heap, index->root, offset); +offset_index_drop_root(heap, index); +} + +size_t offset_index_remove_offset_at(heap_handle_t heap, offset_index_t* index, size_t at) +{ +configASSERT(index->root); +size_t offset=offset_index_group_remove_offset_at(heap, index->root, at); +offset_index_drop_root(heap, index); +return offset; +} + + +//========== +// Portable +//========== + +void* pvPortCalloc(size_t xNum, size_t xSize) +{ +void* buf=NULL; +if(MULTIPLY_WILL_OVERFLOW(xNum, xSize)==0) + { + buf=pvPortMalloc(xNum*xSize); + if(buf!=NULL) + memset(buf, 0, xNum*xSize); + } +return buf; +} + +void* pvPortMalloc(size_t xWantedSize) +{ +void* buf=NULL; +bool locked=heap_lock(); +if(locked) + { + heap_handle_t heap=first_heap; + while(heap) + { + buf=heap_alloc(heap, xWantedSize); + if(buf!=NULL) + break; + heap=(heap_handle_t)heap->next_heap; + } + } +heap_unlock(locked); +if(buf!=NULL) + xSuccessfulAllocations++; +return buf; +} + +void vPortDefineHeapRegions(HeapRegion_t const* pxHeapRegions)PRIVILEGED_FUNCTION +{ +configASSERT(first_heap==NULL); +configASSERT(pxHeapRegions!=NULL); +HeapRegion_t const* region=pxHeapRegions; +while(region->xSizeInBytes>0) + { + size_t offset=(size_t)region->pucStartAddress; + size_t size=region->xSizeInBytes; + heap_handle_t heap=heap_create(last_heap, offset, size); + configASSERT(heap!=NULL); + if(first_heap==NULL) + first_heap=heap; + last_heap=heap; + region++; + } +#if(configUSE_HEAP_IN_ISR==0) +heap_mutex=xSemaphoreCreateMutexStatic(&heap_mutex_buf); +#endif +} + +void vPortFree(void* pv) +{ +if(pv==NULL) + return; +size_t offset=(size_t)pv; +bool locked=heap_lock(); +if(locked) + { + heap_handle_t heap=first_heap; + while(heap) + { + size_t heap_start=(size_t)heap; + size_t heap_end=heap_start+heap->size; + if(offset>heap_start&&offsetnext_heap; + } + } +heap_unlock(locked); +} + +void vPortGetHeapStats(HeapStats_t* pxHeapStats) +{ +configASSERT(pxHeapStats!=NULL); +memset(pxHeapStats, 0, sizeof(HeapStats_t)); +bool locked=heap_lock(); +if(locked) + { + size_t largest=0; + heap_handle_t heap=first_heap; + while(heap) + { + largest=max(largest, heap_get_largest_free_block(heap)); + heap=(heap_handle_t)heap->next_heap; + } + pxHeapStats->xAvailableHeapSpaceInBytes=xFreeBytes; + pxHeapStats->xMinimumEverFreeBytesRemaining=xMinimumFreeBytes; + pxHeapStats->xNumberOfFreeBlocks=xFreeBlocks; + pxHeapStats->xNumberOfSuccessfulAllocations=xSuccessfulAllocations; + pxHeapStats->xNumberOfSuccessfulFrees=xSuccessfulDeletions; + pxHeapStats->xSizeOfLargestFreeBlockInBytes=largest; + pxHeapStats->xSizeOfSmallestFreeBlockInBytes=BLOCK_SIZE_MIN; + } +heap_unlock(locked); +} + +void vPortHeapResetState(void) +{ +#if(configUSE_HEAP_IN_ISR==0) +vSemaphoreDelete(heap_mutex); +heap_mutex=NULL; +#endif +first_heap=NULL; +last_heap=NULL; +xFreeBlocks=0; +xFreeBytes=0; +xMinimumFreeBytes=0; +xSuccessfulAllocations=0; +xSuccessfulDeletions=0; +} + +size_t xPortGetFreeHeapSize(void) +{ +return xFreeBytes; +} + +size_t xPortGetMinimumEverFreeHeapSize(void) +{ +return xMinimumFreeBytes; +} diff --git a/portable/MemMang/heap_6.h b/portable/MemMang/heap_6.h new file mode 100644 index 000000000..b59b777f8 --- /dev/null +++ b/portable/MemMang/heap_6.h @@ -0,0 +1,556 @@ +//========== +// heap_6.h +//========== + +// Memory-manager for real-time C++ applications. +// Allocations and deletions are done in constant low time. + +// Copyright 2024, Sven Bieg (svenbieg@web.de) +// http://github.com/svenbieg/Heap + + +#ifndef _HEAP_H +#define _HEAP_H + + +//======= +// Using +//======= + +#include +#include +#include +#include + +#define MPU_WRAPPERS_INCLUDED_FROM_API_FILE + +#include "FreeRTOS.h" +#include "task.h" + +#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE + + +//========== +// Settings +//========== + +#define configUSE_HEAP_IN_ISR 1 + +#define CLUSTER_GROUP_SIZE 10 + +#if(configSUPPORT_DYNAMIC_ALLOCATION==0) +#error This file must not be used if configSUPPORT_DYNAMIC_ALLOCATION is 0 +#endif + +#if(configHEAP_CLEAR_MEMORY_ON_FREE==1) +#error Not supported with heap_6 +#endif + +#if(configENABLE_HEAP_PROTECTOR==1) +#error Not supported with heap_6 +#endif + + +//======== +// Macros +//======== + +// These macros are from heap_5.c + +/* Check if multiplying a and b will result in overflow. */ +#define MULTIPLY_WILL_OVERFLOW(a, b) (((a)>0)&&((b)>(SIZE_MAX/(a)))) + + +//=========== +// Alignment +//=========== + +#define SIZE_BITS (sizeof(size_t)*8) +#define SIZE_BYTES sizeof(size_t) + +#define BLOCK_SIZE_MIN (4*SIZE_BYTES) + +static inline size_t align_down(size_t value, size_t align) +{ +return value&~(align-1); +} + +static inline size_t align_up(size_t value, size_t align) +{ +return value+(align-value%align)%align; +} + + +//====== +// Heap +//====== + +typedef struct _heap_t +{ +size_t free; +size_t used; +size_t size; +size_t free_block; +size_t next_heap; +size_t map_free; +}heap_t; + +typedef heap_t* heap_handle_t; + + +// Creation +heap_handle_t heap_create(heap_handle_t prev_heap, size_t offset, size_t size); + + +// Allocation +void* heap_alloc(heap_handle_t heap, size_t size); +void heap_free(heap_handle_t heap, void* buffer); + + +// Internal Allocation +void* heap_alloc_from_foot(heap_handle_t heap, size_t size); +void* heap_alloc_from_map(heap_handle_t heap, size_t size); +void* heap_alloc_internal(heap_handle_t heap, size_t size); +void heap_free_cache(heap_handle_t heap); +void heap_free_to_cache(heap_handle_t heap, void* buf); +void heap_free_to_map(heap_handle_t heap, void* buf); + + +// Statistic +size_t heap_get_largest_free_block(heap_handle_t heap); + + +//============ +// Heap-Block +//============ + +typedef struct heap_block_info_t +{ +size_t offset; +union + { + struct + { + size_t size: SIZE_BITS-1; + size_t free: 1; + }; + size_t header; + }; +}heap_block_info_t; + +typedef struct +{ +heap_block_info_t previous; +heap_block_info_t current; +heap_block_info_t next; +}heap_block_chain_t; + + +// Con-/Destructors +void* heap_block_init(heap_handle_t heap, heap_block_info_t const* info); + + +// Common +static inline size_t heap_block_calc_size(size_t size) +{ +return align_up(size, sizeof(size_t))+2*sizeof(size_t); +} + +static inline size_t heap_block_get_offset(void* ptr) +{ +return (size_t)ptr-sizeof(size_t); +} + +static inline void* heap_block_get_pointer(size_t offset) +{ +return (void*)(offset+sizeof(size_t)); +} + + +// Access +void heap_block_get_chain(heap_handle_t heap, void* ptr, heap_block_chain_t* info); +void heap_block_get_info(heap_handle_t heap, void* ptr, heap_block_info_t* info); + + +//=============== +// Cluster-Group +//=============== + +typedef struct +{ +union + { + struct + { + uint32_t dirty: 1; + uint32_t locked: 1; + uint32_t level: 14; + uint32_t child_count: 16; + }; + uint32_t value; + }; +}cluster_group_t; + + +// Con-/Destructors +static inline void cluster_group_init(cluster_group_t* group, uint16_t level, uint16_t child_count) +{ +cluster_group_t set={ 0 }; +set.level=level; +set.child_count=child_count; +group->value=set.value; +} + + +// Access +static inline uint16_t cluster_group_get_child_count(cluster_group_t* group) +{ +cluster_group_t get; +get.value=group->value; +return (uint16_t)get.child_count; +} + +size_t cluster_group_get_item_count(cluster_group_t* group); + +static inline uint16_t cluster_group_get_level(cluster_group_t* group) +{ +cluster_group_t get; +get.value=group->value; +return (uint16_t)get.level; +} + +static inline bool cluster_group_is_dirty(cluster_group_t* group) +{ +cluster_group_t get; +get.value=group->value; +return (uint16_t)get.dirty; +} + +static inline bool cluster_group_is_locked(cluster_group_t* group) +{ +cluster_group_t get; +get.value=group->value; +return (uint16_t)get.locked; +} + + +// Modification +static inline void cluster_group_set_child_count(cluster_group_t* group, uint16_t child_count) +{ +cluster_group_t set; +set.value=group->value; +set.child_count=child_count; +group->value=set.value; +} + +static inline void cluster_group_set_dirty(cluster_group_t* group, bool dirty) +{ +cluster_group_t set; +set.value=group->value; +set.dirty=dirty; +group->value=set.value; +} + +static inline void cluster_group_set_locked(cluster_group_t* group, bool lock) +{ +cluster_group_t set; +set.value=group->value; +configASSERT((bool)set.locked!=lock); +set.locked=lock; +group->value=set.value; +} + + +//============== +// Parent-Group +//============== + +typedef struct +{ +cluster_group_t header; +size_t item_count; +size_t first; +size_t last; +cluster_group_t* children[CLUSTER_GROUP_SIZE]; +}parent_group_t; + + +// Access +uint16_t parent_group_get_group(parent_group_t* group, size_t* at); +int16_t parent_group_get_nearest_space(parent_group_t* group, int16_t pos); + + +// Modification +void parent_group_append_groups(parent_group_t* group, cluster_group_t* const* append, uint16_t count); +void parent_group_insert_groups(parent_group_t* group, uint16_t at, cluster_group_t* const* insert, uint16_t count); +void parent_group_remove_group(heap_handle_t heap, parent_group_t* group, uint16_t at); +void parent_group_remove_groups(parent_group_t* group, uint16_t at, uint16_t count); + + +//================ +// Block-Map-Item +//================ + +typedef struct +{ +size_t size; +union + { + struct + { + size_t offset: SIZE_BITS-1; + size_t single: 1; + }; + size_t entry; + size_t index; + }; +}block_map_item_t; + + +//================= +// Block-Map-Group +//================= + +typedef cluster_group_t block_map_group_t; + +// Access +size_t block_map_group_get_first_size(block_map_group_t* group); +block_map_item_t* block_map_group_get_item(block_map_group_t* group, size_t size); +size_t block_map_group_get_last_size(block_map_group_t* group); + +// Modification +bool block_map_group_add_block(heap_handle_t heap, block_map_group_t* group, heap_block_info_t const* info, bool again); +bool block_map_group_get_block(heap_handle_t heap, block_map_group_t* group, size_t min_size, heap_block_info_t* info); +bool block_map_group_remove_block(heap_handle_t heap, block_map_group_t* group, heap_block_info_t const* info); + + +//====================== +// Block-Map-Item-Group +//====================== + +typedef struct +{ +cluster_group_t header; +block_map_item_t items[CLUSTER_GROUP_SIZE]; +}block_map_item_group_t; + +// Con-/Destructors +block_map_item_group_t* block_map_item_group_create(heap_handle_t heap); + +// Access +size_t block_map_item_group_get_first_size(block_map_item_group_t* group); +block_map_item_t* block_map_item_group_get_item(block_map_item_group_t* group, size_t size); +block_map_item_t* block_map_item_group_get_item_at(block_map_item_group_t* group, uint16_t at); +uint16_t block_map_item_group_get_item_pos(block_map_item_group_t* group, size_t size, bool* exists_ptr); +size_t block_map_item_group_get_last_size(block_map_item_group_t* group); + +// Modification +bool block_map_item_group_add_block(heap_handle_t heap, block_map_item_group_t* group, heap_block_info_t const* info); +bool block_map_item_group_add_item(block_map_item_group_t* group, heap_block_info_t const* info, uint16_t pos); +void block_map_item_group_append_items(block_map_item_group_t* group, block_map_item_t const* items, uint16_t count); +void block_map_item_group_cleanup(block_map_item_group_t* group); +bool block_map_item_group_get_block(heap_handle_t heap, block_map_item_group_t* group, size_t min_size, heap_block_info_t* info, bool passive); +void block_map_item_group_insert_items(block_map_item_group_t* group, uint16_t pos, block_map_item_t const* items, uint16_t count); +bool block_map_item_group_remove_block(heap_handle_t heap, block_map_item_group_t* group, heap_block_info_t const* info); +size_t block_map_item_group_remove_item_at(block_map_item_group_t* group, size_t at, bool passive); +void block_map_item_group_remove_items(block_map_item_group_t* group, uint16_t at, uint16_t count); + + +//======================== +// Block-Map-Parent-Group +//======================== + +typedef struct +{ +cluster_group_t header; +size_t item_count; +size_t first_size; +size_t last_size; +block_map_group_t* children[CLUSTER_GROUP_SIZE]; +}block_map_parent_group_t; + +// Con-/Destructors +block_map_parent_group_t* block_map_parent_group_create(heap_handle_t heap, uint16_t level); +block_map_parent_group_t* block_map_parent_group_create_with_child(heap_handle_t heap, block_map_group_t* child); + +// Access +block_map_item_t* block_map_parent_group_get_item(block_map_parent_group_t* group, size_t size); +uint16_t block_map_parent_group_get_item_pos(block_map_parent_group_t* group, size_t size, uint16_t* pos_ptr, bool must_exist); + +// Modification +bool block_map_parent_group_add_block(heap_handle_t heap, block_map_parent_group_t* group, heap_block_info_t const* info, bool again); +bool block_map_parent_group_add_block_internal(heap_handle_t heap, block_map_parent_group_t* group, heap_block_info_t const* info, bool again); +void block_map_parent_group_append_groups(block_map_parent_group_t* group, block_map_group_t* const* append, uint16_t count); +bool block_map_parent_group_combine_child(heap_handle_t heap, block_map_parent_group_t* group, uint16_t pos); +void block_map_parent_group_combine_children(heap_handle_t heap, block_map_parent_group_t* group); +bool block_map_parent_group_get_block(heap_handle_t heap, block_map_parent_group_t* group, size_t min_size, heap_block_info_t* info, bool passive); +void block_map_parent_group_insert_groups(block_map_parent_group_t* group, uint16_t at, block_map_group_t* const* insert, uint16_t count); +void block_map_parent_group_move_children(block_map_parent_group_t* group, uint16_t from, uint16_t to, uint16_t count); +void block_map_parent_group_move_empty_slot(block_map_parent_group_t* group, uint16_t from, uint16_t to); +bool block_map_parent_group_remove_block(heap_handle_t heap, block_map_parent_group_t* group, heap_block_info_t const* info); +void block_map_parent_group_remove_groups(block_map_parent_group_t* group, uint16_t at, uint16_t count); +bool block_map_parent_group_shift_children(block_map_parent_group_t* group, uint16_t at, uint16_t count); +bool block_map_parent_group_split_child(heap_handle_t heap, block_map_parent_group_t* group, uint16_t at); +void block_map_parent_group_update_bounds(block_map_parent_group_t* group); + + +//=========== +// Block-Map +//=========== + +typedef struct +{ +block_map_group_t* root; +}block_map_t; + +// Con-/Destructors +static inline void block_map_init(block_map_t* map) +{ +map->root=NULL; +} + +// Access +static inline size_t block_map_get_item_count(block_map_t* map) +{ +if(map==NULL) + return 0; +return cluster_group_get_item_count((cluster_group_t*)map->root); +} + +static inline size_t block_map_get_last_size(block_map_t* map) +{ +if(map==NULL) + return 0; +return block_map_group_get_last_size(map->root); +} + +// Modification +bool block_map_add_block(heap_handle_t heap, block_map_t* map, heap_block_info_t const* info); +bool block_map_drop_root(heap_handle_t heap, block_map_t* map); +bool block_map_get_block(heap_handle_t heap, block_map_t* map, size_t min_size, heap_block_info_t* info); +bool block_map_lift_root(heap_handle_t heap, block_map_t* map); +void block_map_remove_block(heap_handle_t heap, block_map_t* map, heap_block_info_t const* info); + + +//==================== +// Offset-Index-Group +//==================== + +typedef cluster_group_t offset_index_group_t; + +// Access +size_t offset_index_group_get_first_offset(offset_index_group_t* group); +size_t offset_index_group_get_last_offset(offset_index_group_t* group); + +// Modification +bool offset_index_group_add_offset(heap_handle_t heap, offset_index_group_t* group, size_t offset, bool again); +void offset_index_group_remove_offset(heap_handle_t heap, offset_index_group_t* group, size_t offset); +size_t offset_index_group_remove_offset_at(heap_handle_t heap, offset_index_group_t* group, size_t at); + + +//========================= +// Offset-Index-Item-Group +//========================= + +typedef struct offset_index_item_group_t +{ +cluster_group_t header; +size_t items[CLUSTER_GROUP_SIZE]; +}offset_index_item_group_t; + +// Con-/Destructors +offset_index_item_group_t* offset_index_item_group_create(heap_handle_t heap); + +// Access +size_t offset_index_item_group_get_first_offset(offset_index_item_group_t* group); +uint16_t offset_index_item_group_get_item_pos(offset_index_item_group_t* group, size_t offset, bool* exists_ptr); +size_t offset_index_item_group_get_last_offset(offset_index_item_group_t* group); + +// Modification +bool offset_index_item_group_add_offset(offset_index_item_group_t* group, size_t offset); +void offset_index_item_group_append_items(offset_index_item_group_t* group, size_t const* items, uint16_t count); +void offset_index_item_group_insert_items(offset_index_item_group_t* group, uint16_t at, size_t const* insert, uint16_t count); +size_t offset_index_item_group_remove_item(offset_index_item_group_t* group, uint16_t at); +void offset_index_item_group_remove_offset(offset_index_item_group_t* group, size_t offset); +size_t offset_index_item_group_remove_offset_at(offset_index_item_group_t* group, size_t at, bool passive); +void offset_index_item_group_remove_items(offset_index_item_group_t* group, uint16_t at, uint16_t count); + + +//=========================== +// Offset-Index-Parent-Group +//=========================== + +typedef struct +{ +cluster_group_t header; +size_t item_count; +size_t first_offset; +size_t last_offset; +offset_index_group_t* children[CLUSTER_GROUP_SIZE]; +}offset_index_parent_group_t; + + +// Con-/Destructors +offset_index_parent_group_t* offset_index_parent_group_create(heap_handle_t heap, uint16_t level); +offset_index_parent_group_t* offset_index_parent_group_create_with_child(heap_handle_t heap, offset_index_group_t* child); + +// Access +uint16_t offset_index_parent_group_get_item_pos(offset_index_parent_group_t* group, size_t offset, uint16_t* pos_ptr, bool must_exist); + +// Modification +bool offset_index_parent_group_add_offset(heap_handle_t heap, offset_index_parent_group_t* group, size_t offset, bool again); +bool offset_index_parent_group_add_offset_internal(heap_handle_t heap, offset_index_parent_group_t* group, size_t offset, bool again); +void offset_index_parent_group_append_groups(offset_index_parent_group_t* group, offset_index_group_t* const* append, uint16_t count); +bool offset_index_parent_group_combine_child(heap_handle_t heap, offset_index_parent_group_t* group, uint16_t at); +void offset_index_parent_group_combine_children(heap_handle_t heap, offset_index_parent_group_t* group); +void offset_index_parent_group_insert_groups(offset_index_parent_group_t* group, uint16_t at, offset_index_group_t* const* insert, uint16_t count); +void offset_index_parent_group_move_children(offset_index_parent_group_t* group, uint16_t from, uint16_t to, uint16_t count); +void offset_index_parent_group_move_empty_slot(offset_index_parent_group_t* group, uint16_t from, uint16_t to); +void offset_index_parent_group_remove_groups(offset_index_parent_group_t* group, uint16_t at, uint16_t count); +void offset_index_parent_group_remove_offset(heap_handle_t heap, offset_index_parent_group_t* group, size_t offset); +size_t offset_index_parent_group_remove_offset_at(heap_handle_t heap, offset_index_parent_group_t* group, size_t at, bool passive); +bool offset_index_parent_group_shift_children(offset_index_parent_group_t* group, uint16_t at, uint16_t count); +bool offset_index_parent_group_split_child(heap_handle_t heap, offset_index_parent_group_t* group, uint16_t at); +void offset_index_parent_group_update_bounds(offset_index_parent_group_t* group); + + +//============== +// Offset-Index +//============== + +typedef struct +{ +offset_index_group_t* root; +}offset_index_t; + +// Con-/Destructors +void offset_index_init(offset_index_t* index); + +// Access +inline size_t offset_index_get_offset_count(offset_index_t* index) +{ +return cluster_group_get_item_count((cluster_group_t*)index->root); +} + +// Modification +bool offset_index_add_offset(heap_handle_t heap, offset_index_t* index, size_t offset); +void offset_index_drop_root(heap_handle_t heap, offset_index_t* index); +bool offset_index_lift_root(heap_handle_t heap, offset_index_t* index); +void offset_index_remove_offset(heap_handle_t heap, offset_index_t* index, size_t offset); +size_t offset_index_remove_offset_at(heap_handle_t heap, offset_index_t* index, size_t at); + + +//========== +// Portable +//========== + +void* pvPortCalloc(size_t xNum, size_t xSize); +void* pvPortMalloc(size_t xWantedSize); +void vPortDefineHeapRegions(HeapRegion_t const* pxHeapRegions)PRIVILEGED_FUNCTION; +void vPortFree(void* pv); +void vPortGetHeapStats(HeapStats_t* pxHeapStats); +void vPortHeapResetState(void); +size_t xPortGetFreeHeapSize(void); +size_t xPortGetMinimumEverFreeHeapSize(void); + +#endif // _HEAP_H