blob: 3b928301ae8f38f42f7823e2ecf68196d17d508a (
plain) (
blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
|
/*
* Heap Handler
*
* COPYRIGHT (c) 1989-1999.
* On-Line Applications Research Corporation (OAR).
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.OARcorp.com/rtems/license.html.
*
* $Id$
*/
#include <rtems/system.h>
#include <rtems/score/sysstate.h>
#include <rtems/score/heap.h>
/*PAGE
*
* _Heap_Extend
*
* This routine grows the_heap memory area using the size bytes which
* begin at starting_address.
*
* Input parameters:
* the_heap - pointer to heap header.
* starting_address - pointer to the memory area.
* size - size in bytes of the memory block to allocate.
*
* Output parameters:
* *amount_extended - amount of memory added to the_heap
*/
Heap_Extend_status _Heap_Extend(
Heap_Control *the_heap,
void *starting_address,
unsigned32 size,
unsigned32 *amount_extended
)
{
Heap_Block *the_block;
unsigned32 *p;
/*
* The overhead was taken from the original heap memory.
*/
Heap_Block *old_final;
Heap_Block *new_final;
/*
* There are five possibilities for the location of starting
* address:
*
* 1. non-contiguous lower address (NOT SUPPORTED)
* 2. contiguous lower address (NOT SUPPORTED)
* 3. in the heap (ERROR)
* 4. contiguous higher address (SUPPORTED)
* 5. non-contiguous higher address (NOT SUPPORTED)
*
* As noted, this code only supports (4).
*/
if ( starting_address >= (void *) the_heap->start && /* case 3 */
starting_address <= (void *) the_heap->final
)
return HEAP_EXTEND_ERROR;
if ( starting_address < (void *) the_heap->start ) { /* cases 1 and 2 */
return HEAP_EXTEND_NOT_IMPLEMENTED; /* cases 1 and 2 */
} else { /* cases 4 and 5 */
the_block = (Heap_Block *)
_Addresses_Subtract_offset( starting_address, HEAP_OVERHEAD );
if ( the_block != the_heap->final )
return HEAP_EXTEND_NOT_IMPLEMENTED; /* case 5 */
}
/*
* Currently only case 4 should make it to this point.
* The basic trick is to make the extend area look like a used
* block and free it.
*/
*amount_extended = size;
old_final = the_heap->final;
new_final = _Addresses_Add_offset( old_final, size );
/* SAME AS: _Addresses_Add_offset( starting_address, size-HEAP_OVERHEAD ); */
the_heap->final = new_final;
old_final->front_flag =
new_final->back_flag = _Heap_Build_flag( size, HEAP_BLOCK_USED );
new_final->front_flag = HEAP_DUMMY_FLAG;
/*
* Must pass in address of "user" area
* So add in the offset field.
*/
p = (unsigned32 *) &old_final->next;
*p = sizeof(unsigned32);
p++;
_Heap_Free( the_heap, p );
return HEAP_EXTEND_SUCCESSFUL;
}
|