22 Copyright (c) 2010 Gerben van den Broeke
33 All rights reserved.
44
5- malloc, free, realloc from avr-libc 1.7.0
6- with minor modifications, by Paul Stoffregen
7-
85 Redistribution and use in source and binary forms, with or without
96 modification, are permitted provided that the following conditions are met:
107
3330 POSSIBILITY OF SUCH DAMAGE.
3431*/
3532
33+
34+ /* $Id: malloc.c 2149 2010-06-09 20:45:37Z joerg_wunsch $ */
3635
3736#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"
4439
45-
46- struct __freelist {
47- size_t sz ;
48- struct __freelist * nx ;
49- };
40+ #include <avr/io.h>
5041
5142/*
5243 * Exported interface:
@@ -59,13 +50,16 @@ struct __freelist {
5950 * with the data segment.
6051 */
6152
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 ;
6258
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 ;
6861
62+ ATTRIBUTE_CLIB_SECTION
6963void *
7064malloc (size_t len )
7165{
@@ -160,7 +154,11 @@ malloc(size_t len)
160154 * Since we don't have an operating system, just make sure
161155 * that we don't collide with the stack.
162156 */
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 ;
164162 if (cp <= __brkval )
165163 /*
166164 * Memory exhausted.
@@ -173,7 +171,6 @@ malloc(size_t len)
173171 if (avail >= len && avail >= len + sizeof (size_t )) {
174172 fp1 = (struct __freelist * )__brkval ;
175173 __brkval += len + sizeof (size_t );
176- __brkval_maximum = __brkval ;
177174 fp1 -> sz = len ;
178175 return & (fp1 -> nx );
179176 }
@@ -184,6 +181,7 @@ malloc(size_t len)
184181}
185182
186183
184+ ATTRIBUTE_CLIB_SECTION
187185void
188186free (void * p )
189187{
@@ -267,114 +265,3 @@ free(void *p)
267265 }
268266}
269267
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