Index: cpukit/ChangeLog
===================================================================
--- cpukit/ChangeLog	(revision 1c6b22861bd606c814514b9326cb13b3b110fb28)
+++ cpukit/ChangeLog	(revision 518c2aeba262cdad2c58bf581c7a49c2966d6569)
@@ -1,2 +1,11 @@
+2009-09-09	Sebastian Huber <Sebastian.Huber@embedded-brains.de>
+
+	* score/include/rtems/score/heap.h, score/inline/rtems/score/heap.inl,
+	score/src/heapallocate.c, score/src/heap.c, score/src/heapextend.c,
+	score/src/heapresizeblock.c, score/src/heapwalk.c: Documenation.
+	Simplified block resize. Improved heap walk. Changed heap layout to
+	avoid a special case for _Heap_Is_used() and _Heap_Is_free().
+	* libmisc/stackchk/check.c: Update for heap API changes.
+
 2009-09-06	Ralf CorsÃ©pius <ralf.corsepius@rtems.org>
 
Index: cpukit/libmisc/stackchk/check.c
===================================================================
--- cpukit/libmisc/stackchk/check.c	(revision 1c6b22861bd606c814514b9326cb13b3b110fb28)
+++ cpukit/libmisc/stackchk/check.c	(revision 518c2aeba262cdad2c58bf581c7a49c2966d6569)
@@ -92,6 +92,13 @@
 
 #else
+  /*
+   * We need this magic offset because during a task delete the task stack will
+   * be freed before we enter the task switch extension which checks the stack.
+   * The task stack free operation will write the next and previous pointers
+   * for the free list into this area.
+   */
   #define Stack_check_Get_pattern_area( _the_stack ) \
-    ((Stack_check_Control *) ((char *)(_the_stack)->area + HEAP_BLOCK_HEADER_SIZE))
+    ((Stack_check_Control *) ((char *)(_the_stack)->area \
+      + sizeof(Heap_Block) - HEAP_BLOCK_HEADER_SIZE))
 
   #define Stack_check_Calculate_used( _low, _size, _high_water) \
Index: cpukit/score/include/rtems/score/heap.h
===================================================================
--- cpukit/score/include/rtems/score/heap.h	(revision 1c6b22861bd606c814514b9326cb13b3b110fb28)
+++ cpukit/score/include/rtems/score/heap.h	(revision 518c2aeba262cdad2c58bf581c7a49c2966d6569)
@@ -92,5 +92,5 @@
  * <table>
  *   <tr><th>Label</th><th colspan=2>Content</th></tr>
- *   <tr><td>heap->begin</td><td colspan=2>heap area begin address</td></tr>
+ *   <tr><td>heap->area_begin</td><td colspan=2>heap area begin address</td></tr>
  *   <tr>
  *     <td>first_block->prev_size</td>
@@ -109,12 +109,16 @@
  *   <tr><td>...</td></tr>
  *   <tr>
- *     <td>second_block->prev_size</td><td colspan=2>size of first block</td>
- *   </tr>
- *   <tr>
- *     <td>second_block->size</td>
- *     <td colspan=2>page size (the value is arbitrary)</td>
- *   </tr>
- *   <tr><td>heap->end</td><td colspan=2>heap area end address</td></tr>
+ *     <td>last_block->prev_size</td><td colspan=2>size of first block</td>
+ *   </tr>
+ *   <tr>
+ *     <td>last_block->size</td>
+ *     <td colspan=2>first block begin address - last block begin address</td>
+ *   </tr>
+ *   <tr><td>heap->area_end</td><td colspan=2>heap area end address</td></tr>
  * </table>
