From b2a0214d4395787eca8e74375d283bf26c9ca4a1 Mon Sep 17 00:00:00 2001 From: Sebastian Huber Date: Mon, 7 Jun 2010 09:35:01 +0000 Subject: 2010-06-07 Sebastian Huber * score/include/rtems/score/heap.h: Declare _Heap_Get_first_and_last_block(). Removed Heap_Extend_status. Changed return type of _Heap_Extend() to bool. * score/inline/rtems/score/heap.inl: Define _Heap_Set_last_block_size(). * score/src/heap.c: Define and use _Heap_Get_first_and_last_block(). * score/src/heapgetinfo.c: Removed assert statements. Do not count the last block. This ensures that all size values are an integral multiple of the page size which is consistent with the other statistics. * score/src/heapextend.c: Implemented support for scattered heap areas. * score/src/heapwalk.c: Dump also last block. Changes for new first and last block values. * ./score/src/pheapextend.c, rtems/src/regionextend.c: Update for _Heap_Extend() changes. --- cpukit/ChangeLog | 19 +++ cpukit/rtems/src/regionextend.c | 10 +- cpukit/score/include/rtems/score/heap.h | 49 ++++-- cpukit/score/inline/rtems/score/heap.inl | 18 +++ cpukit/score/src/heap.c | 92 ++++++++---- cpukit/score/src/heapextend.c | 249 ++++++++++++++++++++++++------- cpukit/score/src/heapgetinfo.c | 19 +-- cpukit/score/src/heapwalk.c | 69 ++++----- cpukit/score/src/pheapextend.c | 8 +- 9 files changed, 375 insertions(+), 158 deletions(-) (limited to 'cpukit') diff --git a/cpukit/ChangeLog b/cpukit/ChangeLog index f466696f16..28e50cf04d 100644 --- a/cpukit/ChangeLog +++ b/cpukit/ChangeLog @@ -1,3 +1,22 @@ +2010-06-07 Sebastian Huber + + * score/include/rtems/score/heap.h: Declare + _Heap_Get_first_and_last_block(). Removed Heap_Extend_status. + Changed return type of _Heap_Extend() to bool. + * score/inline/rtems/score/heap.inl: Define + _Heap_Set_last_block_size(). + * score/src/heap.c: Define and use _Heap_Get_first_and_last_block(). + * score/src/heapgetinfo.c: Removed assert statements. Do not count + the last block. This ensures that all size values are an integral + multiple of the page size which is consistent with the other + statistics. + * score/src/heapextend.c: Implemented support for scattered heap + areas. + * score/src/heapwalk.c: Dump also last block. Changes for new first + and last block values. + * ./score/src/pheapextend.c, rtems/src/regionextend.c: Update for + _Heap_Extend() changes. + 2010-06-03 Chris Johns * sapi/include/confdefs.h: PR 1543. Make default file system when diff --git a/cpukit/rtems/src/regionextend.c b/cpukit/rtems/src/regionextend.c index 0531381328..f4b6c93c2d 100644 --- a/cpukit/rtems/src/regionextend.c +++ b/cpukit/rtems/src/regionextend.c @@ -49,7 +49,7 @@ rtems_status_code rtems_region_extend( ) { uintptr_t amount_extended; - Heap_Extend_status heap_status; + bool extend_ok; Objects_Locations location; rtems_status_code return_status; Region_Control *the_region; @@ -64,21 +64,19 @@ rtems_status_code rtems_region_extend( case OBJECTS_LOCAL: - heap_status = _Heap_Extend( + extend_ok = _Heap_Extend( &the_region->Memory, starting_address, length, &amount_extended ); - if ( heap_status == HEAP_EXTEND_SUCCESSFUL ) { + if ( extend_ok ) { the_region->length += amount_extended; the_region->maximum_segment_size += amount_extended; return_status = RTEMS_SUCCESSFUL; - } else if ( heap_status == HEAP_EXTEND_ERROR ) { + } else { return_status = RTEMS_INVALID_ADDRESS; - } else /* if ( heap_status == HEAP_EXTEND_NOT_IMPLEMENTED ) */ { - return_status = RTEMS_NOT_IMPLEMENTED; } break; diff --git a/cpukit/score/include/rtems/score/heap.h b/cpukit/score/include/rtems/score/heap.h index c2286bf2af..286cc94218 100644 --- a/cpukit/score/include/rtems/score/heap.h +++ b/cpukit/score/include/rtems/score/heap.h @@ -92,7 +92,10 @@ extern "C" { * heap->area_beginheap area begin address * * first_block->prev_size - * page size (the value is arbitrary) + * + * subordinate heap area end address (this will be used to maintain a + * linked list of scattered heap areas) + * * * * first_block->size @@ -310,15 +313,6 @@ typedef struct { Heap_Information Used; } Heap_Information_block; -/** - * @brief See _Heap_Extend(). - */ -typedef enum { - HEAP_EXTEND_SUCCESSFUL, - HEAP_EXTEND_ERROR, - HEAP_EXTEND_NOT_IMPLEMENTED -} Heap_Extend_status; - /** * @brief See _Heap_Resize_block(). */ @@ -328,6 +322,29 @@ typedef enum { HEAP_RESIZE_FATAL_ERROR } Heap_Resize_status; +/** + * @brief Gets the first and last block for the heap area with begin + * @a heap_area_begin and size @a heap_area_size. + * + * A page size of @a page_size and minimal block size of @a min_block_size will + * be used for calculation. + * + * Nothing will be written to this area. + * + * In case of success the pointers to the first and last block will be returned + * via @a first_block_ptr and @a last_block_ptr. + * + * Returns @c true if the area is big enough, and @c false otherwise. + */ +bool _Heap_Get_first_and_last_block( + uintptr_t heap_area_begin, + uintptr_t heap_area_size, + uintptr_t page_size, + uintptr_t min_block_size, + Heap_Block **first_block_ptr, + Heap_Block **last_block_ptr +); + /** * @brief Initializes the heap control block @a heap to manage the area * starting at @a area_begin of size @a area_size bytes. @@ -350,11 +367,15 @@ uintptr_t _Heap_Initialize( * starting at @a area_begin of size @a area_size bytes. * * The extended space available for allocation will be returned in - * @a amount_extended. + * @a amount_extended. This pointer may be @c NULL. + * + * The memory area must be big enough to contain some maintainance blocks. It + * must not overlap parts of the current heap areas. Disconnected subordinate + * heap areas will lead to used blocks which cover the gaps. * - * The memory area must start at the end of the currently used memory area. + * Returns @c true in case of success, and @c false otherwise. */ -Heap_Extend_status _Heap_Extend( +bool _Heap_Extend( Heap_Control *heap, void *area_begin, uintptr_t area_size, @@ -368,7 +389,7 @@ Heap_Extend_status _Heap_Extend( * memory area will begin at an address aligned by this value. * * If the boundary parameter @a boundary is not equal to zero, the allocated - * memory area will fulfill a boundary constraint. The boudnary value + * memory area will fulfill a boundary constraint. The boundary value * specifies the set of addresses which are aligned by the boundary value. The * interior of the allocated memory area will not contain an element of this * set. The begin or end address of the area may be a member of the set. diff --git a/cpukit/score/inline/rtems/score/heap.inl b/cpukit/score/inline/rtems/score/heap.inl index 0f14a0b245..50fb16a55c 100644 --- a/cpukit/score/inline/rtems/score/heap.inl +++ b/cpukit/score/inline/rtems/score/heap.inl @@ -199,6 +199,24 @@ RTEMS_INLINE_ROUTINE bool _Heap_Is_block_in_heap( && (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. * diff --git a/cpukit/score/src/heap.c b/cpukit/score/src/heap.c index c851334679..a0efe71cdd 100644 --- a/cpukit/score/src/heap.c +++ b/cpukit/score/src/heap.c @@ -10,7 +10,7 @@ * COPYRIGHT (c) 1989-2009. * On-Line Applications Research Corporation (OAR). * - * Copyright (c) 2009 embedded brains GmbH. + * Copyright (c) 2009, 2010 embedded brains GmbH. * * The license and distribution terms for this file may be * found in the file LICENSE in this distribution or at @@ -123,6 +123,43 @@ static uint32_t instance = 0; * */ +bool _Heap_Get_first_and_last_block( + uintptr_t heap_area_begin, + uintptr_t heap_area_size, + uintptr_t page_size, + uintptr_t min_block_size, + Heap_Block **first_block_ptr, + Heap_Block **last_block_ptr +) +{ + uintptr_t const heap_area_end = heap_area_begin + heap_area_size; + uintptr_t const alloc_area_begin = + _Heap_Align_up( heap_area_begin + HEAP_BLOCK_HEADER_SIZE, page_size ); + uintptr_t const first_block_begin = + alloc_area_begin - HEAP_BLOCK_HEADER_SIZE; + uintptr_t const overhead = + HEAP_BLOCK_HEADER_SIZE + (first_block_begin - heap_area_begin); + uintptr_t const first_block_size = + _Heap_Align_down( heap_area_size - overhead, page_size ); + Heap_Block *const first_block = (Heap_Block *) first_block_begin; + Heap_Block *const last_block = + _Heap_Block_at( first_block, first_block_size ); + + if ( + heap_area_end < heap_area_begin + || heap_area_size <= overhead + || first_block_size < min_block_size + ) { + /* Invalid area or area too small */ + return false; + } + + *first_block_ptr = first_block; + *last_block_ptr = last_block; + + return true; +} + uintptr_t _Heap_Initialize( Heap_Control *heap, void *heap_area_begin_ptr, @@ -133,12 +170,11 @@ uintptr_t _Heap_Initialize( Heap_Statistics *const stats = &heap->stats; uintptr_t const heap_area_begin = (uintptr_t) heap_area_begin_ptr; uintptr_t const heap_area_end = heap_area_begin + heap_area_size; - uintptr_t alloc_area_begin = heap_area_begin + HEAP_BLOCK_HEADER_SIZE; - uintptr_t alloc_area_size = 0; uintptr_t first_block_begin = 0; uintptr_t first_block_size = 0; + uintptr_t last_block_begin = 0; uintptr_t min_block_size = 0; - uintptr_t overhead = 0; + bool area_ok = false; Heap_Block *first_block = NULL; Heap_Block *last_block = NULL; @@ -154,41 +190,28 @@ uintptr_t _Heap_Initialize( } min_block_size = _Heap_Align_up( sizeof( Heap_Block ), page_size ); - alloc_area_begin = _Heap_Align_up( alloc_area_begin, page_size ); - first_block_begin = alloc_area_begin - HEAP_BLOCK_HEADER_SIZE; - overhead = HEAP_BLOCK_HEADER_SIZE + (first_block_begin - heap_area_begin); - first_block_size = heap_area_size - overhead; - first_block_size = _Heap_Align_down ( first_block_size, page_size ); - alloc_area_size = first_block_size - HEAP_BLOCK_HEADER_SIZE; - - if ( - heap_area_end < heap_area_begin - || heap_area_size <= overhead - || first_block_size < min_block_size - ) { - /* Invalid area or area too small */ + area_ok = _Heap_Get_first_and_last_block( + heap_area_begin, + heap_area_size, + page_size, + min_block_size, + &first_block, + &last_block + ); + if ( !area_ok ) { return 0; } + first_block_begin = (uintptr_t) first_block; + last_block_begin = (uintptr_t) last_block; + first_block_size = last_block_begin - first_block_begin; + /* First block */ - first_block = (Heap_Block *) first_block_begin; - first_block->prev_size = page_size; + first_block->prev_size = heap_area_end; first_block->size_and_flag = first_block_size | HEAP_PREV_BLOCK_USED; first_block->next = _Heap_Free_list_tail( heap ); first_block->prev = _Heap_Free_list_head( heap ); - /* - * Last block. - * - * The next block of the last block is 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. - */ - last_block = _Heap_Block_at( first_block, first_block_size ); - last_block->prev_size = first_block_size; - last_block->size_and_flag = first_block_begin - (uintptr_t) last_block; - /* Heap control */ heap->page_size = page_size; heap->min_block_size = min_block_size; @@ -199,6 +222,11 @@ uintptr_t _Heap_Initialize( _Heap_Free_list_head( heap )->next = first_block; _Heap_Free_list_tail( heap )->prev = first_block; + /* Last block */ + last_block->prev_size = first_block_size; + last_block->size_and_flag = 0; + _Heap_Set_last_block_size( heap ); + /* Statistics */ stats->size = first_block_size; stats->free_size = first_block_size; @@ -222,7 +250,7 @@ uintptr_t _Heap_Initialize( _Heap_Is_aligned( _Heap_Alloc_area_of_block( last_block ), page_size ) ); - return alloc_area_size; + return first_block_size; } void _Heap_Block_split( diff --git a/cpukit/score/src/heapextend.c b/cpukit/score/src/heapextend.c index 02826a82b4..c928e53f73 100644 --- a/cpukit/score/src/heapextend.c +++ b/cpukit/score/src/heapextend.c @@ -10,6 +10,8 @@ * COPYRIGHT (c) 1989-1999. * On-Line Applications Research Corporation (OAR). * + * Copyright (c) 2010 embedded brains GmbH. + * * 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. @@ -25,72 +27,215 @@ #include #include -Heap_Extend_status _Heap_Extend( +static void _Heap_Free_block( Heap_Control *heap, Heap_Block *block ) +{ + Heap_Statistics *const stats = &heap->stats; + + /* Statistics */ + ++stats->used_blocks; + --stats->frees; + + _Heap_Free( heap, (void *) _Heap_Alloc_area_of_block( block )); +} + +static void _Heap_Merge_below( + Heap_Control *heap, + uintptr_t extend_area_begin, + Heap_Block *first_block +) +{ + uintptr_t const page_size = heap->page_size; + uintptr_t const new_first_block_alloc_begin = + _Heap_Align_up( extend_area_begin + HEAP_BLOCK_HEADER_SIZE, page_size ); + uintptr_t const new_first_block_begin = + new_first_block_alloc_begin - HEAP_BLOCK_HEADER_SIZE; + uintptr_t const first_block_begin = (uintptr_t) first_block; + uintptr_t const new_first_block_size = + first_block_begin - new_first_block_begin; + Heap_Block *const new_first_block = (Heap_Block *) new_first_block_begin; + + new_first_block->prev_size = first_block->prev_size; + new_first_block->size_and_flag = new_first_block_size | HEAP_PREV_BLOCK_USED; + + _Heap_Free_block( heap, new_first_block ); +} + +static void _Heap_Merge_above( + Heap_Control *heap, + Heap_Block *last_block, + uintptr_t extend_area_end +) +{ + uintptr_t const page_size = heap->page_size; + uintptr_t const last_block_begin = (uintptr_t) last_block; + uintptr_t const last_block_new_size = _Heap_Align_down( + extend_area_end - last_block_begin - HEAP_BLOCK_HEADER_SIZE, + page_size + ); + Heap_Block *const new_last_block = + _Heap_Block_at( last_block, last_block_new_size ); + + new_last_block->size_and_flag = + (last_block->size_and_flag - last_block_new_size) + | HEAP_PREV_BLOCK_USED; + + _Heap_Block_set_size( last_block, last_block_new_size ); + + _Heap_Free_block( heap, last_block ); +} + +static void _Heap_Link_below( + Heap_Block *link, + Heap_Block *last_block +) +{ + uintptr_t const last_block_begin = (uintptr_t) last_block; + uintptr_t const link_begin = (uintptr_t) link; + + last_block->size_and_flag = + (link_begin - last_block_begin) | HEAP_PREV_BLOCK_USED; +} + +static void _Heap_Link_above( + Heap_Block *link, + Heap_Block *first_block, + Heap_Block *last_block +) +{ + uintptr_t const link_begin = (uintptr_t) link; + uintptr_t const first_block_begin = (uintptr_t) first_block; + + _Heap_Block_set_size( link, first_block_begin - link_begin ); + + last_block->size_and_flag |= HEAP_PREV_BLOCK_USED; +} + +bool _Heap_Extend( Heap_Control *heap, - void *area_begin_ptr, - uintptr_t area_size, - uintptr_t *amount_extended + void *extend_area_begin_ptr, + uintptr_t extend_area_size, + uintptr_t *extended_size_ptr ) { Heap_Statistics *const stats = &heap->stats; - uintptr_t const area_begin = (uintptr_t) area_begin_ptr; - uintptr_t const heap_area_begin = heap->area_begin; - uintptr_t const heap_area_end = heap->area_end; - uintptr_t const new_heap_area_end = heap_area_end + area_size; - uintptr_t extend_size = 0; - Heap_Block *const last_block = heap->last_block; - - /* - * There are five possibilities for the location of starting - * address: - * - * 1. non-contiguous lower address (NOT SUPPORTED) - * 2. contiguous lower address (NOT SUPPORTED) - * 3. in the heap (ERROR) - * 4. contiguous higher address (SUPPORTED) - * 5. non-contiguous higher address (NOT SUPPORTED) - * - * As noted, this code only supports (4). - */ - - if ( area_begin >= heap_area_begin && area_begin < heap_area_end ) { - return HEAP_EXTEND_ERROR; /* case 3 */ - } else if ( area_begin != heap_area_end ) { - return HEAP_EXTEND_NOT_IMPLEMENTED; /* cases 1, 2, and 5 */ + Heap_Block *const first_block = heap->first_block; + Heap_Block *start_block = first_block; + Heap_Block *merge_below_block = NULL; + Heap_Block *merge_above_block = NULL; + Heap_Block *link_below_block = NULL; + Heap_Block *link_above_block = NULL; + Heap_Block *extend_first_block = NULL; + Heap_Block *extend_last_block = NULL; + uintptr_t const page_size = heap->page_size; + uintptr_t const min_block_size = heap->min_block_size; + uintptr_t const extend_area_begin = (uintptr_t) extend_area_begin_ptr; + uintptr_t const extend_area_end = extend_area_begin + extend_area_size; + uintptr_t const free_size = stats->free_size; + uintptr_t extend_first_block_size = 0; + uintptr_t extended_size = 0; + bool extend_area_ok = false; + + if ( extend_area_end < extend_area_begin ) { + return false; } - /* - * Currently only case 4 should make it to this point. - * The basic trick is to make the extend area look like a used - * block and free it. - */ - - heap->area_end = new_heap_area_end; + extend_area_ok = _Heap_Get_first_and_last_block( + extend_area_begin, + extend_area_size, + page_size, + min_block_size, + &extend_first_block, + &extend_last_block + ); + if (!extend_area_ok ) { + /* For simplicity we reject extend areas that are too small */ + return false; + } - extend_size = new_heap_area_end - - (uintptr_t) last_block - HEAP_BLOCK_HEADER_SIZE; - extend_size = _Heap_Align_down( extend_size, heap->page_size ); + do { + uintptr_t const sub_area_begin = (start_block != first_block) ? + (uintptr_t) start_block : heap->area_begin; + uintptr_t const sub_area_end = start_block->prev_size; + Heap_Block *const end_block = + _Heap_Block_of_alloc_area( sub_area_end, page_size ); + + if ( + sub_area_end > extend_area_begin && extend_area_end > sub_area_begin + ) { + return false; + } + + if ( extend_area_end == sub_area_begin ) { + merge_below_block = start_block; + } else if ( extend_area_end < sub_area_end ) { + link_below_block = start_block; + } + + if ( sub_area_end == extend_area_begin ) { + start_block->prev_size = extend_area_end; + + merge_above_block = end_block; + } else if ( sub_area_end < extend_area_begin ) { + link_above_block = end_block; + } + + start_block = _Heap_Block_at( end_block, _Heap_Block_size( end_block ) ); + } while ( start_block != first_block ); + + if ( extend_area_begin < heap->area_begin ) { + heap->area_begin = extend_area_begin; + } else if ( heap->area_end < extend_area_end ) { + heap->area_end = extend_area_end; + } - *amount_extended = extend_size; + extend_first_block_size = + (uintptr_t) extend_last_block - (uintptr_t) extend_first_block; - if( extend_size >= heap->min_block_size ) { - Heap_Block *const new_last_block = _Heap_Block_at( last_block, extend_size ); + extend_first_block->prev_size = extend_area_end; + extend_first_block->size_and_flag = + extend_first_block_size | HEAP_PREV_BLOCK_USED; - _Heap_Block_set_size( last_block, extend_size ); + extend_last_block->prev_size = extend_first_block_size; + extend_last_block->size_and_flag = 0; - new_last_block->size_and_flag = - ((uintptr_t) heap->first_block - (uintptr_t) new_last_block) - | HEAP_PREV_BLOCK_USED; + if ( (uintptr_t) extend_first_block < (uintptr_t) heap->first_block ) { + heap->first_block = extend_first_block; + } else if ( (uintptr_t) extend_last_block > (uintptr_t) heap->last_block ) { + heap->last_block = extend_last_block; + } - heap->last_block = new_last_block; + if ( merge_below_block != NULL ) { + _Heap_Merge_below( heap, extend_area_begin, merge_below_block ); + } else if ( link_below_block != NULL ) { + _Heap_Link_below( + link_below_block, + extend_last_block + ); + } - /* Statistics */ - stats->size += extend_size; - ++stats->used_blocks; - --stats->frees; /* Do not count subsequent call as actual free() */ + if ( merge_above_block != NULL ) { + _Heap_Merge_above( heap, merge_above_block, extend_area_end ); + } else if ( link_above_block != NULL ) { + _Heap_Link_above( + link_above_block, + extend_first_block, + extend_last_block + ); + } - _Heap_Free( heap, (void *) _Heap_Alloc_area_of_block( last_block )); + if ( merge_below_block == NULL && merge_above_block == NULL ) { + _Heap_Free_block( heap, extend_first_block ); } - return HEAP_EXTEND_SUCCESSFUL; + _Heap_Set_last_block_size( heap ); + + extended_size = stats->free_size - free_size; + + /* Statistics */ + stats->size += extended_size; + + if ( extended_size_ptr != NULL ) + *extended_size_ptr = extended_size; + + return true; } diff --git a/cpukit/score/src/heapgetinfo.c b/cpukit/score/src/heapgetinfo.c index bc3d4cc893..bcb5a7f68d 100644 --- a/cpukit/score/src/heapgetinfo.c +++ b/cpukit/score/src/heapgetinfo.c @@ -21,6 +21,8 @@ #include "config.h" #endif +#include + #include #include #include @@ -33,15 +35,7 @@ void _Heap_Get_information( Heap_Block *the_block = the_heap->first_block; Heap_Block *const end = the_heap->last_block; - _HAssert(the_block->prev_size == the_heap->page_size); - _HAssert(_Heap_Is_prev_used(the_block)); - - the_info->Free.number = 0; - the_info->Free.total = 0; - the_info->Free.largest = 0; - the_info->Used.number = 0; - the_info->Used.total = 0; - the_info->Used.largest = 0; + memset(the_info, 0, sizeof(*the_info)); while ( the_block != end ) { uintptr_t const the_size = _Heap_Block_size(the_block); @@ -60,11 +54,4 @@ void _Heap_Get_information( the_block = next_block; } - - /* - * Handle the last dummy block. Don't consider this block to be - * "used" as client never allocated it. Make 'Used.total' contain this - * blocks' overhead though. - */ - the_info->Used.total += HEAP_BLOCK_HEADER_SIZE; } diff --git a/cpukit/score/src/heapwalk.c b/cpukit/score/src/heapwalk.c index f7043c0c41..fae0bd6330 100644 --- a/cpukit/score/src/heapwalk.c +++ b/cpukit/score/src/heapwalk.c @@ -217,23 +217,23 @@ static bool _Heap_Walk_check_control( return false; } - if ( first_block->prev_size != page_size ) { + if ( _Heap_Is_free( last_block ) ) { (*printer)( source, true, - "first block: prev size %u != page size %u\n", - first_block->prev_size, - page_size + "last block: is free\n" ); return false; } - if ( _Heap_Is_free( last_block ) ) { + if ( + _Heap_Block_at( last_block, _Heap_Block_size( last_block ) ) != first_block + ) { (*printer)( source, true, - "last block: is free\n" + "last block: next block is not the first block\n" ); return false; @@ -260,15 +260,16 @@ static bool _Heap_Walk_check_free_block( (*printer)( source, false, - "block 0x%08x: prev 0x%08x%s, next 0x%08x%s\n", + "block 0x%08x: size %u, prev 0x%08x%s, next 0x%08x%s\n", block, + block_size, block->prev, block->prev == first_free_block ? - " (= first)" + " (= first free)" : (block->prev == free_list_head ? " (= head)" : ""), block->next, block->next == last_free_block ? - " (= last)" + " (= last free)" : (block->next == free_list_tail ? " (= tail)" : "") ); @@ -319,8 +320,9 @@ bool _Heap_Walk( { uintptr_t const page_size = heap->page_size; uintptr_t const min_block_size = heap->min_block_size; + Heap_Block *const first_block = heap->first_block; Heap_Block *const last_block = heap->last_block; - Heap_Block *block = heap->first_block; + Heap_Block *block = first_block; Heap_Walk_printer printer = dump ? _Heap_Walk_print : _Heap_Walk_print_nothing; @@ -332,31 +334,13 @@ bool _Heap_Walk( return false; } - while ( block != last_block ) { + do { uintptr_t const block_begin = (uintptr_t) block; uintptr_t const block_size = _Heap_Block_size( block ); bool const prev_used = _Heap_Is_prev_used( block ); Heap_Block *const next_block = _Heap_Block_at( block, block_size ); uintptr_t const next_block_begin = (uintptr_t) next_block; - - if ( prev_used ) { - (*printer)( - source, - false, - "block 0x%08x: size %u\n", - block, - block_size - ); - } else { - (*printer)( - source, - false, - "block 0x%08x: size %u, prev_size %u\n", - block, - block_size, - block->prev_size - ); - } + bool const is_not_last_block = block != last_block; if ( !_Heap_Is_block_in_heap( heap, next_block ) ) { (*printer)( @@ -370,7 +354,7 @@ bool _Heap_Walk( return false; } - if ( !_Heap_Is_aligned( block_size, page_size ) ) { + if ( !_Heap_Is_aligned( block_size, page_size ) && is_not_last_block ) { (*printer)( source, true, @@ -382,7 +366,7 @@ bool _Heap_Walk( return false; } - if ( block_size < min_block_size ) { + if ( block_size < min_block_size && is_not_last_block ) { (*printer)( source, true, @@ -395,7 +379,7 @@ bool _Heap_Walk( return false; } - if ( next_block_begin <= block_begin ) { + if ( next_block_begin <= block_begin && is_not_last_block ) { (*printer)( source, true, @@ -411,10 +395,27 @@ bool _Heap_Walk( if ( !_Heap_Walk_check_free_block( source, printer, heap, block ) ) { return false; } + } else if (prev_used) { + (*printer)( + source, + false, + "block 0x%08x: size %u\n", + block, + block_size + ); + } else { + (*printer)( + source, + false, + "block 0x%08x: size %u, prev_size %u\n", + block, + block_size, + block->prev_size + ); } block = next_block; - } + } while ( block != first_block ); return true; } diff --git a/cpukit/score/src/pheapextend.c b/cpukit/score/src/pheapextend.c index c2aa9735b9..e71fb1bd8c 100644 --- a/cpukit/score/src/pheapextend.c +++ b/cpukit/score/src/pheapextend.c @@ -30,12 +30,12 @@ bool _Protected_heap_Extend( uintptr_t size ) { - Heap_Extend_status status; - uintptr_t amount_extended; + bool extend_ok; + uintptr_t amount_extended; _RTEMS_Lock_allocator(); - status = _Heap_Extend(the_heap, starting_address, size, &amount_extended); + extend_ok = _Heap_Extend(the_heap, starting_address, size, &amount_extended); _RTEMS_Unlock_allocator(); - return (status == HEAP_EXTEND_SUCCESSFUL); + return extend_ok; } -- cgit v1.2.3