/** * @file * * @brief Heap Handler API */ /* * COPYRIGHT (c) 1989-2008. * On-Line Applications Research Corporation (OAR). * * The license and distribution terms for this file may be * found in the file LICENSE in this distribution or at * http://www.rtems.com/license/LICENSE. */ #ifndef _RTEMS_SCORE_HEAP_H # error "Never use directly; include instead." #endif #ifndef _RTEMS_SCORE_HEAP_INL #define _RTEMS_SCORE_HEAP_INL #include /** * @addtogroup ScoreHeap */ /**@{**/ RTEMS_INLINE_ROUTINE Heap_Block *_Heap_Free_list_head( Heap_Control *heap ) { return &heap->free_list; } RTEMS_INLINE_ROUTINE Heap_Block *_Heap_Free_list_tail( Heap_Control *heap ) { return &heap->free_list; } RTEMS_INLINE_ROUTINE Heap_Block *_Heap_Free_list_first( Heap_Control *heap ) { return _Heap_Free_list_head(heap)->next; } RTEMS_INLINE_ROUTINE Heap_Block *_Heap_Free_list_last( Heap_Control *heap ) { return _Heap_Free_list_tail(heap)->prev; } RTEMS_INLINE_ROUTINE void _Heap_Free_list_remove( Heap_Block *block ) { Heap_Block *next = block->next; Heap_Block *prev = block->prev; prev->next = next; next->prev = prev; } RTEMS_INLINE_ROUTINE void _Heap_Free_list_replace( Heap_Block *old_block, Heap_Block *new_block ) { Heap_Block *next = old_block->next; Heap_Block *prev = old_block->prev; new_block->next = next; new_block->prev = prev; next->prev = new_block; prev->next = new_block; } RTEMS_INLINE_ROUTINE void _Heap_Free_list_insert_after( Heap_Block *block_before, Heap_Block *new_block ) { Heap_Block *next = block_before->next; new_block->next = next; new_block->prev = block_before; block_before->next = new_block; next->prev = new_block; } RTEMS_INLINE_ROUTINE void _Heap_Free_list_insert_before( Heap_Block *block_next, Heap_Block *new_block ) { Heap_Block *prev = block_next->prev; new_block->next = block_next; new_block->prev = prev; prev->next = new_block; block_next->prev = new_block; } RTEMS_INLINE_ROUTINE bool _Heap_Is_aligned( uintptr_t value, uintptr_t alignment ) { return (value % alignment) == 0; } RTEMS_INLINE_ROUTINE uintptr_t _Heap_Align_down( uintptr_t value, uintptr_t alignment ) { return value - (value % alignment); } /** * @brief Returns the block which is @a offset away from @a block. */ RTEMS_INLINE_ROUTINE Heap_Block *_Heap_Block_at( const Heap_Block *block, uintptr_t offset ) { return (Heap_Block *) ((uintptr_t) block + offset); } RTEMS_INLINE_ROUTINE Heap_Block *_Heap_Prev_block( const Heap_Block *block ) { return (Heap_Block *) ((uintptr_t) block - block->prev_size); } RTEMS_INLINE_ROUTINE uintptr_t _Heap_Alloc_area_of_block( const Heap_Block *block ) { return (uintptr_t) block + HEAP_BLOCK_HEADER_SIZE; } RTEMS_INLINE_ROUTINE Heap_Block *_Heap_Block_of_alloc_area( uintptr_t alloc_begin, uintptr_t page_size ) { return (Heap_Block *) (_Heap_Align_down( alloc_begin, page_size ) - HEAP_BLOCK_HEADER_SIZE); } RTEMS_INLINE_ROUTINE uintptr_t _Heap_Block_size( const Heap_Block *block ) { return block->size_and_flag & ~HEAP_PREV_BLOCK_USED; } RTEMS_INLINE_ROUTINE void _Heap_Block_set_size( Heap_Block *block, uintptr_t size ) { uintptr_t flag = block->size_and_flag & HEAP_PREV_BLOCK_USED; block->size_and_flag = size | flag; } RTEMS_INLINE_ROUTINE bool _Heap_Is_prev_used( const Heap_Block *block ) { return block->size_and_flag & HEAP_PREV_BLOCK_USED; } RTEMS_INLINE_ROUTINE bool _Heap_Is_used( const Heap_Block *block ) { const Heap_Block *const next_block = _Heap_Block_at( block, _Heap_Block_size( block ) ); return _Heap_Is_prev_used( next_block ); } RTEMS_INLINE_ROUTINE bool _Heap_Is_free( const Heap_Block *block ) { return !_Heap_Is_used( block ); } RTEMS_INLINE_ROUTINE bool _Heap_Is_block_in_heap( const Heap_Control *heap, const Heap_Block *block ) { return (uintptr_t) block >= (uintptr_t) heap->first_block && (uintptr_t) block <= (uintptr_t) heap->last_block; } /** * @brief Sets the size of the last block for heap @a heap. * * The next block of the last block will be the first block. Since the first * block indicates that the previous block is used, this ensures that the last * block appears as used for the _Heap_Is_used() and _Heap_Is_free() * functions. * * This feature will be used to terminate the scattered heap area list. See * also _Heap_Extend(). */ RTEMS_INLINE_ROUTINE void _Heap_Set_last_block_size( Heap_Control *heap ) { _Heap_Block_set_size( heap->last_block, (uintptr_t) heap->first_block - (uintptr_t) heap->last_block ); } /** * @brief Returns the size of the allocatable area in bytes. * * This value is an integral multiple of the page size. */ RTEMS_INLINE_ROUTINE uintptr_t _Heap_Get_size( const Heap_Control *heap ) { return heap->stats.size; } RTEMS_INLINE_ROUTINE uintptr_t _Heap_Max( uintptr_t a, uintptr_t b ) { return a > b ? a : b; } RTEMS_INLINE_ROUTINE uintptr_t _Heap_Min( uintptr_t a, uintptr_t b ) { return a < b ? a : b; } /** @} */ #endif /* end of include file */