+ * 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.
  *
  * @{
@@ -206,15 +210,21 @@
 
   /**
-   * @brief The size of the memory for heap.
+   * @brief Size of the allocatable area in bytes.
+   *
+   * This value is an integral multiple of the page size.
    */
   uintptr_t size;
 
   /**
-   * @brief Current free size.
+   * @brief Current free size in bytes.
+   *
+   * This value is an integral multiple of the page size.
    */
   uintptr_t free_size;
 
   /**
-   * @brief Minimum free size ever.
+   * @brief Minimum free size ever in bytes.
+   *
+   * This value is an integral multiple of the page size.
    */
   uintptr_t min_free_size;
@@ -241,5 +251,5 @@
 
   /**
-   * @brief Total number of successful calls to alloc.
+   * @brief Total number of successful allocations.
    */
   uint32_t allocs;
@@ -355,5 +365,5 @@
 
 /**
- * @brief Allocates a memory area of size @a size bytes.
+ * @brief Allocates a memory area of size @a size bytes from the heap @a heap.
  *
  * If the alignment parameter @a alignment is not equal to zero, the allocated
@@ -379,9 +389,24 @@
 );
 
-#define _Heap_Allocate_aligned( heap, size, alignment ) \
-  _Heap_Allocate_aligned_with_boundary( heap, size, alignment, 0 )
-
-#define _Heap_Allocate( heap, size ) \
-  _Heap_Allocate_aligned_with_boundary( heap, size, 0, 0 )
+/**
+ * @brief See _Heap_Allocate_aligned_with_boundary() with boundary equals zero.
+ */
+RTEMS_INLINE_ROUTINE void *_Heap_Allocate_aligned(
+  Heap_Control *heap,
+  uintptr_t size,
+  uintptr_t alignment
+)
+{
+  return _Heap_Allocate_aligned_with_boundary( heap, size, alignment, 0 );
+}
+
+/**
+ * @brief See _Heap_Allocate_aligned_with_boundary() with alignment and
+ * boundary equals zero.
+ */
+RTEMS_INLINE_ROUTINE void *_Heap_Allocate( Heap_Control *heap, uintptr_t size )
+{
+  return _Heap_Allocate_aligned_with_boundary( heap, size, 0, 0 );
+}
 
 /**
@@ -474,5 +499,9 @@
  * @a alloc_size bytes in the block @a block.
  *
- * The block may be split up into multiple blocks.
+ * The block may be split up into multiple blocks.  The previous and next block
+ * may be used or free.  Free block parts which form a vaild new block will be
+ * inserted into the free list or merged with an adjacent free block.  If the
+ * block is used, they will be inserted after the free list head.  If the block
+ * is free, they will be inserted after the previous block in the free list.
  *
  * Inappropriate values for @a alloc_begin or @a alloc_size may corrupt the
Index: cpukit/score/inline/rtems/score/heap.inl
===================================================================
--- cpukit/score/inline/rtems/score/heap.inl	(revision 1c6b22861bd606c814514b9326cb13b3b110fb28)
+++ cpukit/score/inline/rtems/score/heap.inl	(revision 518c2aeba262cdad2c58bf581c7a49c2966d6569)
@@ -124,9 +124,16 @@
  */
 RTEMS_INLINE_ROUTINE Heap_Block *_Heap_Block_at(
-  Heap_Block *block,
+  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);
 }
 
@@ -147,4 +154,19 @@
 }
 
+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 )
 {
@@ -152,7 +174,19 @@
 }
 
-RTEMS_INLINE_ROUTINE uintptr_t _Heap_Block_size( 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 );
 }
 
@@ -167,9 +201,11 @@
 
 /**
- * @brief Returns the heap area size.
+ * @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->area_end - heap->area_begin;
+  return heap->stats.size;
 }
 
Index: cpukit/score/src/heap.c
===================================================================
--- cpukit/score/src/heap.c	(revision 1c6b22861bd606c814514b9326cb13b3b110fb28)
+++ cpukit/score/src/heap.c	(revision 518c2aeba262cdad2c58bf581c7a49c2966d6569)
@@ -141,5 +141,5 @@
   uintptr_t overhead = 0;
   Heap_Block *first_block = NULL;
-  Heap_Block *second_block = NULL;
+  Heap_Block *last_block = NULL;
 
   if ( page_size == 0 ) {
@@ -147,4 +147,9 @@
   } else {
     page_size = _Heap_Align_up( page_size, CPU_ALIGNMENT );
+
+    if ( page_size < CPU_ALIGNMENT ) {
+      /* Integer overflow */
+      return 0;
+    }
   }
   min_block_size = _Heap_Align_up( sizeof( Heap_Block ), page_size );
@@ -173,8 +178,15 @@
   first_block->prev = _Heap_Free_list_head( heap );
 
-  /* Second and last block */
-  second_block = _Heap_Block_at( first_block, first_block_size );
-  second_block->prev_size = first_block_size;
-  second_block->size_and_flag = page_size;
+  /*
+   * 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 */
@@ -184,10 +196,10 @@
   heap->area_end = heap_area_end;
   heap->first_block = first_block;
-  heap->last_block = second_block;
+  heap->last_block = last_block;
   _Heap_Free_list_head( heap )->next = first_block;
   _Heap_Free_list_tail( heap )->prev = first_block;
 
   /* Statistics */
-  stats->size = heap_area_size;
+  stats->size = first_block_size;
   stats->free_size = first_block_size;
   stats->min_free_size = first_block_size;
@@ -209,20 +221,19 @@
   );
   _HAssert(
-    _Heap_Is_aligned( _Heap_Alloc_area_of_block( second_block ), page_size )
+    _Heap_Is_aligned( _Heap_Alloc_area_of_block( last_block ), page_size )
   );
