source: rtems/cpukit/score/src/heapextend.c @ 2d7ae960

4.115
Last change on this file since 2d7ae960 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: 6.7 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) 2010 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
28static void _Heap_Free_block( Heap_Control *heap, Heap_Block *block )
29{
30  Heap_Statistics *const stats = &heap->stats;
31
32  /* Statistics */
33  ++stats->used_blocks;
34  --stats->frees;
35
36  _Heap_Free( heap, (void *) _Heap_Alloc_area_of_block( block ));
37}
38
39static void _Heap_Merge_below(
40  Heap_Control *heap,
41  uintptr_t extend_area_begin,
42  Heap_Block *first_block
43)
44{
45  uintptr_t const page_size = heap->page_size;
46  uintptr_t const new_first_block_alloc_begin =
47    _Heap_Align_up( extend_area_begin + HEAP_BLOCK_HEADER_SIZE, page_size );
48  uintptr_t const new_first_block_begin =
49    new_first_block_alloc_begin - HEAP_BLOCK_HEADER_SIZE;
50  uintptr_t const first_block_begin = (uintptr_t) first_block;
51  uintptr_t const new_first_block_size =
52    first_block_begin - new_first_block_begin;
53  Heap_Block *const new_first_block = (Heap_Block *) new_first_block_begin;
54
55  new_first_block->prev_size = first_block->prev_size;
56  new_first_block->size_and_flag = new_first_block_size | HEAP_PREV_BLOCK_USED;
57
58  _Heap_Free_block( heap, new_first_block );
59}
60
61static void _Heap_Merge_above(
62  Heap_Control *heap,
63  Heap_Block *last_block,
64  uintptr_t extend_area_end
65)
66{
67  uintptr_t const page_size = heap->page_size;
68  uintptr_t const last_block_begin = (uintptr_t) last_block;
69  uintptr_t const last_block_new_size = _Heap_Align_down(
70    extend_area_end - last_block_begin - HEAP_BLOCK_HEADER_SIZE,
71    page_size
72  );
73  Heap_Block *const new_last_block =
74    _Heap_Block_at( last_block, last_block_new_size );
75
76  new_last_block->size_and_flag =
77    (last_block->size_and_flag - last_block_new_size)
78      | HEAP_PREV_BLOCK_USED;
79
80  _Heap_Block_set_size( last_block, last_block_new_size );
81
82  _Heap_Free_block( heap, last_block );
83}
84
85static void _Heap_Link_below(
86  Heap_Block *link,
87  Heap_Block *last_block
88)
89{
90  uintptr_t const last_block_begin = (uintptr_t) last_block;
91  uintptr_t const link_begin = (uintptr_t) link;
92
93  last_block->size_and_flag =
94    (link_begin - last_block_begin) | HEAP_PREV_BLOCK_USED;
95}
96
97static void _Heap_Link_above(
98  Heap_Block *link,
99  Heap_Block *first_block,
100  Heap_Block *last_block
101)
102{
103  uintptr_t const link_begin = (uintptr_t) link;
104  uintptr_t const first_block_begin = (uintptr_t) first_block;
105
106  _Heap_Block_set_size( link, first_block_begin - link_begin );
107
108  last_block->size_and_flag |= HEAP_PREV_BLOCK_USED;
109}
110
111bool _Heap_Extend(
112  Heap_Control *heap,
113  void *extend_area_begin_ptr,
114  uintptr_t extend_area_size,
115  uintptr_t *extended_size_ptr
116)
117{
118  Heap_Statistics *const stats = &heap->stats;
119  Heap_Block *const first_block = heap->first_block;
120  Heap_Block *start_block = first_block;
121  Heap_Block *merge_below_block = NULL;
122  Heap_Block *merge_above_block = NULL;
123  Heap_Block *link_below_block = NULL;
124  Heap_Block *link_above_block = NULL;
125  Heap_Block *extend_first_block = NULL;
126  Heap_Block *extend_last_block = NULL;
127  uintptr_t const page_size = heap->page_size;
128  uintptr_t const min_block_size = heap->min_block_size;
129  uintptr_t const extend_area_begin = (uintptr_t) extend_area_begin_ptr;
130  uintptr_t const extend_area_end = extend_area_begin + extend_area_size;
131  uintptr_t const free_size = stats->free_size;
132  uintptr_t extend_first_block_size = 0;
133  uintptr_t extended_size = 0;
134  bool extend_area_ok = false;
135
136  if ( extend_area_end < extend_area_begin ) {
137    return false;
138  }
139
140  extend_area_ok = _Heap_Get_first_and_last_block(
141    extend_area_begin,
142    extend_area_size,
143    page_size,
144    min_block_size,
145    &extend_first_block,
146    &extend_last_block
147  );
148  if (!extend_area_ok ) {
149    /* For simplicity we reject extend areas that are too small */
150    return false;
151  }
152
153  do {
154    uintptr_t const sub_area_begin = (start_block != first_block) ?
155      (uintptr_t) start_block : heap->area_begin;
156    uintptr_t const sub_area_end = start_block->prev_size;
157    Heap_Block *const end_block =
158      _Heap_Block_of_alloc_area( sub_area_end, page_size );
159
160    if (
161      sub_area_end > extend_area_begin && extend_area_end > sub_area_begin
162    ) {
163      return false;
164    }
165
166    if ( extend_area_end == sub_area_begin ) {
167      merge_below_block = start_block;
168    } else if ( extend_area_end < sub_area_end ) {
169      link_below_block = start_block;
170    }
171
172    if ( sub_area_end == extend_area_begin ) {
173      start_block->prev_size = extend_area_end;
174
175      merge_above_block = end_block;
176    } else if ( sub_area_end < extend_area_begin ) {
177      link_above_block = end_block;
178    }
179
180    start_block = _Heap_Block_at( end_block, _Heap_Block_size( end_block ) );
181  } while ( start_block != first_block );
182
183  if ( extend_area_begin < heap->area_begin ) {
184    heap->area_begin = extend_area_begin;
185  } else if ( heap->area_end < extend_area_end ) {
186    heap->area_end = extend_area_end;
187  }
188
189  extend_first_block_size =
190    (uintptr_t) extend_last_block - (uintptr_t) extend_first_block;
191
192  extend_first_block->prev_size = extend_area_end;
193  extend_first_block->size_and_flag =
194    extend_first_block_size | HEAP_PREV_BLOCK_USED;
195  _Heap_Protection_block_initialize( heap, extend_first_block );
196
197  extend_last_block->prev_size = extend_first_block_size;
198  extend_last_block->size_and_flag = 0;
199  _Heap_Protection_block_initialize( heap, extend_last_block );
200
201  if ( (uintptr_t) extend_first_block < (uintptr_t) heap->first_block ) {
202    heap->first_block = extend_first_block;
203  } else if ( (uintptr_t) extend_last_block > (uintptr_t) heap->last_block ) {
204    heap->last_block = extend_last_block;
205  }
206
207  if ( merge_below_block != NULL ) {
208    _Heap_Merge_below( heap, extend_area_begin, merge_below_block );
209  } else if ( link_below_block != NULL ) {
210    _Heap_Link_below(
211      link_below_block,
212      extend_last_block
213    );
214  }
215
216  if ( merge_above_block != NULL ) {
217    _Heap_Merge_above( heap, merge_above_block, extend_area_end );
218  } else if ( link_above_block != NULL ) {
219    _Heap_Link_above(
220      link_above_block,
221      extend_first_block,
222      extend_last_block
223    );
224  }
225
226  if ( merge_below_block == NULL && merge_above_block == NULL ) {
227    _Heap_Free_block( heap, extend_first_block );
228  }
229
230  _Heap_Set_last_block_size( heap );
231
232  extended_size = stats->free_size - free_size;
233
234  /* Statistics */
235  stats->size += extended_size;
236
237  if ( extended_size_ptr != NULL )
238    *extended_size_ptr = extended_size;
239
240  return true;
241}
Note: See TracBrowser for help on using the repository browser.