source: rtems/cpukit/score/src/heapfree.c @ b72e847b

4.8
Last change on this file since b72e847b was 55d7626, checked in by Joel Sherrill <joel.sherrill@…>, on 07/11/07 at 20:56:10

2007-07-11 Joel Sherrill <joel.sherrill@…>

  • libcsupport/src/malloc.c: Clean up Malloc debug code.
  • score/include/rtems/score/heap.h: Spacing.
  • score/inline/rtems/score/thread.inl:
  • score/src/heapfree.c. Clean up and add explicit check of the address being freed actually being in the heap.
  • score/src/heapwalk.c: Switch to printk and do not call abort.
  • Property mode set to 100644
File size: 3.9 KB
Line 
1/*
2 *  Heap Handler
3 *
4 *  COPYRIGHT (c) 1989-2007.
5 *  On-Line Applications Research Corporation (OAR).
6 *
7 *  The license and distribution terms for this file may be
8 *  found in the file LICENSE in this distribution or at
9 *  http://www.rtems.com/license/LICENSE.
10 *
11 *  $Id$
12 */
13
14#if HAVE_CONFIG_H
15#include "config.h"
16#endif
17
18#include <rtems/system.h>
19#include <rtems/score/sysstate.h>
20#include <rtems/score/heap.h>
21
22/*PAGE
23 *
24 *  _Heap_Free
25 *
26 *  This kernel routine returns the memory designated by the
27 *  given heap and given starting address to the memory pool.
28 *
29 *  Input parameters:
30 *    the_heap         - pointer to heap header
31 *    starting_address - starting address of the memory block to free.
32 *
33 *  Output parameters:
34 *    TRUE  - if starting_address is valid heap address
35 *    FALSE - if starting_address is invalid heap address
36 */
37
38boolean _Heap_Free(
39  Heap_Control        *the_heap,
40  void                *starting_address
41)
42{
43  Heap_Block      *the_block;
44  Heap_Block      *next_block;
45  uint32_t         the_size;
46  uint32_t         next_size;
47  Heap_Statistics *const stats = &the_heap->stats;
48  boolean          next_is_free;
49
50  if ( !_Addresses_Is_in_range(
51       starting_address, (void *)the_heap->start, (void *)the_heap->final ) ) {
52    _HAssert(starting_address != NULL);
53    return( FALSE );
54  }
55
56  _Heap_Start_of_block( the_heap, starting_address, &the_block );
57
58  if ( !_Heap_Is_block_in( the_heap, the_block ) ) {
59    _HAssert( FALSE );
60    return( FALSE );
61  }
62
63  the_size = _Heap_Block_size( the_block );
64  next_block = _Heap_Block_at( the_block, the_size );
65
66  if ( !_Heap_Is_block_in( the_heap, next_block ) ) {
67    _HAssert( FALSE );
68    return( FALSE );
69  }
70
71  if ( !_Heap_Is_prev_used( next_block ) ) {
72    _HAssert( FALSE );
73    return( FALSE );
74  }
75
76  next_size = _Heap_Block_size( next_block );
77  next_is_free = next_block < the_heap->final &&
78    !_Heap_Is_prev_used(_Heap_Block_at(next_block, next_size));
79
80  if ( !_Heap_Is_prev_used( the_block ) ) {
81    uint32_t const prev_size = the_block->prev_size;
82    Heap_Block *const prev_block = _Heap_Block_at( the_block, -prev_size );
83
84    if ( !_Heap_Is_block_in( the_heap, prev_block ) ) {
85      _HAssert( FALSE );
86      return( FALSE );
87    }
88
89    /* As we always coalesce free blocks, the block that preceedes prev_block
90       must have been used. */
91    if ( !_Heap_Is_prev_used ( prev_block) ) {
92      _HAssert( FALSE );
93      return( FALSE );
94    }
95
96    if ( next_is_free ) {       /* coalesce both */
97      uint32_t const size = the_size + prev_size + next_size;
98      _Heap_Block_remove( next_block );
99      stats->free_blocks -= 1;
100      prev_block->size = size | HEAP_PREV_USED;
101      next_block = _Heap_Block_at( prev_block, size );
102      _HAssert(!_Heap_Is_prev_used( next_block));
103      next_block->prev_size = size;
104    }
105    else {                      /* coalesce prev */
106      uint32_t const size = the_size + prev_size;
107      prev_block->size = size | HEAP_PREV_USED;
108      next_block->size &= ~HEAP_PREV_USED;
109      next_block->prev_size = size;
110    }
111  }
112  else if ( next_is_free ) {    /* coalesce next */
113    uint32_t const size = the_size + next_size;
114    _Heap_Block_replace( next_block, the_block );
115    the_block->size = size | HEAP_PREV_USED;
116    next_block  = _Heap_Block_at( the_block, size );
117    next_block->prev_size = size;
118  }
119  else {                        /* no coalesce */
120    /* Add 'the_block' to the head of the free blocks list as it tends to
121       produce less fragmentation than adding to the tail. */
122    _Heap_Block_insert_after( _Heap_Head( the_heap), the_block );
123    the_block->size = the_size | HEAP_PREV_USED;
124    next_block->size &= ~HEAP_PREV_USED;
125    next_block->prev_size = the_size;
126
127    stats->free_blocks += 1;
128    if ( stats->max_free_blocks < stats->free_blocks )
129      stats->max_free_blocks = stats->free_blocks;
130  }
131
132  stats->used_blocks -= 1;
133  stats->free_size += the_size;
134  stats->frees += 1;
135
136  return( TRUE );
137}
Note: See TracBrowser for help on using the repository browser.