source: rtems/cpukit/score/src/heapallocate.c @ 9b4422a2

4.115
Last change on this file since 9b4422a2 was 9b4422a2, checked in by Joel Sherrill <joel.sherrill@…>, on 05/03/12 at 15:09:24

Remove All CVS Id Strings Possible Using a Script

Script does what is expected and tries to do it as
smartly as possible.

+ remove occurrences of two blank comment lines

next to each other after Id string line removed.

+ remove entire comment blocks which only exited to

contain CVS Ids

+ If the processing left a blank line at the top of

a file, it was removed.

  • Property mode set to 100644
File size: 7.4 KB
Line 
1/**
2 * @file
3 *
4 * @ingroup ScoreHeap
5 *
6 * @brief Heap Handler implementation.
7 */
8
9/*
10 *  COPYRIGHT (c) 1989-1999.
11 *  On-Line Applications Research Corporation (OAR).
12 *
13 *  Copyright (c) 2009 embedded brains GmbH.
14 *
15 *  The license and distribution terms for this file may be
16 *  found in the file LICENSE in this distribution or at
17 *  http://www.rtems.com/license/LICENSE.
18 */
19
20#if HAVE_CONFIG_H
21#include "config.h"
22#endif
23
24#include <rtems/system.h>
25#include <rtems/score/sysstate.h>
26#include <rtems/score/heap.h>
27
28#ifndef HEAP_PROTECTION
29  #define _Heap_Protection_free_delayed_blocks( heap, alloc_begin ) false
30#else
31  static bool _Heap_Protection_free_delayed_blocks(
32    Heap_Control *heap,
33    uintptr_t alloc_begin
34  )
35  {
36    bool search_again = false;
37    uintptr_t const blocks_to_free_count =
38      (heap->Protection.delayed_free_block_count + 1) / 2;
39
40    if ( alloc_begin == 0 && blocks_to_free_count > 0 ) {
41      Heap_Block *block_to_free = heap->Protection.first_delayed_free_block;
42      uintptr_t count = 0;
43
44      for ( count = 0; count < blocks_to_free_count; ++count ) {
45        Heap_Block *next_block_to_free =
46          block_to_free->Protection_begin.next_delayed_free_block;
47
48        block_to_free->Protection_begin.next_delayed_free_block =
49          HEAP_PROTECTION_OBOLUS;
50
51        _Heap_Free(
52          heap,
53          (void *) _Heap_Alloc_area_of_block( block_to_free )
54        );
55
56        block_to_free = next_block_to_free;
57      }
58
59      heap->Protection.delayed_free_block_count -= blocks_to_free_count;
60      heap->Protection.first_delayed_free_block = block_to_free;
61
62      search_again = true;
63    }
64
65    return search_again;
66  }
67#endif
68
69#ifdef RTEMS_HEAP_DEBUG
70  static void _Heap_Check_allocation(
71    const Heap_Control *heap,
72    const Heap_Block *block,
73    uintptr_t alloc_begin,
74    uintptr_t alloc_size,
75    uintptr_t alignment,
76    uintptr_t boundary
77  )
78  {
79    uintptr_t const min_block_size = heap->min_block_size;
80    uintptr_t const page_size = heap->page_size;
81
82    uintptr_t const block_begin = (uintptr_t) block;
83    uintptr_t const block_size = _Heap_Block_size( block );
84    uintptr_t const block_end = block_begin + block_size;
85
86    uintptr_t const alloc_end = alloc_begin + alloc_size;
87
88    uintptr_t const alloc_area_begin = _Heap_Alloc_area_of_block( block );
89    uintptr_t const alloc_area_offset = alloc_begin - alloc_area_begin;
90
91    _HAssert( block_size >= min_block_size );
92    _HAssert( block_begin < block_end );
93    _HAssert(
94      _Heap_Is_aligned( block_begin + HEAP_BLOCK_HEADER_SIZE, page_size )
95    );
96    _HAssert(
97      _Heap_Is_aligned( block_size, page_size )
98    );
99
100    _HAssert( alloc_end <= block_end + HEAP_ALLOC_BONUS );
101    _HAssert( alloc_area_begin == block_begin + HEAP_BLOCK_HEADER_SIZE);
102    _HAssert( alloc_area_offset < page_size );
103
104    _HAssert( _Heap_Is_aligned( alloc_area_begin, page_size ) );
105    if ( alignment == 0 ) {
106      _HAssert( alloc_begin == alloc_area_begin );
107    } else {
108      _HAssert( _Heap_Is_aligned( alloc_begin, alignment ) );
109    }
110
111    if ( boundary != 0 ) {
112      uintptr_t boundary_line = _Heap_Align_down( alloc_end, boundary );
113
114      _HAssert( alloc_size <= boundary );
115      _HAssert( boundary_line <= alloc_begin || alloc_end <= boundary_line );
116    }
117  }
118#else
119  #define _Heap_Check_allocation( h, b, ab, as, ag, bd ) ((void) 0)
120#endif
121
122static uintptr_t _Heap_Check_block(
123  const Heap_Control *heap,
124  const Heap_Block *block,
125  uintptr_t alloc_size,
126  uintptr_t alignment,
127  uintptr_t boundary
128)
129{
130  uintptr_t const page_size = heap->page_size;
131  uintptr_t const min_block_size = heap->min_block_size;
132
133  uintptr_t const block_begin = (uintptr_t) block;
134  uintptr_t const block_size = _Heap_Block_size( block );
135  uintptr_t const block_end = block_begin + block_size;
136
137  uintptr_t const alloc_begin_floor = _Heap_Alloc_area_of_block( block );
138  uintptr_t const alloc_begin_ceiling = block_end - min_block_size
139    + HEAP_BLOCK_HEADER_SIZE + page_size - 1;
140
141  uintptr_t alloc_end = block_end + HEAP_ALLOC_BONUS;
142  uintptr_t alloc_begin = alloc_end - alloc_size;
143
144  alloc_begin = _Heap_Align_down( alloc_begin, alignment );
145
146  /* Ensure that the we have a valid new block at the end */
147  if ( alloc_begin > alloc_begin_ceiling ) {
148    alloc_begin = _Heap_Align_down( alloc_begin_ceiling, alignment );
149  }
150
151  alloc_end = alloc_begin + alloc_size;
152
153  /* Ensure boundary constaint */
154  if ( boundary != 0 ) {
155    uintptr_t const boundary_floor = alloc_begin_floor + alloc_size;
156    uintptr_t boundary_line = _Heap_Align_down( alloc_end, boundary );
157
158    while ( alloc_begin < boundary_line && boundary_line < alloc_end ) {
159      if ( boundary_line < boundary_floor ) {
160        return 0;
161      }
162      alloc_begin = boundary_line - alloc_size;
163      alloc_begin = _Heap_Align_down( alloc_begin, alignment );
164      alloc_end = alloc_begin + alloc_size;
165      boundary_line = _Heap_Align_down( alloc_end, boundary );
166    }
167  }
168
169  /* Ensure that the we have a valid new block at the beginning */
170  if ( alloc_begin >= alloc_begin_floor ) {
171    uintptr_t const alloc_block_begin =
172      (uintptr_t) _Heap_Block_of_alloc_area( alloc_begin, page_size );
173    uintptr_t const free_size = alloc_block_begin - block_begin;
174
175    if ( free_size >= min_block_size || free_size == 0 ) {
176      return alloc_begin;
177    }
178  }
179
180  return 0;
181}
182
183void *_Heap_Allocate_aligned_with_boundary(
184  Heap_Control *heap,
185  uintptr_t alloc_size,
186  uintptr_t alignment,
187  uintptr_t boundary
188)
189{
190  Heap_Statistics *const stats = &heap->stats;
191  uintptr_t const block_size_floor = alloc_size + HEAP_BLOCK_HEADER_SIZE
192    - HEAP_ALLOC_BONUS;
193  uintptr_t const page_size = heap->page_size;
194  Heap_Block *block = NULL;
195  uintptr_t alloc_begin = 0;
196  uint32_t search_count = 0;
197  bool search_again = false;
198
199  if ( block_size_floor < alloc_size ) {
200    /* Integer overflow occured */
201    return NULL;
202  }
203
204  if ( boundary != 0 ) {
205    if ( boundary < alloc_size ) {
206      return NULL;
207    }
208
209    if ( alignment == 0 ) {
210      alignment = page_size;
211    }
212  }
213
214  do {
215    Heap_Block *const free_list_tail = _Heap_Free_list_tail( heap );
216
217    block = _Heap_Free_list_first( heap );
218    while ( block != free_list_tail ) {
219      _HAssert( _Heap_Is_prev_used( block ) );
220
221      _Heap_Protection_block_check( heap, block );
222
223      /*
224       * The HEAP_PREV_BLOCK_USED flag is always set in the block size_and_flag
225       * field.  Thus the value is about one unit larger than the real block
226       * size.  The greater than operator takes this into account.
227       */
228      if ( block->size_and_flag > block_size_floor ) {
229        if ( alignment == 0 ) {
230          alloc_begin = _Heap_Alloc_area_of_block( block );
231        } else {
232          alloc_begin = _Heap_Check_block(
233            heap,
234            block,
235            alloc_size,
236            alignment,
237            boundary
238          );
239        }
240      }
241
242      /* Statistics */
243      ++search_count;
244
245      if ( alloc_begin != 0 ) {
246        break;
247      }
248
249      block = block->next;
250    }
251
252    search_again = _Heap_Protection_free_delayed_blocks( heap, alloc_begin );
253  } while ( search_again );
254
255  if ( alloc_begin != 0 ) {
256    /* Statistics */
257    ++stats->allocs;
258    stats->searches += search_count;
259
260    block = _Heap_Block_allocate( heap, block, alloc_begin, alloc_size );
261
262    _Heap_Check_allocation(
263      heap,
264      block,
265      alloc_begin,
266      alloc_size,
267      alignment,
268      boundary
269    );
270  }
271
272  /* Statistics */
273  if ( stats->max_search < search_count ) {
274    stats->max_search = search_count;
275  }
276
277  return (void *) alloc_begin;
278}
Note: See TracBrowser for help on using the repository browser.