-
-  if ( !_Heap_Walk( heap, 0, false ) ) {
-    _Heap_Walk( heap, 0, true );
-  }
 
   return alloc_area_size;
 }
 
-static Heap_Block *_Heap_Block_split(
+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;
@@ -238,5 +249,5 @@
   uintptr_t const free_size_limit = min_block_size + HEAP_BLOCK_SIZE_OFFSET;
 
-  Heap_Block *const next_block = _Heap_Block_at( block, block_size );
+  Heap_Block *next_block = _Heap_Block_at( block, block_size );
 
   _HAssert( used_size <= block_size + HEAP_BLOCK_SIZE_OFFSET );
@@ -244,19 +255,35 @@
 
   if ( free_size >= free_size_limit ) {
-    uintptr_t const free_block_size = block_size - used_block_size;
     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 );
 
-    block->size_and_flag = used_block_size
-      | (block->size_and_flag & HEAP_PREV_BLOCK_USED);
+    _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;
-
-    return free_block;
+    next_block->size_and_flag &= ~HEAP_PREV_BLOCK_USED;
   } else {
     next_block->size_and_flag |= HEAP_PREV_BLOCK_USED;
-
-    return NULL;
   }
 }
@@ -265,19 +292,9 @@
   Heap_Control *heap,
   Heap_Block *block,
