/* SPDX-License-Identifier: BSD-2-Clause */ /** * @file * * @ingroup RTEMSScoreHeap * * @brief This source file contains the implementation of * _Heap_Resize_block(). */ /* * COPYRIGHT (c) 1989-1999. * On-Line Applications Research Corporation (OAR). * * Copyright (c) 2009 embedded brains GmbH & Co. KG * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include static Heap_Resize_status _Heap_Resize_block_checked( Heap_Control *heap, Heap_Block *block, uintptr_t alloc_begin, uintptr_t new_alloc_size, uintptr_t *old_size, uintptr_t *new_size ) { Heap_Statistics *const stats = &heap->stats; uintptr_t const block_begin = (uintptr_t) block; uintptr_t block_size = _Heap_Block_size( block ); uintptr_t block_end = block_begin + block_size; uintptr_t alloc_size = block_end - alloc_begin + HEAP_ALLOC_BONUS; Heap_Block *next_block = _Heap_Block_at( block, block_size ); uintptr_t next_block_size = _Heap_Block_size( next_block ); bool next_block_is_free = _Heap_Is_free( next_block ); _HAssert( _Heap_Is_block_in_heap( heap, next_block ) ); _HAssert( _Heap_Is_prev_used( next_block ) ); *old_size = alloc_size; if ( next_block_is_free ) { block_size += next_block_size; alloc_size += next_block_size; } if ( new_alloc_size > alloc_size ) { return HEAP_RESIZE_UNSATISFIED; } if ( next_block_is_free ) { _Heap_Block_set_size( block, block_size ); _Heap_Free_list_remove( next_block ); next_block = _Heap_Block_at( block, block_size ); next_block->size_and_flag |= HEAP_PREV_BLOCK_USED; /* Statistics */ --stats->free_blocks; stats->free_size -= next_block_size; } block = _Heap_Block_allocate( heap, block, alloc_begin, new_alloc_size ); block_size = _Heap_Block_size( block ); next_block = _Heap_Block_at( block, block_size ); *new_size = (uintptr_t) next_block - alloc_begin + HEAP_ALLOC_BONUS; /* Statistics */ ++stats->resizes; return HEAP_RESIZE_SUCCESSFUL; } Heap_Resize_status _Heap_Resize_block( Heap_Control *heap, void *alloc_begin_ptr, uintptr_t new_alloc_size, uintptr_t *old_size, uintptr_t *new_size ) { uintptr_t const page_size = heap->page_size; uintptr_t const alloc_begin = (uintptr_t) alloc_begin_ptr; Heap_Block *const block = _Heap_Block_of_alloc_area( alloc_begin, page_size ); *old_size = 0; *new_size = 0; if ( _Heap_Is_block_in_heap( heap, block ) ) { _Heap_Protection_block_check( heap, block ); /* TODO: Free only the next block if necessary */ _Heap_Protection_free_all_delayed_blocks( heap ); return _Heap_Resize_block_checked( heap, block, alloc_begin, new_alloc_size, old_size, new_size ); } return HEAP_RESIZE_FATAL_ERROR; }