|
-
-
-
- #include <stdlib.h>
- #include <inttypes.h>
- #include <string.h>
- #include <avr/io.h>
-
- extern char __heap_start;
- extern char __heap_end;
- #define STACK_POINTER() ((char *)AVR_STACK_POINTER_REG)
-
- struct __freelist {
- size_t sz;
- struct __freelist *nx;
- };
-
-
-
- size_t __malloc_margin = 128;
- char *__malloc_heap_start = &__heap_start;
- char *__malloc_heap_end = &__heap_end;
-
- char *__brkval = NULL;
- struct __freelist *__flp;
-
-
-
-
-
- void *
- malloc(size_t len)
- {
- struct __freelist *fp1, *fp2, *sfp1, *sfp2;
- char *cp;
- size_t s, avail;
-
-
-
- if (len < sizeof(struct __freelist) - sizeof(size_t))
- len = sizeof(struct __freelist) - sizeof(size_t);
-
-
-
- for (s = 0, fp1 = __flp, fp2 = 0;
- fp1;
- fp2 = fp1, fp1 = fp1->nx) {
- if (fp1->sz < len)
- continue;
- if (fp1->sz == len) {
-
-
- if (fp2)
- fp2->nx = fp1->nx;
- else
- __flp = fp1->nx;
- return &(fp1->nx);
- }
- else {
- if (s == 0 || fp1->sz < s) {
-
- s = fp1->sz;
- sfp1 = fp1;
- sfp2 = fp2;
- }
- }
- }
-
-
- if (s) {
- if (s - len < sizeof(struct __freelist)) {
-
- if (sfp2)
- sfp2->nx = sfp1->nx;
- else
- __flp = sfp1->nx;
- return &(sfp1->nx);
- }
-
-
- cp = (char *)sfp1;
- s -= len;
- cp += s;
- sfp2 = (struct __freelist *)cp;
- sfp2->sz = len;
- sfp1->sz = s - sizeof(size_t);
- return &(sfp2->nx);
- }
-
-
- if (__brkval == 0)
- __brkval = __malloc_heap_start;
- cp = __malloc_heap_end;
- if (cp == 0)
- cp = STACK_POINTER() - __malloc_margin;
- if (cp <= __brkval)
-
-
- return 0;
- avail = cp - __brkval;
-
-
- if (avail >= len && avail >= len + sizeof(size_t)) {
- fp1 = (struct __freelist *)__brkval;
- __brkval += len + sizeof(size_t);
-
- fp1->sz = len;
- return &(fp1->nx);
- }
-
-
- return 0;
- }
-
-
- void
- free(void *p)
- {
- struct __freelist *fp1, *fp2, *fpnew;
- char *cp1, *cp2, *cpnew;
-
-
- if (p == 0)
- return;
-
- cpnew = p;
- cpnew -= sizeof(size_t);
- fpnew = (struct __freelist *)cpnew;
- fpnew->nx = 0;
-
-
-
- if (__flp == 0) {
- if ((char *)p + fpnew->sz == __brkval)
- __brkval = cpnew;
- else
- __flp = fpnew;
- return;
- }
-
-
-
- for (fp1 = __flp, fp2 = 0;
- fp1;
- fp2 = fp1, fp1 = fp1->nx) {
- if (fp1 < fpnew)
- continue;
- cp1 = (char *)fp1;
- fpnew->nx = fp1;
- if ((char *)&(fpnew->nx) + fpnew->sz == cp1) {
-
- fpnew->sz += fp1->sz + sizeof(size_t);
- fpnew->nx = fp1->nx;
- }
- if (fp2 == 0) {
-
- __flp = fpnew;
- return;
- }
- break;
- }
-
-
- fp2->nx = fpnew;
- cp2 = (char *)&(fp2->nx);
- if (cp2 + fp2->sz == cpnew) {
-
- fp2->sz += fpnew->sz + sizeof(size_t);
- fp2->nx = fpnew->nx;
- }
-
-
- for (fp1 = __flp, fp2 = 0;
- fp1->nx != 0;
- fp2 = fp1, fp1 = fp1->nx)
- ;
- cp2 = (char *)&(fp1->nx);
- if (cp2 + fp1->sz == __brkval) {
- if (fp2 == NULL)
-
- __flp = NULL;
- else
- fp2->nx = NULL;
- __brkval = cp2 - sizeof(size_t);
- }
- }
-
-
-
- void *
- realloc(void *ptr, size_t len)
- {
- struct __freelist *fp1, *fp2, *fp3, *ofp3;
- char *cp, *cp1;
- void *memp;
- size_t s, incr;
-
-
- if (ptr == 0)
- return malloc(len);
-
- cp1 = (char *)ptr;
- cp1 -= sizeof(size_t);
- fp1 = (struct __freelist *)cp1;
-
- cp = (char *)ptr + len;
- if (cp < cp1)
-
- return 0;
-
-
-
- if (len <= fp1->sz) {
-
-
- if (fp1->sz <= sizeof(struct __freelist) ||
- len > fp1->sz - sizeof(struct __freelist))
- return ptr;
- fp2 = (struct __freelist *)cp;
- fp2->sz = fp1->sz - len - sizeof(size_t);
- fp1->sz = len;
- free(&(fp2->nx));
- return ptr;
- }
-
-
-
- incr = len - fp1->sz;
- cp = (char *)ptr + fp1->sz;
- fp2 = (struct __freelist *)cp;
- for (s = 0, ofp3 = 0, fp3 = __flp;
- fp3;
- ofp3 = fp3, fp3 = fp3->nx) {
- if (fp3 == fp2 && fp3->sz + sizeof(size_t) >= incr) {
-
- if (fp3->sz + sizeof(size_t) - incr > sizeof(struct __freelist)) {
-
- cp = (char *)ptr + len;
- fp2 = (struct __freelist *)cp;
- fp2->nx = fp3->nx;
- fp2->sz = fp3->sz - incr;
- fp1->sz = len;
- } else {
-
- fp1->sz += fp3->sz + sizeof(size_t);
- fp2 = fp3->nx;
- }
- if (ofp3)
- ofp3->nx = fp2;
- else
- __flp = fp2;
- return ptr;
- }
-
-
- if (fp3->sz > s)
- s = fp3->sz;
- }
-
-
- if (__brkval == (char *)ptr + fp1->sz && len > s) {
- cp = (char *)ptr + len;
- cp1 = STACK_POINTER() - __malloc_margin;
- if (cp < cp1) {
- __brkval = cp;
-
- fp1->sz = len;
- return ptr;
- }
-
- return 0;
- }
-
-
-
- if ((memp = malloc(len)) == 0)
- return 0;
- memcpy(memp, ptr, fp1->sz);
- free(ptr);
- return memp;
- }
|