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 | * 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/sysstate.h> |
---|
26 | #include <rtems/score/heap.h> |
---|
27 | |
---|
28 | Heap_Extend_status _Heap_Extend( |
---|
29 | Heap_Control *heap, |
---|
30 | void *area_begin_ptr, |
---|
31 | uintptr_t area_size, |
---|
32 | uintptr_t *amount_extended |
---|
33 | ) |
---|
34 | { |
---|
35 | Heap_Statistics *const stats = &heap->stats; |
---|
36 | uintptr_t const area_begin = (uintptr_t) area_begin_ptr; |
---|
37 | uintptr_t const heap_area_begin = heap->area_begin; |
---|
38 | uintptr_t const heap_area_end = heap->area_end; |
---|
39 | uintptr_t const new_heap_area_end = heap_area_end + area_size; |
---|
40 | uintptr_t extend_size = 0; |
---|
41 | Heap_Block *const last_block = heap->last_block; |
---|
42 | |
---|
43 | /* |
---|
44 | * There are five possibilities for the location of starting |
---|
45 | * address: |
---|
46 | * |
---|
47 | * 1. non-contiguous lower address (NOT SUPPORTED) |
---|
48 | * 2. contiguous lower address (NOT SUPPORTED) |
---|
49 | * 3. in the heap (ERROR) |
---|
50 | * 4. contiguous higher address (SUPPORTED) |
---|
51 | * 5. non-contiguous higher address (NOT SUPPORTED) |
---|
52 | * |
---|
53 | * As noted, this code only supports (4). |
---|
54 | */ |
---|
55 | |
---|
56 | if ( area_begin >= heap_area_begin && area_begin < heap_area_end ) { |
---|
57 | return HEAP_EXTEND_ERROR; /* case 3 */ |
---|
58 | } else if ( area_begin != heap_area_end ) { |
---|
59 | return HEAP_EXTEND_NOT_IMPLEMENTED; /* cases 1, 2, and 5 */ |
---|
60 | } |
---|
61 | |
---|
62 | /* |
---|
63 | * Currently only case 4 should make it to this point. |
---|
64 | * The basic trick is to make the extend area look like a used |
---|
65 | * block and free it. |
---|
66 | */ |
---|
67 | |
---|
68 | heap->area_end = new_heap_area_end; |
---|
69 | |
---|
70 | extend_size = new_heap_area_end |
---|
71 | - (uintptr_t) last_block - HEAP_BLOCK_HEADER_SIZE; |
---|
72 | extend_size = _Heap_Align_down( extend_size, heap->page_size ); |
---|
73 | |
---|
74 | *amount_extended = extend_size; |
---|
75 | |
---|
76 | if( extend_size >= heap->min_block_size ) { |
---|
77 | Heap_Block *const new_last_block = _Heap_Block_at( last_block, extend_size ); |
---|
78 | |
---|
79 | _Heap_Block_set_size( last_block, extend_size ); |
---|
80 | |
---|
81 | new_last_block->size_and_flag = |
---|
82 | ((uintptr_t) heap->first_block - (uintptr_t) new_last_block) |
---|
83 | | HEAP_PREV_BLOCK_USED; |
---|
84 | |
---|
85 | heap->last_block = new_last_block; |
---|
86 | |
---|
87 | /* Statistics */ |
---|
88 | stats->size += extend_size; |
---|
89 | ++stats->used_blocks; |
---|
90 | --stats->frees; /* Do not count subsequent call as actual free() */ |
---|
91 | |
---|
92 | _Heap_Free( heap, (void *) _Heap_Alloc_area_of_block( last_block )); |
---|
93 | } |
---|
94 | |
---|
95 | return HEAP_EXTEND_SUCCESSFUL; |
---|
96 | } |
---|