source: rtems/cpukit/score/src/heapfree.c @ 962e894f

4.104.114.84.95
Last change on this file since 962e894f was 962e894f, checked in by Joel Sherrill <joel.sherrill@…>, on 01/20/05 at 18:22:29

2005-01-20 Sergei Organov <osv@…>

PR 536/rtems
Heap manager re-implementation to consume less memory and still satisfy
alignment requirements.


  • score/src/heap.c, score/src/heapallocate.c, score/src/heapextend.c, score/src/heapfree.c, score/src/heapgetinfo.c, score/src/heapgetfreeinfo.c, core/src/heapsizeofuserarea.c, score/src/heapwalk.c, core/macros/rtems/score/heap.inl, score/inline/rtems/score/heap.inl, score/include/rtems/score/heap.h: Reimplemented.
  • score/src/heapallocatealigned.c: new file
  • score/Makefile.am: HEAP_C_FILES: add score/src/heapallocatealigned.c
  • Property mode set to 100644
File size: 3.7 KB
Line 
1/*
2 *  Heap Handler
3 *
4 *  COPYRIGHT (c) 1989-1999.
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
15#include <rtems/system.h>
16#include <rtems/score/sysstate.h>
17#include <rtems/score/heap.h>
18
19/*PAGE
20 *
21 *  _Heap_Free
22 *
23 *  This kernel routine returns the memory designated by the
24 *  given heap and given starting address to the memory pool.
25 *
26 *  Input parameters:
27 *    the_heap         - pointer to heap header
28 *    starting_address - starting address of the memory block to free.
29 *
30 *  Output parameters:
31 *    TRUE  - if starting_address is valid heap address
32 *    FALSE - if starting_address is invalid heap address
33 */
34
35boolean _Heap_Free(
36  Heap_Control        *the_heap,
37  void                *starting_address
38)
39{
40  Heap_Block        *the_block;
41  Heap_Block        *next_block;
42  uint32_t         the_size;
43  uint32_t         next_size;
44  Heap_Statistics *const stats = &the_heap->stats;
45  boolean            next_is_free;
46
47  _Heap_Start_of_block( the_heap, starting_address, &the_block );
48
49  if ( !_Heap_Is_block_in( the_heap, the_block ) ) {
50    _HAssert(starting_address == NULL);
51    return( FALSE );
52  }
53
54  the_size = _Heap_Block_size( the_block );
55  next_block = _Heap_Block_at( the_block, the_size );
56
57  if ( !_Heap_Is_prev_used( next_block ) ) {
58    _HAssert(FALSE);
59    return( FALSE );
60  }
61
62  if ( !_Heap_Is_block_in( the_heap, next_block ) ) {
63    _HAssert(FALSE);
64    return( FALSE );
65  }
66
67  next_size = _Heap_Block_size( next_block );
68  next_is_free = next_block < the_heap->final &&
69    !_Heap_Is_prev_used(_Heap_Block_at(next_block, next_size));
70
71  if ( !_Heap_Is_prev_used( the_block ) ) {
72    uint32_t const prev_size = the_block->prev_size;
73    Heap_Block *const prev_block = _Heap_Block_at( the_block, -prev_size );
74
75    if ( !_Heap_Is_block_in( the_heap, prev_block ) ) {
76      _HAssert(FALSE);
77      return( FALSE );
78    }
79
80    /* As we always coalesce free blocks, the block that preceedes prev_block
81       must have been used. */
82    if ( !_Heap_Is_prev_used ( prev_block) ) {
83      _HAssert(FALSE);
84      return( FALSE );
85    }
86
87    if ( next_is_free ) {       /* coalesce both */
88      uint32_t const size = the_size + prev_size + next_size;
89      _Heap_Block_remove( next_block );
90      stats->free_blocks -= 1;
91      prev_block->size = size | HEAP_PREV_USED;
92      next_block = _Heap_Block_at( prev_block, size );
93      _HAssert(!_Heap_Is_prev_used( next_block));
94      next_block->prev_size = size;
95    }
96    else {                      /* coalesce prev */
97      uint32_t const size = the_size + prev_size;
98      prev_block->size = size | HEAP_PREV_USED;
99      next_block->size &= ~HEAP_PREV_USED;
100      next_block->prev_size = size;
101    }
102  }
103  else if ( next_is_free ) {    /* coalesce next */
104    uint32_t const size = the_size + next_size;
105    _Heap_Block_replace( next_block, the_block );
106    the_block->size = size | HEAP_PREV_USED;
107    next_block  = _Heap_Block_at( the_block, size );
108    next_block->prev_size = size;
109  }
110  else {                        /* no coalesce */
111    /* Add 'the_block' to the head of the free blocks list as it tends to
112       produce less fragmentation than adding to the tail. */
113    _Heap_Block_insert_after( _Heap_Head( the_heap), the_block );
114    the_block->size = the_size | HEAP_PREV_USED;
115    next_block->size &= ~HEAP_PREV_USED;
116    next_block->prev_size = the_size;
117
118    stats->free_blocks += 1;
119    if ( stats->max_free_blocks < stats->free_blocks )
120      stats->max_free_blocks = stats->free_blocks;
121  }
122
123  stats->used_blocks -= 1;
124  stats->free_size += the_size;
125  stats->frees += 1;
126
127  return( TRUE );
128}
Note: See TracBrowser for help on using the repository browser.