source: rtems/cpukit/score/src/heapwalk.c @ dea3eccb

4.104.115
Last change on this file since dea3eccb was dea3eccb, checked in by Joel Sherrill <joel.sherrill@…>, on 09/06/09 at 15:24:08

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

  • libcsupport/src/free.c, libmisc/stackchk/check.c, rtems/include/rtems/rtems/region.h, rtems/src/regioncreate.c, rtems/src/regionextend.c, rtems/src/regiongetinfo.c, rtems/src/regiongetsegment.c, rtems/src/regiongetsegmentsize.c, rtems/src/regionresizesegment.c, score/src/pheapallocate.c, score/src/pheapallocatealigned.c, score/src/pheapextend.c, score/src/pheapfree.c, score/src/pheapgetblocksize.c, score/src/pheapgetfreeinfo.c, score/src/pheapgetinfo.c, score/src/pheapgetsize.c, score/src/pheapinit.c, score/src/pheapresizeblock.c, score/src/pheapwalk.c: Update for heap API changes.
  • score/include/rtems/score/apimutex.h, score/include/rtems/score/object.h: Documentation.
  • score/include/rtems/score/heap.h, score/include/rtems/score/protectedheap.h, score/inline/rtems/score/heap.inl, score/src/heap.c, score/src/heapallocate.c, score/src/heapallocatealigned.c, score/src/heapextend.c, score/src/heapfree.c, score/src/heapgetfreeinfo.c, score/src/heapgetinfo.c, score/src/heapresizeblock.c, score/src/heapsizeofuserarea.c, score/src/heapwalk.c: Overall cleanup. Added boundary constraint to allocation function. More changes follow.
  • Property mode set to 100644
