summaryrefslogtreecommitdiffstats
path: root/cpukit
diff options
context:
space:
mode:
authorSebastian Huber <sebastian.huber@embedded-brains.de>2010-06-07 09:35:01 +0000
committerSebastian Huber <sebastian.huber@embedded-brains.de>2010-06-07 09:35:01 +0000
commitb2a0214d4395787eca8e74375d283bf26c9ca4a1 (patch)
treeeb91086d7da6342ea88ad774939bb90afcfd3e4f /cpukit
parent2010-06-07 Sebastian Huber <sebastian.huber@embedded-brains.de> (diff)
downloadrtems-b2a0214d4395787eca8e74375d283bf26c9ca4a1.tar.bz2
2010-06-07 Sebastian Huber <sebastian.huber@embedded-brains.de>
* 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.
Diffstat (limited to 'cpukit')
-rw-r--r--cpukit/ChangeLog19
-rw-r--r--cpukit/rtems/src/regionextend.c10
-rw-r--r--cpukit/score/include/rtems/score/heap.h49
-rw-r--r--cpukit/score/inline/rtems/score/heap.inl18
-rw-r--r--cpukit/score/src/heap.c92
-rw-r--r--cpukit/score/src/heapextend.c249
-rw-r--r--cpukit/score/src/heapgetinfo.c19
-rw-r--r--cpukit/score/src/heapwalk.c69
-rw-r--r--cpukit/score/src/pheapextend.c8
9 files changed, 375 insertions, 158 deletions
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 <sebastian.huber@embedded-brains.de>
+
+ * 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 <chrisj@rtems.org>
* 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" {
* <tr><td>heap->area_begin</td><td colspan=2>heap area begin address</td></tr>
* <tr>
* <td>first_block->prev_size</td>
- * <td colspan=2>page size (the value is arbitrary)</td>
+ * <td colspan=2>
+ * subordinate heap area end address (this will be used to maintain a
+ * linked list of scattered heap areas)
+ * </td>
* </tr>
* <tr>
* <td>first_block->size</td>
@@ -311,15 +314,6 @@ typedef struct {
} 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().
*/
typedef enum {
@@ -329,6 +323,29 @@ typedef enum {
} 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
@@ -200,6 +200,24 @@ RTEMS_INLINE_ROUTINE bool _Heap_Is_block_in_heap(
}
/**
+ * @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.
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 <rtems/score/sysstate.h>
#include <rtems/score/heap.h>
-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 <string.h>
+
#include <rtems/system.h>
#include <rtems/score/sysstate.h>
#include <rtems/score/heap.h>
@@ -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;
}