source: rtems/cpukit/score/src/heapwalk.c @ 518c2aeb

4.104.115
Last change on this file since 518c2aeb was 518c2aeb, checked in by Joel Sherrill <joel.sherrill@…>, on 09/09/09 at 14:58:37

2009-09-09 Sebastian Huber <Sebastian.Huber@…>

  • 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.
  • Property mode set to 100644
File size: 8.9 KB
Line 
1/**
2 * @file
3 *
4 * @ingroup ScoreHeap
5 *
6 * @brief Heap Handler implementation.
7 */
8
9/*
10 *  COPYRIGHT ( c ) 1989-2007.
11 *  On-Line Applications Research Corporation ( OAR ).
12 *
13 *  The license and distribution terms for this file may be
14 *  found in the file LICENSE in this distribution or at
15 *  http://www.rtems.com/license/LICENSE.
16 *
17 *  $Id$
18 */
19
20#if HAVE_CONFIG_H
21#include "config.h"
22#endif
23
24#include <rtems/system.h>
25#include <rtems/score/address.h>
26#include <rtems/score/sysstate.h>
27#include <rtems/score/heap.h>
28#include <rtems/score/interr.h>
29#include <rtems/bspIo.h>
30
31static void _Heap_Walk_printk( int source, bool dump, bool error, const char *fmt, ... )
32{
33  if ( dump ) {
34    va_list ap;
35
36    if ( error ) {
37      printk( "FAIL[%d]: ", source );
38    } else {
39      printk( "PASS[%d]: ", source );
40    }
41
42    va_start( ap, fmt );
43    vprintk( fmt, ap );
44    va_end( ap );
45  }
46}
47
48static bool _Heap_Walk_check_free_list(
49  int source,
50  bool dump,
51  Heap_Control *heap
52)
53{
54  uintptr_t const page_size = heap->page_size;
55  const Heap_Block *const free_list_tail = _Heap_Free_list_tail( heap );
56  const Heap_Block *const first_free_block = _Heap_Free_list_first( heap );
57  const Heap_Block *prev_block = free_list_tail;
58  const Heap_Block *free_block = first_free_block;
59
60  while ( free_block != free_list_tail ) {
61    if ( !_Heap_Is_block_in_heap( heap, free_block ) ) {
62      _Heap_Walk_printk(
63        source,
64        dump,
65        true,
66        "free block 0x%08x: not in heap\n",
67        free_block
68      );
69
70      return false;
71    }
72
73    if (
74      !_Heap_Is_aligned( _Heap_Alloc_area_of_block( free_block ), page_size )
75    ) {
76      _Heap_Walk_printk(
77        source,
78        dump,
79        true,
80        "free block 0x%08x: alloc area not page aligned\n",
81        free_block
82      );
83
84      return false;
85    }
86
87    if ( _Heap_Is_used( free_block ) ) {
88      _Heap_Walk_printk(
89        source,
90        dump,
91        true,
92        "free block 0x%08x: is used\n",
93        free_block
94      );
95
96      return false;
97    }
98
99    if ( free_block->prev != prev_block ) {
100      _Heap_Walk_printk(
101        source,
102        dump,
103        true,
104        "free block 0x%08x: invalid previous block 0x%08x\n",
105        free_block,
106        free_block->prev
107      );
108
109      return false;
110    }
111
112    prev_block = free_block;
113    free_block = free_block->next;
114  }
115
116  return true;
117}
118
119static bool _Heap_Walk_is_in_free_list(
120  Heap_Control *heap,
121  Heap_Block *block
122)
123{
124  const Heap_Block *const free_list_tail = _Heap_Free_list_tail( heap );
125  const Heap_Block *free_block = _Heap_Free_list_first( heap );
126
127  while ( free_block != free_list_tail ) {
128    if ( free_block == block ) {
129      return true;
130    }
131    free_block = free_block->next;
132  }
133
134  return false;
135}
136
137static bool _Heap_Walk_check_control(
138  int source,
139  bool dump,
140  Heap_Control *heap
141)
142{
143  uintptr_t const page_size = heap->page_size;
144  uintptr_t const min_block_size = heap->min_block_size;
145  Heap_Block *const first_free_block = _Heap_Free_list_first( heap );
146  Heap_Block *const last_free_block = _Heap_Free_list_last( heap );
147  Heap_Block *const first_block = heap->first_block;
148  Heap_Block *const last_block = heap->last_block;
149
150  _Heap_Walk_printk(
151    source,
152    dump,
153    false,
154    "page size %u, min block size %u\n"
155      "\tarea begin 0x%08x, area end 0x%08x\n"
156      "\tfirst block 0x%08x, last block 0x%08x\n"
157      "\tfirst free 0x%08x, last free 0x%08x\n",
158    page_size, min_block_size,
159    heap->area_begin, heap->area_end,
160    first_block, last_block,
161    first_free_block, last_free_block
162  );
163
164  if ( page_size == 0 ) {
165    _Heap_Walk_printk( source, dump, true, "page size is zero\n" );
166
167    return false;
168  }
169
170  if ( !_Addresses_Is_aligned( (void *) page_size ) ) {
171    _Heap_Walk_printk(
172      source,
173      dump,
174      true,
175      "page size %u not CPU aligned\n",
176      page_size
177    );
178
179    return false;
180  }
181
182  if ( !_Heap_Is_aligned( min_block_size, page_size ) ) {
183    _Heap_Walk_printk(
184      source,
185      dump,
186      true,
187      "min block size %u not page aligned\n",
188      min_block_size
189    );
190
191    return false;
192  }
193
194  if (
195    !_Heap_Is_aligned( _Heap_Alloc_area_of_block( first_block ), page_size )
196  ) {
197    _Heap_Walk_printk(
198      source,
199      dump,
200      true,
201      "first block 0x%08x: alloc area not page aligned\n",
202      first_block
203    );
204
205    return false;
206  }
207
208  if ( !_Heap_Is_prev_used( first_block ) ) {
209    _Heap_Walk_printk(
210      source,
211      dump,
212      true,
213      "first block: HEAP_PREV_BLOCK_USED is cleared\n"
214    );
215
216    return false;
217  }
218
219  if ( first_block->prev_size != page_size ) {
220    _Heap_Walk_printk(
221      source,
222      dump,
223      true,
224      "first block: prev size %u != page size %u\n",
225      first_block->prev_size,
226      page_size
227    );
228
229    return false;
230  }
231
232  if ( _Heap_Is_free( last_block ) ) {
233    _Heap_Walk_printk(
234      source,
235      dump,
236      true,
237      "last block: is free\n"
238    );
239
240    return false;
241  }
242
243  return _Heap_Walk_check_free_list( source, dump, heap );
244}
245
246static bool _Heap_Walk_check_free_block(
247  int source,
248  bool dump,
249  Heap_Control *heap,
250  Heap_Block *block
251)
252{
253  Heap_Block *const free_list_tail = _Heap_Free_list_tail( heap );
254  Heap_Block *const free_list_head = _Heap_Free_list_head( heap );
255  Heap_Block *const first_free_block = _Heap_Free_list_first( heap );
256  Heap_Block *const last_free_block = _Heap_Free_list_last( heap );
257  bool const prev_used = _Heap_Is_prev_used( block );
258  uintptr_t const block_size = _Heap_Block_size( block );
259  Heap_Block *const next_block = _Heap_Block_at( block, block_size );
260
261  _Heap_Walk_printk(
262    source,
263    dump,
264    false,
265    "block 0x%08x: prev 0x%08x%s, next 0x%08x%s\n",
266    block,
267    block->prev,
268    block->prev == first_free_block ?
269      " (= first)"
270        : (block->prev == free_list_head ? " (= head)" : ""),
271    block->next,
272    block->next == last_free_block ?
273      " (= last)"
274        : (block->next == free_list_tail ? " (= tail)" : "")
275  );
276
277  if ( block_size != next_block->prev_size ) {
278    _Heap_Walk_printk(
279      source,
280      dump,
281      true,
282      "block 0x%08x: size %u != size %u (in next block 0x%08x)\n",
283      block,
284      block_size,
285      next_block->prev_size,
286      next_block
287    );
288
289    return false;
290  }
291
292  if ( !prev_used ) {
293    _Heap_Walk_printk(
294      source,
295      dump,
296      true,
297      "block 0x%08x: two consecutive blocks are free\n",
298      block
299    );
300
301    return false;
302  }
303
304  if ( !_Heap_Walk_is_in_free_list( heap, block ) ) {
305    _Heap_Walk_printk(
306      source,
307      dump,
308      true,
309      "block 0x%08x: free block not in free list\n",
310      block
311    );
312
313    return false;
314  }
315
316  return true;
317}
318
319bool _Heap_Walk(
320  Heap_Control *heap,
321  int source,
322  bool dump
323)
324{
325  uintptr_t const page_size = heap->page_size;
326  uintptr_t const min_block_size = heap->min_block_size;
327  Heap_Block *const last_block = heap->last_block;
328  Heap_Block *block = heap->first_block;
329
330  if ( !_System_state_Is_up( _System_state_Get() ) ) {
331    return true;
332  }
333
334  if ( !_Heap_Walk_check_control( source, dump, heap ) ) {
335    return false;
336  }
337
338  while ( block != last_block ) {
339    uintptr_t const block_begin = (uintptr_t) block;
340    uintptr_t const block_size = _Heap_Block_size( block );
341    bool const prev_used = _Heap_Is_prev_used( block );
342    Heap_Block *const next_block = _Heap_Block_at( block, block_size );
343    uintptr_t const next_block_begin = (uintptr_t) next_block;
344
345    if ( prev_used ) {
346      _Heap_Walk_printk(
347        source,
348        dump,
349        false,
350        "block 0x%08x: size %u\n",
351        block,
352        block_size
353      );
354    } else {
355      _Heap_Walk_printk(
356        source,
357        dump,
358        false,
359        "block 0x%08x: size %u, prev_size %u\n",
360        block,
361        block_size,
362        block->prev_size
363      );
364    }
365
366    if ( !_Heap_Is_block_in_heap( heap, next_block ) ) {
367      _Heap_Walk_printk(
368        source,
369        dump,
370        true,
371        "block 0x%08x: next block 0x%08x not in heap\n",
372        block,
373        next_block
374      );
375     
376      return false;
377    }
378
379    if ( !_Heap_Is_aligned( block_size, page_size ) ) {
380      _Heap_Walk_printk(
381        source,
382        dump,
383        true,
384        "block 0x%08x: block size %u not page aligned\n",
385        block,
386        block_size
387      );
388     
389      return false;
390    }
391
392    if ( block_size < min_block_size ) {
393      _Heap_Walk_printk(
394        source,
395        dump,
396        true,
397        "block 0x%08x: size %u < min block size %u\n",
398        block,
399        block_size,
400        min_block_size
401      );
402     
403      return false;
404    }
405
406    if ( next_block_begin <= block_begin ) {
407      _Heap_Walk_printk(
408        source,
409        dump,
410        true,
411        "block 0x%08x: next block 0x%08x is not a successor\n",
412        block,
413        next_block
414      );
415     
416      return false;
417    }
418   
419    if ( !_Heap_Is_prev_used( next_block ) ) {
420      if ( !_Heap_Walk_check_free_block( source, dump, heap, block ) ) {
421        return false;
422      }
423    }
424
425    block = next_block;
426  }
427
428  return true;
429}
Note: See TracBrowser for help on using the repository browser.