2
2
Copyright (c) 2010 Gerben van den Broeke
3
3
All rights reserved.
4
4
5
- malloc, free, realloc from avr-libc 1.7.0
6
- with minor modifications, by Paul Stoffregen
7
-
8
5
Redistribution and use in source and binary forms, with or without
9
6
modification, are permitted provided that the following conditions are met:
10
7
33
30
POSSIBILITY OF SUCH DAMAGE.
34
31
*/
35
32
33
+
34
+ /* $Id: malloc.c 2149 2010-06-09 20:45:37Z joerg_wunsch $ */
36
35
37
36
#include <stdlib.h>
38
- #include <inttypes.h>
39
- #include <string.h>
40
- #include <avr/io.h>
41
-
42
-
43
- #define __MALLOC_MARGIN__ 120
37
+ #include "sectionname.h"
38
+ #include "stdlib_private.h"
44
39
45
-
46
- struct __freelist {
47
- size_t sz ;
48
- struct __freelist * nx ;
49
- };
40
+ #include <avr/io.h>
50
41
51
42
/*
52
43
* Exported interface:
@@ -59,13 +50,16 @@ struct __freelist {
59
50
* with the data segment.
60
51
*/
61
52
53
+ /* May be changed by the user only before the first malloc() call. */
54
+
55
+ size_t __malloc_margin = 32 ;
56
+ char * __malloc_heap_start = & __heap_start ;
57
+ char * __malloc_heap_end = & __heap_end ;
62
58
63
- #define STACK_POINTER () ((char *)AVR_STACK_POINTER_REG)
64
- extern char __heap_start ;
65
- char * __brkval = & __heap_start ; // first location not yet allocated
66
- struct __freelist * __flp ; // freelist pointer (head of freelist)
67
- char * __brkval_maximum = 100 ;
59
+ char * __brkval ;
60
+ struct __freelist * __flp ;
68
61
62
+ ATTRIBUTE_CLIB_SECTION
69
63
void *
70
64
malloc (size_t len )
71
65
{
@@ -160,7 +154,11 @@ malloc(size_t len)
160
154
* Since we don't have an operating system, just make sure
161
155
* that we don't collide with the stack.
162
156
*/
163
- cp = STACK_POINTER () - __MALLOC_MARGIN__ ;
157
+ if (__brkval == 0 )
158
+ __brkval = __malloc_heap_start ;
159
+ cp = __malloc_heap_end ;
160
+ if (cp == 0 )
161
+ cp = STACK_POINTER () - __malloc_margin ;
164
162
if (cp <= __brkval )
165
163
/*
166
164
* Memory exhausted.
@@ -173,7 +171,6 @@ malloc(size_t len)
173
171
if (avail >= len && avail >= len + sizeof (size_t )) {
174
172
fp1 = (struct __freelist * )__brkval ;
175
173
__brkval += len + sizeof (size_t );
176
- __brkval_maximum = __brkval ;
177
174
fp1 -> sz = len ;
178
175
return & (fp1 -> nx );
179
176
}
@@ -184,6 +181,7 @@ malloc(size_t len)
184
181
}
185
182
186
183
184
+ ATTRIBUTE_CLIB_SECTION
187
185
void
188
186
free (void * p )
189
187
{
@@ -267,114 +265,3 @@ free(void *p)
267
265
}
268
266
}
269
267
270
-
271
-
272
- void *
273
- realloc (void * ptr , size_t len )
274
- {
275
- struct __freelist * fp1 , * fp2 , * fp3 , * ofp3 ;
276
- char * cp , * cp1 ;
277
- void * memp ;
278
- size_t s , incr ;
279
-
280
- /* Trivial case, required by C standard. */
281
- if (ptr == 0 )
282
- return malloc (len );
283
-
284
- cp1 = (char * )ptr ;
285
- cp1 -= sizeof (size_t );
286
- fp1 = (struct __freelist * )cp1 ;
287
-
288
- cp = (char * )ptr + len ; /* new next pointer */
289
- if (cp < cp1 )
290
- /* Pointer wrapped across top of RAM, fail. */
291
- return 0 ;
292
-
293
- /*
294
- * See whether we are growing or shrinking. When shrinking,
295
- * we split off a chunk for the released portion, and call
296
- * free() on it. Therefore, we can only shrink if the new
297
- * size is at least sizeof(struct __freelist) smaller than the
298
- * previous size.
299
- */
300
- if (len <= fp1 -> sz ) {
301
- /* The first test catches a possible unsigned int
302
- * rollover condition. */
303
- if (fp1 -> sz <= sizeof (struct __freelist ) ||
304
- len > fp1 -> sz - sizeof (struct __freelist ))
305
- return ptr ;
306
- fp2 = (struct __freelist * )cp ;
307
- fp2 -> sz = fp1 -> sz - len - sizeof (size_t );
308
- fp1 -> sz = len ;
309
- free (& (fp2 -> nx ));
310
- return ptr ;
311
- }
312
-
313
- /*
314
- * If we get here, we are growing. First, see whether there
315
- * is space in the free list on top of our current chunk.
316
- */
317
- incr = len - fp1 -> sz ;
318
- cp = (char * )ptr + fp1 -> sz ;
319
- fp2 = (struct __freelist * )cp ;
320
- for (s = 0 , ofp3 = 0 , fp3 = __flp ;
321
- fp3 ;
322
- ofp3 = fp3 , fp3 = fp3 -> nx ) {
323
- if (fp3 == fp2 && fp3 -> sz + sizeof (size_t ) >= incr ) {
324
- /* found something that fits */
325
- if (fp3 -> sz + sizeof (size_t ) - incr > sizeof (struct __freelist )) {
326
- /* split off a new freelist entry */
327
- cp = (char * )ptr + len ;
328
- fp2 = (struct __freelist * )cp ;
329
- fp2 -> nx = fp3 -> nx ;
330
- fp2 -> sz = fp3 -> sz - incr ;
331
- fp1 -> sz = len ;
332
- } else {
333
- /* it just fits, so use it entirely */
334
- fp1 -> sz += fp3 -> sz + sizeof (size_t );
335
- fp2 = fp3 -> nx ;
336
- }
337
- if (ofp3 )
338
- ofp3 -> nx = fp2 ;
339
- else
340
- __flp = fp2 ;
341
- return ptr ;
342
- }
343
- /*
344
- * Find the largest chunk on the freelist while
345
- * walking it.
346
- */
347
- if (fp3 -> sz > s )
348
- s = fp3 -> sz ;
349
- }
350
- /*
351
- * If we are the topmost chunk in memory, and there was no
352
- * large enough chunk on the freelist that could be re-used
353
- * (by a call to malloc() below), quickly extend the
354
- * allocation area if possible, without need to copy the old
355
- * data.
356
- */
357
- if (__brkval == (char * )ptr + fp1 -> sz && len > s ) {
358
- cp = (char * )ptr + len ;
359
- cp1 = STACK_POINTER () - __MALLOC_MARGIN__ ;
360
- if (cp < cp1 ) {
361
- __brkval = cp ;
362
- __brkval_maximum = cp ;
363
- fp1 -> sz = len ;
364
- return ptr ;
365
- }
366
- /* If that failed, we are out of luck. */
367
- return 0 ;
368
- }
369
-
370
- /*
371
- * Call malloc() for a new chunk, then copy over the data, and
372
- * release the old region.
373
- */
374
- if ((memp = malloc (len )) == 0 )
375
- return 0 ;
376
- memcpy (memp , ptr , fp1 -> sz );
377
- free (ptr );
378
- return memp ;
379
- }
380
-
0 commit comments