[93b4e6ef] | 1 | /* |
---|
| 2 | * Heap Handler |
---|
| 3 | * |
---|
[08311cc3] | 4 | * COPYRIGHT (c) 1989-1999. |
---|
[93b4e6ef] | 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 |
---|
[dd687d97] | 9 | * http://www.rtems.com/license/LICENSE. |
---|
[93b4e6ef] | 10 | * |
---|
| 11 | * $Id$ |
---|
| 12 | */ |
---|
| 13 | |
---|
[a8eed23] | 14 | #if HAVE_CONFIG_H |
---|
| 15 | #include "config.h" |
---|
| 16 | #endif |
---|
[93b4e6ef] | 17 | |
---|
[77b1020a] | 18 | #include <stdlib.h> /* abort */ |
---|
| 19 | |
---|
[93b4e6ef] | 20 | #include <rtems/system.h> |
---|
| 21 | #include <rtems/score/sysstate.h> |
---|
| 22 | #include <rtems/score/heap.h> |
---|
| 23 | |
---|
| 24 | /*PAGE |
---|
| 25 | * |
---|
| 26 | * _Heap_Walk |
---|
| 27 | * |
---|
| 28 | * This kernel routine walks the heap and verifies its correctness. |
---|
| 29 | * |
---|
| 30 | * Input parameters: |
---|
| 31 | * the_heap - pointer to heap header |
---|
| 32 | * source - a numeric indicator of the invoker of this routine |
---|
| 33 | * do_dump - when TRUE print the information |
---|
| 34 | * |
---|
| 35 | * Output parameters: NONE |
---|
| 36 | */ |
---|
| 37 | |
---|
[962e894f] | 38 | #if !defined(RTEMS_HEAP_DEBUG) |
---|
[93b4e6ef] | 39 | |
---|
[962e894f] | 40 | boolean _Heap_Walk( |
---|
[93b4e6ef] | 41 | Heap_Control *the_heap, |
---|
| 42 | int source, |
---|
| 43 | boolean do_dump |
---|
| 44 | ) |
---|
| 45 | { |
---|
[962e894f] | 46 | return TRUE; |
---|
[93b4e6ef] | 47 | } |
---|
| 48 | |
---|
[962e894f] | 49 | #else /* defined(RTEMS_HEAP_DEBUG) */ |
---|
[93b4e6ef] | 50 | |
---|
| 51 | #include <stdio.h> |
---|
| 52 | |
---|
[962e894f] | 53 | boolean _Heap_Walk( |
---|
[93b4e6ef] | 54 | Heap_Control *the_heap, |
---|
| 55 | int source, |
---|
| 56 | boolean do_dump |
---|
| 57 | ) |
---|
| 58 | { |
---|
[962e894f] | 59 | Heap_Block *the_block = the_heap->start; |
---|
| 60 | Heap_Block *const end = the_heap->final; |
---|
| 61 | Heap_Block *const tail = _Heap_Tail(the_heap); |
---|
| 62 | int error = 0; |
---|
| 63 | int passes = 0; |
---|
[93b4e6ef] | 64 | |
---|
| 65 | /* |
---|
| 66 | * We don't want to allow walking the heap until we have |
---|
| 67 | * transferred control to the user task so we watch the |
---|
| 68 | * system state. |
---|
| 69 | */ |
---|
| 70 | |
---|
| 71 | if ( !_System_state_Is_up( _System_state_Get() ) ) |
---|
[962e894f] | 72 | return FALSE; |
---|
[93b4e6ef] | 73 | |
---|
[962e894f] | 74 | if (source < 0) |
---|
| 75 | source = the_heap->stats.instance; |
---|
[93b4e6ef] | 76 | |
---|
[962e894f] | 77 | if (do_dump == TRUE) |
---|
[a607d363] | 78 | printf("\nPASS: %d start %p final %p first %p last %p begin %p end %p\n", |
---|
[962e894f] | 79 | source, the_block, end, |
---|
| 80 | _Heap_First(the_heap), _Heap_Last(the_heap), |
---|
| 81 | the_heap->begin, the_heap->end); |
---|
[93b4e6ef] | 82 | |
---|
| 83 | /* |
---|
| 84 | * Handle the 1st block |
---|
| 85 | */ |
---|
| 86 | |
---|
[962e894f] | 87 | if (!_Heap_Is_prev_used(the_block)) { |
---|
[a607d363] | 88 | printf("PASS: %d !HEAP_PREV_USED flag of 1st block isn't set\n", source); |
---|
[93b4e6ef] | 89 | error = 1; |
---|
| 90 | } |
---|
| 91 | |
---|
[80f2885b] | 92 | if (the_block->prev_size != the_heap->page_size) { |
---|
[a607d363] | 93 | printf("PASS: %d !prev_size of 1st block isn't page_size\n", source); |
---|
[962e894f] | 94 | error = 1; |
---|
| 95 | } |
---|
| 96 | |
---|
| 97 | while ( the_block < end ) { |
---|
| 98 | uint32_t const the_size = _Heap_Block_size(the_block); |
---|
| 99 | Heap_Block *const next_block = _Heap_Block_at(the_block, the_size); |
---|
| 100 | boolean prev_used = _Heap_Is_prev_used(the_block); |
---|
| 101 | |
---|
| 102 | if (do_dump) { |
---|
[a607d363] | 103 | printf("PASS: %d block %p size %d(%c)", |
---|
[962e894f] | 104 | source, the_block, the_size, (prev_used ? 'U' : 'F')); |
---|
| 105 | if (prev_used) |
---|
[a607d363] | 106 | printf(" prev_size %d", the_block->prev_size); |
---|
[962e894f] | 107 | else |
---|
[a607d363] | 108 | printf(" (prev_size) %d", the_block->prev_size); |
---|
[93b4e6ef] | 109 | } |
---|
| 110 | |
---|
[962e894f] | 111 | if (!_Heap_Is_block_in(the_heap, next_block)) { |
---|
[a607d363] | 112 | if (do_dump) printf("\n"); |
---|
| 113 | printf("PASS: %d !block %p is out of heap\n", source, next_block); |
---|
[962e894f] | 114 | error = 1; |
---|
| 115 | break; |
---|
| 116 | } |
---|
[93b4e6ef] | 117 | |
---|
[962e894f] | 118 | if (!_Heap_Is_prev_used(next_block)) { |
---|
| 119 | if (do_dump) |
---|
[a607d363] | 120 | printf( " prev %p next %p", the_block->prev, the_block->next); |
---|
[962e894f] | 121 | if (_Heap_Block_size(the_block) != next_block->prev_size) { |
---|
[a607d363] | 122 | if (do_dump) printf("\n"); |
---|
| 123 | printf("PASS: %d !front and back sizes don't match", source); |
---|
[93b4e6ef] | 124 | error = 1; |
---|
[962e894f] | 125 | } |
---|
| 126 | if (!prev_used) { |
---|
[a607d363] | 127 | if (do_dump || error) printf("\n"); |
---|
| 128 | printf("PASS: %d !two consecutive blocks are free", source); |
---|
[962e894f] | 129 | error = 1; |
---|
| 130 | } |
---|
| 131 | |
---|
| 132 | { /* Check if 'the_block' is in the free block list */ |
---|
| 133 | Heap_Block* block = _Heap_First(the_heap); |
---|
| 134 | while(block != the_block && block != tail) |
---|
| 135 | block = block->next; |
---|
| 136 | if(block != the_block) { |
---|
[a607d363] | 137 | if (do_dump || error) printf("\n"); |
---|
| 138 | printf("PASS: %d !the_block not in the free list", source); |
---|
[962e894f] | 139 | error = 1; |
---|
[93b4e6ef] | 140 | } |
---|
| 141 | } |
---|
[962e894f] | 142 | |
---|
[93b4e6ef] | 143 | } |
---|
[a607d363] | 144 | if (do_dump || error) printf("\n"); |
---|
[93b4e6ef] | 145 | |
---|
[962e894f] | 146 | if (the_size < the_heap->min_block_size) { |
---|
[a607d363] | 147 | printf("PASS: %d !block size is too small\n", source); |
---|
[962e894f] | 148 | error = 1; |
---|
| 149 | break; |
---|
| 150 | } |
---|
| 151 | if (!_Heap_Is_aligned( the_size, the_heap->page_size)) { |
---|
[a607d363] | 152 | printf("PASS: %d !block size is misaligned\n", source); |
---|
[962e894f] | 153 | error = 1; |
---|
| 154 | } |
---|
| 155 | |
---|
| 156 | if (++passes > (do_dump ? 10 : 0) && error) |
---|
| 157 | break; |
---|
| 158 | |
---|
| 159 | the_block = next_block; |
---|
| 160 | } |
---|
| 161 | |
---|
| 162 | if (the_block != end) { |
---|
[a607d363] | 163 | printf("PASS: %d !last block address isn't equal to 'final'\n", source); |
---|
[962e894f] | 164 | error = 1; |
---|
| 165 | } |
---|
| 166 | |
---|
[80f2885b] | 167 | if (_Heap_Block_size(the_block) != the_heap->page_size) { |
---|
[a607d363] | 168 | printf("PASS: %d !last block's size isn't page_size\n", source); |
---|
[962e894f] | 169 | error = 1; |
---|
[93b4e6ef] | 170 | } |
---|
| 171 | |
---|
[962e894f] | 172 | if(do_dump && error) |
---|
| 173 | abort(); |
---|
| 174 | |
---|
| 175 | return error == 0; |
---|
| 176 | |
---|
[93b4e6ef] | 177 | } |
---|
[962e894f] | 178 | #endif /* defined(RTEMS_HEAP_DEBUG) */ |
---|