+  Heap_Block *free_list_anchor,
   uintptr_t alloc_size
 )
 {
-  Heap_Block *const free_block = _Heap_Block_split( heap, block, alloc_size );
-
-  if ( free_block != NULL ) {
-    _Heap_Free_list_replace( block, free_block );
-  } else {
-    Heap_Statistics *const stats = &heap->stats;
-
-    _Heap_Free_list_remove( block );
-
-    /* Statistics */
-    --stats->free_blocks;
-  }
+  _Heap_Block_split( heap, block, free_list_anchor, alloc_size );
 
   return block;
@@ -287,9 +304,12 @@
   Heap_Control *heap,
   Heap_Block *block,
+  Heap_Block *free_list_anchor,
   uintptr_t alloc_begin,
   uintptr_t alloc_size
 )
 {
-  uintptr_t const block_begin = (uintptr_t) block;
+  Heap_Statistics *const stats = &heap->stats;
+
+  uintptr_t block_begin = (uintptr_t) block;
   uintptr_t block_size = _Heap_Block_size( block );
   uintptr_t block_end = block_begin + block_size;
@@ -300,6 +320,4 @@
   uintptr_t const new_block_size = block_end - new_block_begin;
 
-  Heap_Block *free_block = NULL;
-
   block_end = new_block_begin;
   block_size = block_end - block_begin;
@@ -308,12 +326,29 @@
   _HAssert( new_block_size >= heap->min_block_size );
 
+  /* Statistics */
+  stats->free_size += block_size;
+
+  if ( _Heap_Is_prev_used( block ) ) {
+    _Heap_Free_list_insert_after( free_list_anchor, block );
+
+    free_list_anchor = block;
+
+    /* Statistics */
+    ++stats->free_blocks;
+  } else {
+    Heap_Block *const prev_block = _Heap_Prev_block( block );
+    uintptr_t const prev_block_size = _Heap_Block_size( prev_block );
+
+    block = prev_block;
+    block_begin = (uintptr_t) block;
+    block_size += prev_block_size;
+  }
+
   block->size_and_flag = block_size | HEAP_PREV_BLOCK_USED;
+
   new_block->prev_size = block_size;
   new_block->size_and_flag = new_block_size;
 
-  free_block = _Heap_Block_split( heap, new_block, alloc_size );
-  if ( free_block != NULL ) {
-    _Heap_Free_list_insert_after( block, free_block );
-  }
+  _Heap_Block_split( heap, new_block, free_list_anchor, alloc_size );
 
   return new_block;
@@ -328,21 +363,45 @@
 {
   Heap_Statistics *const stats = &heap->stats;
+
   uintptr_t const alloc_area_begin = _Heap_Alloc_area_of_block( block );
   uintptr_t const alloc_area_offset = alloc_begin - alloc_area_begin;
 
-  _HAssert( _Heap_Is_prev_used( block ) );
+  Heap_Block *free_list_anchor = NULL;
+
   _HAssert( alloc_area_begin <= alloc_begin );
+
+  if ( _Heap_Is_free( block ) ) {
+    free_list_anchor = block->prev;
+
+    _Heap_Free_list_remove( block );
+
+    /* Statistics */
+    --stats->free_blocks;
+    ++stats->used_blocks;
+    stats->free_size -= _Heap_Block_size( block );
+  } else {
+    free_list_anchor = _Heap_Free_list_head( heap );
+  }
 
   if ( alloc_area_offset < heap->page_size ) {
     alloc_size += alloc_area_offset;
 
-    block = _Heap_Block_allocate_from_begin( heap, block, alloc_size );
+    block = _Heap_Block_allocate_from_begin(
+      heap,
+      block,
+      free_list_anchor,
+      alloc_size
+    );
   } else {
-    block = _Heap_Block_allocate_from_end( heap, block, alloc_begin, alloc_size );
+    block = _Heap_Block_allocate_from_end(
+      heap,
+      block,
+      free_list_anchor,
+      alloc_begin,
+      alloc_size
+    );
   }
 
   /* Statistics */
-  ++stats->used_blocks;
-  stats->free_size -= _Heap_Block_size( block );
   if ( stats->min_free_size > stats->free_size ) {
     stats->min_free_size = stats->free_size;
Index: cpukit/score/src/heapallocate.c
===================================================================
--- cpukit/score/src/heapallocate.c	(revision 1c6b22861bd606c814514b9326cb13b3b110fb28)
+++ cpukit/score/src/heapallocate.c	(revision 518c2aeba262cdad2c58bf581c7a49c2966d6569)
@@ -49,5 +49,4 @@
     uintptr_t const alloc_area_begin = _Heap_Alloc_area_of_block( block );
     uintptr_t const alloc_area_offset = alloc_begin - alloc_area_begin;
-    uintptr_t const alloc_area_size = alloc_area_offset + alloc_size;
 
     _HAssert( block_size >= min_block_size );
@@ -207,4 +206,7 @@
 
   if ( alloc_begin != 0 ) {
+    /* Statistics */
+    stats->searches += search_count;
+
     block = _Heap_Block_allocate( heap, block, alloc_begin, alloc_size );
 
@@ -217,7 +219,4 @@
       boundary
     );
-
-    /* Statistics */
-    stats->searches += search_count;
   }
 
Index: cpukit/score/src/heapextend.c
===================================================================
--- cpukit/score/src/heapextend.c	(revision 1c6b22861bd606c814514b9326cb13b3b110fb28)
+++ cpukit/score/src/heapextend.c	(revision 518c2aeba262cdad2c58bf581c7a49c2966d6569)
@@ -39,6 +39,5 @@
   uintptr_t const new_heap_area_end = heap_area_end + area_size;
   uintptr_t extend_size = 0;
-  Heap_Block *const old_final = heap->last_block;
-  Heap_Block *new_final = NULL;
+  Heap_Block *const last_block = heap->last_block;
 
   /*
@@ -70,5 +69,5 @@
 
   extend_size = new_heap_area_end
-    - (uintptr_t) old_final - HEAP_BLOCK_HEADER_SIZE;
+    - (uintptr_t) last_block - HEAP_BLOCK_HEADER_SIZE;
   extend_size = _Heap_Align_down( extend_size, heap->page_size );
 
@@ -76,16 +75,20 @@
 
   if( extend_size >= heap->min_block_size ) {
-    old_final->size_and_flag = extend_size
-      | (old_final->size_and_flag & HEAP_PREV_BLOCK_USED);
-    new_final = _Heap_Block_at( old_final, extend_size );
-    new_final->size_and_flag = heap->page_size | HEAP_PREV_BLOCK_USED;
+    Heap_Block *const new_last_block = _Heap_Block_at( last_block, extend_size );
 
-    heap->last_block = new_final;
+    _Heap_Block_set_size( last_block, extend_size );
 
-    stats->size += area_size;
+    new_last_block->size_and_flag =
+      ((uintptr_t) heap->first_block - (uintptr_t) new_last_block)
+        | HEAP_PREV_BLOCK_USED;
+
+    heap->last_block = new_last_block;
+
+    /* Statistics */
+    stats->size += extend_size;
     ++stats->used_blocks;
     --stats->frees; /* Do not count subsequent call as actual free() */
 
-    _Heap_Free( heap, (void *) _Heap_Alloc_area_of_block( old_final ));
+    _Heap_Free( heap, (void *) _Heap_Alloc_area_of_block( last_block ));
   }
 
Index: cpukit/score/src/heapresizeblock.c
===================================================================
--- cpukit/score/src/heapresizeblock.c	(revision 1c6b22861bd606c814514b9326cb13b3b110fb28)
+++ cpukit/score/src/heapresizeblock.c	(revision 518c2aeba262cdad2c58bf581c7a49c2966d6569)
@@ -10,4 +10,6 @@
  *  COPYRIGHT (c) 1989-1999.
  *  On-Line Applications Research Corporation (OAR).
+ *
+ *  Copyright (c) 2009 embedded brains GmbH.
  *
  *  The license and distribution terms for this file may be
@@ -26,4 +28,64 @@
 #include <rtems/score/heap.h>
 
+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_BLOCK_SIZE_OFFSET;
+
+  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_BLOCK_SIZE_OFFSET;
+
+  /* Statistics */
+  ++stats->resizes;
+
+  return HEAP_RESIZE_SUCCESSFUL;
+}
+
 Heap_Resize_status _Heap_Resize_block(
   Heap_Control *heap,
@@ -34,156 +96,24 @@
 )
 {
-  Heap_Statistics *const stats = &heap->stats;
-  uintptr_t const min_block_size = heap->min_block_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 );
-  Heap_Block *next_block = NULL;
-  Heap_Block *next_next_block = NULL;
-  uintptr_t block_size = 0;
-  uintptr_t block_end = 0;
-  uintptr_t next_block_size = 0;
-  bool next_block_is_used = false;;
-  uintptr_t alloc_size = 0;
-  uintptr_t prev_block_used_flag = 0;
 
   *old_size = 0;
   *new_size = 0;
 
