[dea3eccb] | 1 | /** |
---|
| 2 | * @file |
---|
| 3 | * |
---|
| 4 | * @ingroup ScoreHeap |
---|
[80f2885b] | 5 | * |
---|
[dea3eccb] | 6 | * @brief Heap Handler implementation. |
---|
| 7 | */ |
---|
| 8 | |
---|
| 9 | /* |
---|
[80f2885b] | 10 | * COPYRIGHT (c) 1989-1999. |
---|
| 11 | * On-Line Applications Research Corporation (OAR). |
---|
| 12 | * |
---|
[518c2aeb] | 13 | * Copyright (c) 2009 embedded brains GmbH. |
---|
| 14 | * |
---|
[80f2885b] | 15 | * The license and distribution terms for this file may be |
---|
| 16 | * found in the file LICENSE in this distribution or at |
---|
[c499856] | 17 | * http://www.rtems.org/license/LICENSE. |
---|
[80f2885b] | 18 | */ |
---|
| 19 | |
---|
[2ff7d00] | 20 | #if HAVE_CONFIG_H |
---|
| 21 | #include "config.h" |
---|
| 22 | #endif |
---|
[80f2885b] | 23 | |
---|
| 24 | #include <rtems/system.h> |
---|
[e6f7f81] | 25 | #include <rtems/score/heapimpl.h> |
---|
[80f2885b] | 26 | |
---|
[518c2aeb] | 27 | static Heap_Resize_status _Heap_Resize_block_checked( |
---|
[371cea31] | 28 | Heap_Control *heap, |
---|
[518c2aeb] | 29 | Heap_Block *block, |
---|
| 30 | uintptr_t alloc_begin, |
---|
[dea3eccb] | 31 | uintptr_t new_alloc_size, |
---|
| 32 | uintptr_t *old_size, |
---|
| 33 | uintptr_t *new_size |
---|
[80f2885b] | 34 | ) |
---|
| 35 | { |
---|
[371cea31] | 36 | Heap_Statistics *const stats = &heap->stats; |
---|
[dea3eccb] | 37 | |
---|
[518c2aeb] | 38 | uintptr_t const block_begin = (uintptr_t) block; |
---|
| 39 | uintptr_t block_size = _Heap_Block_size( block ); |
---|
| 40 | uintptr_t block_end = block_begin + block_size; |
---|
[dea3eccb] | 41 | |
---|
[4d73c38] | 42 | uintptr_t alloc_size = block_end - alloc_begin + HEAP_ALLOC_BONUS; |
---|
[80f2885b] | 43 | |
---|
[518c2aeb] | 44 | Heap_Block *next_block = _Heap_Block_at( block, block_size ); |
---|
| 45 | uintptr_t next_block_size = _Heap_Block_size( next_block ); |
---|
[721fe34] | 46 | bool next_block_is_free = _Heap_Is_free( next_block ); |
---|
[80f2885b] | 47 | |
---|
[dea3eccb] | 48 | _HAssert( _Heap_Is_block_in_heap( heap, next_block ) ); |
---|
| 49 | _HAssert( _Heap_Is_prev_used( next_block ) ); |
---|
[80f2885b] | 50 | |
---|
[dea3eccb] | 51 | *old_size = alloc_size; |
---|
[80f2885b] | 52 | |
---|
[518c2aeb] | 53 | if ( next_block_is_free ) { |
---|
| 54 | block_size += next_block_size; |
---|
| 55 | alloc_size += next_block_size; |
---|
| 56 | } |
---|
[80f2885b] | 57 | |
---|
[518c2aeb] | 58 | if ( new_alloc_size > alloc_size ) { |
---|
| 59 | return HEAP_RESIZE_UNSATISFIED; |
---|
| 60 | } |
---|
[dea3eccb] | 61 | |
---|
[518c2aeb] | 62 | if ( next_block_is_free ) { |
---|
| 63 | _Heap_Block_set_size( block, block_size ); |
---|
[dea3eccb] | 64 | |
---|
[518c2aeb] | 65 | _Heap_Free_list_remove( next_block ); |
---|
[dea3eccb] | 66 | |
---|
[518c2aeb] | 67 | next_block = _Heap_Block_at( block, block_size ); |
---|
| 68 | next_block->size_and_flag |= HEAP_PREV_BLOCK_USED; |
---|
[80f2885b] | 69 | |
---|
[518c2aeb] | 70 | /* Statistics */ |
---|
| 71 | --stats->free_blocks; |
---|
| 72 | stats->free_size -= next_block_size; |
---|
| 73 | } |
---|
[80f2885b] | 74 | |
---|
[518c2aeb] | 75 | block = _Heap_Block_allocate( heap, block, alloc_begin, new_alloc_size ); |
---|
[dea3eccb] | 76 | |
---|
[518c2aeb] | 77 | block_size = _Heap_Block_size( block ); |
---|
| 78 | next_block = _Heap_Block_at( block, block_size ); |
---|
[4d73c38] | 79 | *new_size = (uintptr_t) next_block - alloc_begin + HEAP_ALLOC_BONUS; |
---|
[dea3eccb] | 80 | |
---|
[518c2aeb] | 81 | /* Statistics */ |
---|
| 82 | ++stats->resizes; |
---|
[dea3eccb] | 83 | |
---|
[518c2aeb] | 84 | return HEAP_RESIZE_SUCCESSFUL; |
---|
| 85 | } |
---|
[dea3eccb] | 86 | |
---|
[518c2aeb] | 87 | Heap_Resize_status _Heap_Resize_block( |
---|
| 88 | Heap_Control *heap, |
---|
| 89 | void *alloc_begin_ptr, |
---|
| 90 | uintptr_t new_alloc_size, |
---|
| 91 | uintptr_t *old_size, |
---|
| 92 | uintptr_t *new_size |
---|
| 93 | ) |
---|
| 94 | { |
---|
| 95 | uintptr_t const page_size = heap->page_size; |
---|
[dea3eccb] | 96 | |
---|
[518c2aeb] | 97 | uintptr_t const alloc_begin = (uintptr_t) alloc_begin_ptr; |
---|
[dea3eccb] | 98 | |
---|
[518c2aeb] | 99 | Heap_Block *const block = _Heap_Block_of_alloc_area( alloc_begin, page_size ); |
---|
[dea3eccb] | 100 | |
---|
[518c2aeb] | 101 | *old_size = 0; |
---|
| 102 | *new_size = 0; |
---|
[dea3eccb] | 103 | |
---|
[518c2aeb] | 104 | if ( _Heap_Is_block_in_heap( heap, block ) ) { |
---|
[678b206f] | 105 | _Heap_Protection_block_check( heap, block ); |
---|
[c497657] | 106 | |
---|
| 107 | /* TODO: Free only the next block if necessary */ |
---|
| 108 | _Heap_Protection_free_all_delayed_blocks( heap ); |
---|
| 109 | |
---|
[518c2aeb] | 110 | return _Heap_Resize_block_checked( |
---|
| 111 | heap, |
---|
| 112 | block, |
---|
| 113 | alloc_begin, |
---|
| 114 | new_alloc_size, |
---|
| 115 | old_size, |
---|
| 116 | new_size |
---|
| 117 | ); |
---|
[80f2885b] | 118 | } |
---|
[678b206f] | 119 | return HEAP_RESIZE_FATAL_ERROR; |
---|
[80f2885b] | 120 | } |
---|