static bool _Heap_Walk_check_free_list( int source, Heap_Walk_printer printer, Heap_Control *heap ) { uintptr_t const page_size = heap->page_size; const Heap_Block *const free_list_tail = _Heap_Free_list_tail( heap ); const Heap_Block *const first_free_block = _Heap_Free_list_first( heap ); const Heap_Block *prev_block = free_list_tail; const Heap_Block *free_block = first_free_block; while ( free_block != free_list_tail ) { if ( !_Heap_Is_block_in_heap( heap, free_block ) ) { (*printer)( source, true, "free block 0x%08x: not in heap\n", free_block ); return false; } if ( !_Heap_Is_aligned( _Heap_Alloc_area_of_block( free_block ), page_size ) ) { (*printer)( source, true, "free block 0x%08x: alloc area not page aligned\n", free_block ); return false; } if ( _Heap_Is_used( free_block ) ) { (*printer)( source, true, "free block 0x%08x: is used\n", free_block ); return false; } if ( free_block->prev != prev_block ) { (*printer)( source, true, "free block 0x%08x: invalid previous block 0x%08x\n", free_block, free_block->prev ); return false; } prev_block = free_block; free_block = free_block->next; } return true; }
void _Heap_Block_split( Heap_Control *heap, Heap_Block *block, Heap_Block *free_list_anchor, uintptr_t alloc_size ) { Heap_Statistics *const stats = &heap->stats; uintptr_t const page_size = heap->page_size; uintptr_t const min_block_size = heap->min_block_size; uintptr_t const min_alloc_size = min_block_size - HEAP_BLOCK_HEADER_SIZE; uintptr_t const block_size = _Heap_Block_size( block ); uintptr_t const used_size = _Heap_Max( alloc_size, min_alloc_size ) + HEAP_BLOCK_HEADER_SIZE; uintptr_t const used_block_size = _Heap_Align_up( used_size, page_size ); uintptr_t const free_size = block_size + HEAP_BLOCK_SIZE_OFFSET - used_size; uintptr_t const free_size_limit = min_block_size + HEAP_BLOCK_SIZE_OFFSET; Heap_Block *next_block = _Heap_Block_at( block, block_size ); _HAssert( used_size <= block_size + HEAP_BLOCK_SIZE_OFFSET ); _HAssert( used_size + free_size == block_size + HEAP_BLOCK_SIZE_OFFSET ); if ( free_size >= free_size_limit ) { Heap_Block *const free_block = _Heap_Block_at( block, used_block_size ); uintptr_t free_block_size = block_size - used_block_size; _HAssert( used_block_size + free_block_size == block_size ); _Heap_Block_set_size( block, used_block_size ); /* Statistics */ stats->free_size += free_block_size; if ( _Heap_Is_used( next_block ) ) { _Heap_Free_list_insert_after( free_list_anchor, free_block ); /* Statistics */ ++stats->free_blocks; } else { uintptr_t const next_block_size = _Heap_Block_size( next_block ); _Heap_Free_list_replace( next_block, free_block ); free_block_size += next_block_size; next_block = _Heap_Block_at( free_block, free_block_size ); } free_block->size_and_flag = free_block_size | HEAP_PREV_BLOCK_USED; next_block->prev_size = free_block_size; next_block->size_and_flag &= ~HEAP_PREV_BLOCK_USED; } else { next_block->size_and_flag |= HEAP_PREV_BLOCK_USED; } }