|
@@ -52,6 +52,9 @@ static userptr_t top = UNULL;
|
52
|
52
|
/** Bottom of heap (current lowest allocated block) */
|
53
|
53
|
static userptr_t bottom = UNULL;
|
54
|
54
|
|
|
55
|
+/** Remaining space on heap */
|
|
56
|
+static size_t heap_size;
|
|
57
|
+
|
55
|
58
|
/**
|
56
|
59
|
* Initialise external heap
|
57
|
60
|
*
|
|
@@ -59,12 +62,12 @@ static userptr_t bottom = UNULL;
|
59
|
62
|
*/
|
60
|
63
|
static int init_eheap ( void ) {
|
61
|
64
|
struct memory_map memmap;
|
62
|
|
- unsigned long heap_size = 0;
|
63
|
65
|
unsigned int i;
|
64
|
66
|
|
65
|
67
|
DBG ( "Allocating external heap\n" );
|
66
|
68
|
|
67
|
69
|
get_memmap ( &memmap );
|
|
70
|
+ heap_size = 0;
|
68
|
71
|
for ( i = 0 ; i < memmap.count ; i++ ) {
|
69
|
72
|
struct memory_region *region = &memmap.regions[i];
|
70
|
73
|
unsigned long r_start, r_end;
|
|
@@ -99,8 +102,8 @@ static int init_eheap ( void ) {
|
99
|
102
|
return -ENOMEM;
|
100
|
103
|
}
|
101
|
104
|
|
102
|
|
- DBG ( "External heap grows downwards from %lx\n",
|
103
|
|
- user_to_phys ( top, 0 ) );
|
|
105
|
+ DBG ( "External heap grows downwards from %lx (size %zx)\n",
|
|
106
|
+ user_to_phys ( top, 0 ), heap_size );
|
104
|
107
|
return 0;
|
105
|
108
|
}
|
106
|
109
|
|
|
@@ -110,6 +113,7 @@ static int init_eheap ( void ) {
|
110
|
113
|
*/
|
111
|
114
|
static void ecollect_free ( void ) {
|
112
|
115
|
struct external_memory extmem;
|
|
116
|
+ size_t len;
|
113
|
117
|
|
114
|
118
|
/* Walk the free list and collect empty blocks */
|
115
|
119
|
while ( bottom != top ) {
|
|
@@ -119,8 +123,9 @@ static void ecollect_free ( void ) {
|
119
|
123
|
break;
|
120
|
124
|
DBG ( "EXTMEM freeing [%lx,%lx)\n", user_to_phys ( bottom, 0 ),
|
121
|
125
|
user_to_phys ( bottom, extmem.size ) );
|
122
|
|
- bottom = userptr_add ( bottom,
|
123
|
|
- ( extmem.size + sizeof ( extmem ) ) );
|
|
126
|
+ len = ( extmem.size + sizeof ( extmem ) );
|
|
127
|
+ bottom = userptr_add ( bottom, len );
|
|
128
|
+ heap_size += len;
|
124
|
129
|
}
|
125
|
130
|
}
|
126
|
131
|
|
|
@@ -153,7 +158,12 @@ static userptr_t memtop_urealloc ( userptr_t ptr, size_t new_size ) {
|
153
|
158
|
sizeof ( extmem ) );
|
154
|
159
|
} else {
|
155
|
160
|
/* Create a zero-length block */
|
|
161
|
+ if ( heap_size < sizeof ( extmem ) ) {
|
|
162
|
+ DBG ( "EXTMEM out of space\n" );
|
|
163
|
+ return UNULL;
|
|
164
|
+ }
|
156
|
165
|
ptr = bottom = userptr_add ( bottom, -sizeof ( extmem ) );
|
|
166
|
+ heap_size -= sizeof ( extmem );
|
157
|
167
|
DBG ( "EXTMEM allocating [%lx,%lx)\n",
|
158
|
168
|
user_to_phys ( ptr, 0 ), user_to_phys ( ptr, 0 ) );
|
159
|
169
|
extmem.size = 0;
|
|
@@ -163,6 +173,10 @@ static userptr_t memtop_urealloc ( userptr_t ptr, size_t new_size ) {
|
163
|
173
|
/* Expand/shrink block if possible */
|
164
|
174
|
if ( ptr == bottom ) {
|
165
|
175
|
/* Update block */
|
|
176
|
+ if ( new_size > ( heap_size - extmem.size ) ) {
|
|
177
|
+ DBG ( "EXTMEM out of space\n" );
|
|
178
|
+ return UNULL;
|
|
179
|
+ }
|
166
|
180
|
new = userptr_add ( ptr, - ( new_size - extmem.size ) );
|
167
|
181
|
align = ( user_to_phys ( new, 0 ) & ( EM_ALIGN - 1 ) );
|
168
|
182
|
new_size += align;
|
|
@@ -174,8 +188,9 @@ static userptr_t memtop_urealloc ( userptr_t ptr, size_t new_size ) {
|
174
|
188
|
user_to_phys ( new, new_size ));
|
175
|
189
|
memmove_user ( new, 0, ptr, 0, ( ( extmem.size < new_size ) ?
|
176
|
190
|
extmem.size : new_size ) );
|
177
|
|
- extmem.size = new_size;
|
178
|
191
|
bottom = new;
|
|
192
|
+ heap_size -= ( new_size - extmem.size );
|
|
193
|
+ extmem.size = new_size;
|
179
|
194
|
} else {
|
180
|
195
|
/* Cannot expand; can only pretend to shrink */
|
181
|
196
|
if ( new_size > extmem.size ) {
|
|
@@ -193,7 +208,7 @@ static userptr_t memtop_urealloc ( userptr_t ptr, size_t new_size ) {
|
193
|
208
|
|
194
|
209
|
/* Collect any free blocks and update hidden memory region */
|
195
|
210
|
ecollect_free();
|
196
|
|
- hide_umalloc ( user_to_phys ( bottom, -sizeof ( extmem ) ),
|
|
211
|
+ hide_umalloc ( user_to_phys ( bottom, 0 ),
|
197
|
212
|
user_to_phys ( top, 0 ) );
|
198
|
213
|
|
199
|
214
|
return ( new_size ? new : UNOWHERE );
|