File size: 10.0 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  const Heap_Block *const free_list_tail = _Heap_Free_list_tail( heap );
55  const Heap_Block *const first_free_block = _Heap_Free_list_first( heap );
56  const Heap_Block *free_block = first_free_block;
57  uintptr_t const page_size = heap->page_size;
58  uintptr_t const loop_limit =
59    ((uintptr_t) heap->last_block - (uintptr_t) heap->first_block)
60      / heap->min_block_size;
61  uintptr_t loop_counter = 0;
62
63  while ( free_block != free_list_tail && loop_counter < loop_limit ) {
64    if ( !_Heap_Is_block_in_heap( heap, free_block ) ) {
65      _Heap_Walk_printk(
66        source,
67        dump,
68        true,
69        "free block 0x%08x: not in heap\n",
70        free_block
71      );
72
73      return false;
74    }
75
76    if (
77      !_Heap_Is_aligned( _Heap_Alloc_area_of_block( free_block ), page_size )
78    ) {
79      _Heap_Walk_printk(
80        source,
81        dump,
82        true,
83        "free block 0x%08x: alloc area not page aligned\n",
84        free_block
85      );
86
87      return false;
88    }
89
90    ++loop_counter;
91
92    free_block = free_block->next;
93  }
94
95  if ( loop_counter >= loop_limit ) {
96    _Heap_Walk_printk(
97      source,
98      dump,
99      true,
100      "free list contains a loop\n"
101    );
102
103    return false;
104  }
105
106  return true;
107}
108
109static bool _Heap_Walk_is_in_free_list(
110  Heap_Control *heap,
111  Heap_Block *block
112)
113{
114  const Heap_Block *const free_list_tail = _Heap_Free_list_tail( heap );
115  const Heap_Block *free_block = _Heap_Free_list_first( heap );
116
117  while ( free_block != free_list_tail ) {
118    if ( free_block == block ) {
119      return true;
120    }
121    free_block = free_block->next;
122  }
123
124  return false;
125}
126
127static bool _Heap_Walk_check_control(
128  int source,
129  bool dump,
130  Heap_Control *heap
131)
132{
133  uintptr_t const page_size = heap->page_size;
134  uintptr_t const min_block_size = heap->min_block_size;
135  Heap_Block *const free_list_tail = _Heap_Free_list_tail( heap );
136  Heap_Block *const free_list_head = _Heap_Free_list_head( heap );
137  Heap_Block *const first_free_block = _Heap_Free_list_first( heap );
138  Heap_Block *const last_free_block = _Heap_Free_list_last( heap );
139  Heap_Block *const first_block = heap->first_block;
140  Heap_Block *const last_block = heap->last_block;
141
142  _Heap_Walk_printk(
143    source,
144    dump,
145    false,
146    "page size %u, min block size %u\n"
147      "\tarea begin 0x%08x, area end 0x%08x\n"
148      "\tfirst block 0x%08x, last block 0x%08x\n"
149      "\tfirst free 0x%08x, last free 0x%08x\n",
150    page_size, min_block_size,
151    heap->area_begin, heap->area_end,
152    first_block, last_block,
153    first_free_block, last_free_block
154  );
155
156  if ( page_size == 0 ) {
157    _Heap_Walk_printk( source, dump, true, "page size is zero\n" );
158
159    return false;
160  }
161
162  if ( !_Addresses_Is_aligned( (void *) page_size ) ) {
163    _Heap_Walk_printk(
164      source,
165      dump,
166      true,
167      "page size %u not CPU aligned\n",
168      page_size
169    );
170
171    return false;
172  }
173
174  if ( !_Heap_Is_aligned( min_block_size, page_size ) ) {
175    _Heap_Walk_printk(
176      source,
177      dump,
178      true,
179      "min block size %u not page aligned\n",
180      min_block_size
181    );
182
183    return false;
184  }
185
186  if (
187    first_free_block != free_list_head
188      && !_Addresses_Is_aligned( first_free_block )
189  ) {
190    _Heap_Walk_printk(
191      source,
192      dump,
193      true,
194      "first free block: 0x%08x not CPU aligned\n",
195      first_free_block
196    );
197
198    return false;
199  }
200
201  if (
202    last_free_block != free_list_tail
203      && !_Addresses_Is_aligned( last_free_block )
204  ) {
205    _Heap_Walk_printk(
206      source,
207      dump,
208      true,
209      "last free block: 0x%08x not CPU aligned\n",
210      last_free_block
211    );
212   
213    return false;
214  }
215
216  if (
217    !_Heap_Is_aligned( _Heap_Alloc_area_of_block( first_block ), page_size )
218  ) {
219    _Heap_Walk_printk(
220      source,
221      dump,
222      true,
223      "first block: 0x%08x not page aligned\n",
224      first_block
225    );
226
227    return false;
228  }
229
230  if (
231    !_Heap_Is_aligned( _Heap_Alloc_area_of_block( last_block ), page_size )
232  ) {
233    _Heap_Walk_printk(
234      source,
235      dump,
236      true,
237      "last block: 0x%08x not page aligned\n",
238      last_block
239    );
240
241    return false;
242  }
243
244  if ( !_Heap_Is_prev_used( first_block ) ) {
245    _Heap_Walk_printk(
246      source,
247      dump,
248      true,
249      "first block: HEAP_PREV_BLOCK_USED is cleared\n"
250    );
251  }
252
253  if ( first_block->prev_size != page_size ) {
254    _Heap_Walk_printk(
255      source,
256      dump,
257      true,
258      "first block: prev size %u != page size %u\n",
259      first_block->prev_size,
260      page_size
261    );
262  }
263
264  return _Heap_Walk_check_free_list( source, dump, heap );
265}
266
267bool _Heap_Walk(
268  Heap_Control *heap,
269  int source,
270  bool dump
271)
272{
273  uintptr_t const page_size = heap->page_size;
274  uintptr_t const min_block_size = heap->min_block_size;
275  Heap_Block *const free_list_tail = _Heap_Free_list_tail( heap );
276  Heap_Block *const free_list_head = _Heap_Free_list_head( heap );
277  Heap_Block *const first_free_block = _Heap_Free_list_first( heap );
278  Heap_Block *const last_free_block = _Heap_Free_list_last( heap );
279  Heap_Block *const last_block = heap->last_block;
280  Heap_Block *block = heap->first_block;
281  bool error = false;
282
283  if ( !_System_state_Is_up( _System_state_Get() ) ) {
284    return true;
285  }
286
287  if ( !_Heap_Walk_check_control( source, dump, heap ) ) {
288    return false;
289  }
290
291  while ( block != last_block && _Addresses_Is_aligned( block ) ) {
292    uintptr_t const block_begin = (uintptr_t) block;
293    uintptr_t const block_size = _Heap_Block_size( block );
294    bool const prev_used = _Heap_Is_prev_used( block );
295    Heap_Block *const next_block = _Heap_Block_at( block, block_size );
296    uintptr_t const next_block_begin = (uintptr_t) next_block;
297
298    if ( prev_used ) {
299      _Heap_Walk_printk(
300        source,
301        dump,
302        error,
303        "block 0x%08x: size %u\n",
304        block,
305        block_size
306      );
307    } else {
308      _Heap_Walk_printk(
309        source,
310        dump,
311        error,
312        "block 0x%08x: size %u, prev_size %u\n",
313        block,
314        block_size,
315        block->prev_size
316      );
317    }
318
319    if (
320      !_Heap_Is_aligned( block_begin + HEAP_BLOCK_HEADER_SIZE, page_size )
321    ) {
322      error = true;
323      _Heap_Walk_printk(
324        source,
325        dump,
326        error,
327        "block 0x%08x: not page (%u) aligned\n",
328        block,
329        page_size
330      );
331      break;
332    }
333
334    if ( !_Heap_Is_aligned( block_size, page_size ) ) {
335      error = true;
336      _Heap_Walk_printk(
337        source,
338        dump,
339        error,
340        "block 0x%08x: block size %u not page (%u) aligned\n",
341        block,
342        block_size,
343        page_size
344      );
345      break;
346    }
347
348    if ( block_size < min_block_size ) {
349      error = true;
350      _Heap_Walk_printk(
351        source,
352        dump,
353        error,
354        "block 0x%08x: size %u < min block size %u\n",
355        block,
356        block_size,
357        min_block_size
358      );
359      break;
360    }
361
362    if ( next_block_begin <= block_begin ) {
363      error = true;
364      _Heap_Walk_printk(
365        source,
366        dump,
367        error,
368        "block 0x%08x: next block 0x%08x is not a successor\n",
369        block,
370        next_block
371      );
372      break;
373    }
374   
375    if ( !_Heap_Is_prev_used( next_block ) ) {
376      _Heap_Walk_printk(
377        source,
378        dump,
379        error,
380        "block 0x%08x: prev 0x%08x%s, next 0x%08x%s\n",
381        block,
382        block->prev,
383        block->prev == first_free_block ?
384          " (= first)"
385            : (block->prev == free_list_head ? " (= head)" : ""),
386        block->next,
387        block->next == last_free_block ?
388          " (= last)"
389            : (block->next == free_list_tail ? " (= tail)" : "")
390      );
391
392      if ( block_size != next_block->prev_size ) {
393        error = true;
394        _Heap_Walk_printk(
395          source,
396          dump,
397          error,
398          "block 0x%08x: size %u != size %u (in next block 0x%08x)\n",
399          block,
400          block_size,
401          next_block->prev_size,
402          next_block
403        );
404      }
405
406      if ( !prev_used ) {
407        error = true;
408        _Heap_Walk_printk(
409          source,
410          dump,
411          error,
412          "block 0x%08x: two consecutive blocks are free\n",
413          block
414        );
415      }
416
417      if ( !_Heap_Walk_is_in_free_list( heap, block ) ) {
418        error = true;
419        _Heap_Walk_printk(
420          source,
421          dump,
422          error,
423          "block 0x%08x: free block not in free list\n",
424          block
425        );
426      }
427    }
428
429    block = next_block;
430  }
431
432  if ( !_Addresses_Is_aligned( block ) ) {
433    error = true;
434    _Heap_Walk_printk(
435      source,
436      dump,
437      error,
438      "block 0x%08x: not CPU aligned\n",
439      block
440    );
441
442    return false;
443  }
444
445  if ( block == last_block ) {
446    uintptr_t const block_size = _Heap_Block_size( block );
447
448    if ( block_size != page_size ) {
449      error = true;
450      _Heap_Walk_printk(
451        source,
452        dump,
453        error,
454        "last block 0x%08x: size %u != page size %u\n",
455        block,
456        block_size,
457        page_size
458      );
459    }
460  } else {
461    error = true;
462    _Heap_Walk_printk(
463      source,
464      dump,
465      error,
466      "last block 0x%08x != last block 0x%08x\n",
467      block,
468      last_block
469    );
470  }
471
472  return !error;
473}
Note: See TracBrowser for help on using the repository browser.