-  if ( !_Heap_Is_block_in_heap( heap, block ) ) {
+  if ( _Heap_Is_block_in_heap( heap, block ) ) {
+    return _Heap_Resize_block_checked(
+      heap,
+      block,
+      alloc_begin,
+      new_alloc_size,
+      old_size,
+      new_size
+    );
+  } else {
     return HEAP_RESIZE_FATAL_ERROR;
   }
-
-  block_size = _Heap_Block_size( block );
-  block_end = (uintptr_t) block + block_size;
-  prev_block_used_flag = block->size_and_flag & HEAP_PREV_BLOCK_USED;
-  next_block = _Heap_Block_at( block, block_size );
-
-  _HAssert( _Heap_Is_block_in_heap( heap, next_block ) );
-  _HAssert( _Heap_Is_prev_used( next_block ) );
-
-  next_block_size = _Heap_Block_size( next_block );
-  next_next_block = _Heap_Block_at( next_block, next_block_size );
-
-  _HAssert(
-    next_block == heap->last_block
-      || _Heap_Is_block_in_heap( heap, next_next_block )
-  );
-
-  next_block_is_used = next_block == heap->last_block
-    || _Heap_Is_prev_used( next_next_block );
-
-  alloc_size = block_end - alloc_begin + HEAP_BLOCK_SIZE_OFFSET;
-
-  *old_size = alloc_size;
-
-  if ( new_alloc_size > alloc_size ) {
-    /*
-     * Need to extend the block: allocate part of the next block and then
-     * merge the blocks.
-     */
-    if ( next_block_is_used ) {
-      return HEAP_RESIZE_UNSATISFIED;
-    } else {
-      uintptr_t add_block_size =
-        _Heap_Align_up( new_alloc_size - alloc_size, page_size );
-
-      if ( add_block_size < min_block_size ) {
-        add_block_size = min_block_size;
-      }
-
-      if ( add_block_size > next_block_size ) {
-        return HEAP_RESIZE_UNSATISFIED;
-      }
-
-      next_block = _Heap_Block_allocate(
-        heap,
-        next_block,
-        _Heap_Alloc_area_of_block( next_block ),
-        add_block_size - HEAP_BLOCK_HEADER_SIZE
-      );
-
-      /* Merge the blocks */
-      block->size_and_flag = ( block_size + _Heap_Block_size( next_block ) )
-        | prev_block_used_flag;
-
-      /* Statistics */
-      --stats->used_blocks;
-    }
-  } else {
-    /* Calculate how much memory we could free */
-    uintptr_t free_block_size =
-      _Heap_Align_down( alloc_size - new_alloc_size, page_size );
-
-    if ( free_block_size > 0 ) {
-      /*
-       * To free some memory the block should be shortened so that it can can
-       * hold 'new_alloc_size' user bytes and still remain not shorter than
-       * 'min_block_size'. 
-       */
-      uintptr_t new_block_size = block_size - free_block_size;
-
-      if ( new_block_size < min_block_size ) {
-        uintptr_t const delta = min_block_size - new_block_size;
-
-        _HAssert( free_block_size >= delta );
-
-        free_block_size -= delta;
-
-        if ( free_block_size == 0 ) {
-          /* Statistics */
-          ++stats->resizes;
-
-          return HEAP_RESIZE_SUCCESSFUL;
-        }
-
-        new_block_size += delta;
-      }
-
-      _HAssert( new_block_size >= min_block_size );
-      _HAssert( new_block_size + free_block_size == block_size );
-      _HAssert( _Heap_Is_aligned( new_block_size, page_size ) );
-      _HAssert( _Heap_Is_aligned( free_block_size, page_size ) );
-
-      if ( !next_block_is_used ) {
-        /* Extend the next block */
-        Heap_Block *const new_next_block =
-          _Heap_Block_at( block, new_block_size );
-        uintptr_t const new_next_block_size =
-          next_block_size + free_block_size;
-
-        _HAssert( _Heap_Is_block_in_heap( heap, next_next_block ) );
-
-        block->size_and_flag = new_block_size | prev_block_used_flag;
-        new_next_block->size_and_flag =
-          new_next_block_size | HEAP_PREV_BLOCK_USED;
-        next_next_block->prev_size = new_next_block_size;
-
-        _Heap_Free_list_replace( next_block, new_next_block );
-
-        *new_size = new_next_block_size - HEAP_BLOCK_SIZE_OFFSET;
-
-        /* Statistics */
-        stats->free_size += free_block_size;
-      } else if ( free_block_size >= min_block_size ) {
-        /* Split the block into two used parts, then free the second one */
-        block->size_and_flag = new_block_size | prev_block_used_flag;
-        next_block = _Heap_Block_at( block, new_block_size );
-        next_block->size_and_flag = free_block_size | HEAP_PREV_BLOCK_USED;
-
-        _Heap_Free( heap, (void *) _Heap_Alloc_area_of_block( next_block ) );
-
-        *new_size = free_block_size - HEAP_BLOCK_SIZE_OFFSET;
-
-        /* Statistics */
-        ++stats->used_blocks; /* We have created used block */
-        --stats->frees; /* Do not count next call in stats */
-      }
-    }
-  }
-
-  /* Statistics */
-  ++stats->resizes;
-
-  return HEAP_RESIZE_SUCCESSFUL;
 }
Index: cpukit/score/src/heapwalk.c
===================================================================
--- cpukit/score/src/heapwalk.c	(revision 1c6b22861bd606c814514b9326cb13b3b110fb28)
+++ cpukit/score/src/heapwalk.c	(revision 518c2aeba262cdad2c58bf581c7a49c2966d6569)
@@ -52,14 +52,11 @@
 )
 {
+  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;
-  uintptr_t const page_size = heap->page_size;
-  uintptr_t const loop_limit =
-    ((uintptr_t) heap->last_block - (uintptr_t) heap->first_block)
-      / heap->min_block_size;
-  uintptr_t loop_counter = 0;
-
-  while ( free_block != free_list_tail && loop_counter < loop_limit ) {
+
+  while ( free_block != free_list_tail ) {
     if ( !_Heap_Is_block_in_heap( heap, free_block ) ) {
       _Heap_Walk_printk(
@@ -88,18 +85,31 @@
     }
 
-    ++loop_counter;
-
+    if ( _Heap_Is_used( free_block ) ) {
+      _Heap_Walk_printk(
+        source,
+        dump,
+        true,
+        "free block 0x%08x: is used\n",
+        free_block
+      );
+
+      return false;
+    }
+
+    if ( free_block->prev != prev_block ) {
+      _Heap_Walk_printk(
+        source,
+        dump,
+        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;
-  }
-
-  if ( loop_counter >= loop_limit ) {
-    _Heap_Walk_printk(
-      source,
-      dump,
-      true,
-      "free list contains a loop\n"
-    );
-
-    return false;
   }
 
@@ -133,6 +143,4 @@
   uintptr_t const page_size = heap->page_size;
   uintptr_t const min_block_size = heap->min_block_size;
-  Heap_Block *const free_list_tail = _Heap_Free_list_tail( heap );
-  Heap_Block *const free_list_head = _Heap_Free_list_head( heap );
   Heap_Block *const first_free_block = _Heap_Free_list_first( heap );
   Heap_Block *const last_free_block = _Heap_Free_list_last( heap );
@@ -185,34 +193,4 @@
 
   if (
-    first_free_block != free_list_head
-      && !_Addresses_Is_aligned( first_free_block )
-  ) {
-    _Heap_Walk_printk(
-      source,
-      dump,
-      true,
-      "first free block: 0x%08x not CPU aligned\n",
-      first_free_block
-    );
-
-    return false;
-  }
-
-  if (
-    last_free_block != free_list_tail
-      && !_Addresses_Is_aligned( last_free_block )
-  ) {
-    _Heap_Walk_printk(
-      source,
-      dump,
-      true,
-      "last free block: 0x%08x not CPU aligned\n",
-      last_free_block
-    );
-    
-    return false;
-  }
-
-  if (
     !_Heap_Is_aligned( _Heap_Alloc_area_of_block( first_block ), page_size )
   ) {
@@ -221,5 +199,5 @@
       dump,
       true,
-      "first block: 0x%08x not page aligned\n",
+      "first block 0x%08x: alloc area not page aligned\n",
       first_block
     );
@@ -228,18 +206,4 @@
   }
 
-  if (
-    !_Heap_Is_aligned( _Heap_Alloc_area_of_block( last_block ), page_size )
-  ) {
-    _Heap_Walk_printk(
-      source,
-      dump,
-      true,
-      "last block: 0x%08x not page aligned\n",
-      last_block
-    );
-
-    return false;
-  }
-
   if ( !_Heap_Is_prev_used( first_block ) ) {
     _Heap_Walk_printk(
@@ -249,4 +213,6 @@
       "first block: HEAP_PREV_BLOCK_USED is cleared\n"
     );
+
+    return false;
   }
 
@@ -260,7 +226,93 @@
       page_size
     );
+
+    return false;
+  }
+
+  if ( _Heap_Is_free( last_block ) ) {
+    _Heap_Walk_printk(
+      source,
+      dump,
+      true,
+      "last block: is free\n"
+    );
+
+    return false;
   }
 
   return _Heap_Walk_check_free_list( source, dump, heap );
+}
+
+static bool _Heap_Walk_check_free_block(
+  int source,
+  bool dump,
+  Heap_Control *heap,
+  Heap_Block *block
+)
+{
+  Heap_Block *const free_list_tail = _Heap_Free_list_tail( heap );
+  Heap_Block *const free_list_head = _Heap_Free_list_head( heap );
+  Heap_Block *const first_free_block = _Heap_Free_list_first( heap );
+  Heap_Block *const last_free_block = _Heap_Free_list_last( heap );
+  bool const prev_used = _Heap_Is_prev_used( block );
+  uintptr_t const block_size = _Heap_Block_size( block );
+  Heap_Block *const next_block = _Heap_Block_at( block, block_size );
+
+  _Heap_Walk_printk(
+    source,
+    dump,
+    false,
+    "block 0x%08x: prev 0x%08x%s, next 0x%08x%s\n",
+    block,
+    block->prev,
+    block->prev == first_free_block ?
+      " (= first)"
+        : (block->prev == free_list_head ? " (= head)" : ""),
+    block->next,
+    block->next == last_free_block ?
+      " (= last)"
+        : (block->next == free_list_tail ? " (= tail)" : "")
+  );
+
+  if ( block_size != next_block->prev_size ) {
+    _Heap_Walk_printk(
+      source,
+      dump,
+      true,
+      "block 0x%08x: size %u != size %u (in next block 0x%08x)\n",
+      block,
+      block_size,
+      next_block->prev_size,
+      next_block
+    );
+
+    return false;
+  }
+
+  if ( !prev_used ) {
+    _Heap_Walk_printk(
+      source,
+      dump,
+      true,
+      "block 0x%08x: two consecutive blocks are free\n",
+      block
+    );
+
+    return false;
+  }
+
+  if ( !_Heap_Walk_is_in_free_list( heap, block ) ) {
+    _Heap_Walk_printk(
+      source,
+      dump,
+      true,
+      "block 0x%08x: free block not in free list\n",
+      block
+    );
+
+    return false;
+  }
+
+  return true;
 }
 
@@ -273,11 +325,6 @@
   uintptr_t const page_size = heap->page_size;
   uintptr_t const min_block_size = heap->min_block_size;
-  Heap_Block *const free_list_tail = _Heap_Free_list_tail( heap );
-  Heap_Block *const free_list_head = _Heap_Free_list_head( heap );
-  Heap_Block *const first_free_block = _Heap_Free_list_first( heap );
-  Heap_Block *const last_free_block = _Heap_Free_list_last( heap );
   Heap_Block *const last_block = heap->last_block;
   Heap_Block *block = heap->first_block;
-  bool error = false;
 
   if ( !_System_state_Is_up( _System_state_Get() ) ) {
@@ -289,5 +336,5 @@
   }
 
-  while ( block != last_block && _Addresses_Is_aligned( block ) ) {
+  while ( block != last_block ) {
     uintptr_t const block_begin = (uintptr_t) block;
     uintptr_t const block_size = _Heap_Block_size( block );
@@ -300,5 +347,5 @@
         source,
         dump,
-        error,
+        false,
         "block 0x%08x: size %u\n",
         block,
@@ -309,5 +356,5 @@
         source,
         dump,
-        error,
+        false,
         "block 0x%08x: size %u, prev_size %u\n",
         block,
@@ -317,39 +364,35 @@
     }
 
-    if (
-      !_Heap_Is_aligned( block_begin + HEAP_BLOCK_HEADER_SIZE, page_size )
-    ) {
-      error = true;
-      _Heap_Walk_printk(
-        source,
-        dump,
-        error,
-        "block 0x%08x: not page (%u) aligned\n",
-        block,
-        page_size
-      );
-      break;
+    if ( !_Heap_Is_block_in_heap( heap, next_block ) ) {
+      _Heap_Walk_printk(
+        source,
+        dump,
+        true,
+        "block 0x%08x: next block 0x%08x not in heap\n",
+        block,
+        next_block
+      );
+      
+      return false;
     }
 
     if ( !_Heap_Is_aligned( block_size, page_size ) ) {
-      error = true;
-      _Heap_Walk_printk(
-        source,
-        dump,
-        error,
-        "block 0x%08x: block size %u not page (%u) aligned\n",
-        block,
-        block_size,
-        page_size
-      );
-      break;
+      _Heap_Walk_printk(
+        source,
+        dump,
+        true,
+        "block 0x%08x: block size %u not page aligned\n",
+        block,
+        block_size
+      );
+      
+      return false;
     }
 
     if ( block_size < min_block_size ) {
-      error = true;
-      _Heap_Walk_printk(
-        source,
-        dump,
-        error,
+      _Heap_Walk_printk(
+        source,
+        dump,
+        true,
         "block 0x%08x: size %u < min block size %u\n",
         block,
@@ -357,72 +400,25 @@
         min_block_size
       );
-      break;
+      
+      return false;
     }
 
     if ( next_block_begin <= block_begin ) {
-      error = true;
-      _Heap_Walk_printk(
-        source,
-        dump,
-        error,
+      _Heap_Walk_printk(
+        source,
+        dump,
+        true,
         "block 0x%08x: next block 0x%08x is not a successor\n",
         block,
         next_block
       );
-      break;
+      
+      return false;
     }
    
     if ( !_Heap_Is_prev_used( next_block ) ) {
-      _Heap_Walk_printk(
-        source,
-        dump,
-        error,
-        "block 0x%08x: prev 0x%08x%s, next 0x%08x%s\n",
-        block,
-        block->prev,
-        block->prev == first_free_block ?
-          " (= first)"
-            : (block->prev == free_list_head ? " (= head)" : ""),
-        block->next,
-        block->next == last_free_block ?
-          " (= last)"
-            : (block->next == free_list_tail ? " (= tail)" : "")
-      );
-
-      if ( block_size != next_block->prev_size ) {
-        error = true;
-        _Heap_Walk_printk(
-          source,
-          dump,
-          error,
-          "block 0x%08x: size %u != size %u (in next block 0x%08x)\n",
-          block,
-          block_size,
-          next_block->prev_size,
-          next_block
-        );
+      if ( !_Heap_Walk_check_free_block( source, dump, heap, block ) ) {
+        return false;
       }
-
-      if ( !prev_used ) {
-        error = true;
-        _Heap_Walk_printk(
-          source,
-          dump,
-          error,
-          "block 0x%08x: two consecutive blocks are free\n",
-          block
-        );
-      }
-
-      if ( !_Heap_Walk_is_in_free_list( heap, block ) ) {
-        error = true;
-        _Heap_Walk_printk(
-          source,
-          dump,
-          error,
-          "block 0x%08x: free block not in free list\n",
-          block
-        );
-      }
     }
 
@@ -430,44 +426,4 @@
   }
 
-  if ( !_Addresses_Is_aligned( block ) ) {
-    error = true;
-    _Heap_Walk_printk(
-      source,
-      dump,
-      error,
-      "block 0x%08x: not CPU aligned\n",
-      block
-    );
-
-    return false;
-  }
-
-  if ( block == last_block ) {
-    uintptr_t const block_size = _Heap_Block_size( block );
-
-    if ( block_size != page_size ) {
-      error = true;
-      _Heap_Walk_printk(
-        source,
-        dump,
-        error,
-        "last block 0x%08x: size %u != page size %u\n",
-        block,
-        block_size,
-        page_size
-      );
-    }
-  } else {
-    error = true;
-    _Heap_Walk_printk(
-      source,
-      dump,
-      error,
-      "last block 0x%08x != last block 0x%08x\n",
-      block,
-      last_block
-    );
-  }
-
-  return !error;
-}
+  return true;
+}
