avr-libc-dev
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re[3]: [avr-libc-dev] malloc implementation


From: Bertolt Mildner
Subject: Re[3]: [avr-libc-dev] malloc implementation
Date: Fri, 17 Dec 2004 17:25:05 +0100

Hi Joerg,

And again found something. Sorry!
So here is a full revised version:

void *
malloc(size_t len)
{
        struct __freelist *current          = __flp;
        struct __freelist *before_current   = NULL;
        struct __freelist *candidate        = NULL;
        struct __freelist *before_candidate = NULL;

        size_t size = 0;
        char *cp;
        
        /*
         * Our minimum chunk size is the size of a pointer (plus the
         * size of the "sz" field, but we don't need to account for
         * this), otherwise we could not possibly fit a freelist entry
         * into the chunk later.
         */
        if (len < sizeof(struct __freelist) - sizeof(current->sz))
                len = sizeof(struct __freelist) - sizeof(current->sz);


        /*
         * Step 1: Walk the free list and try finding the smallest
         * chunk that is >= len.
         * While walking, note down the candidate (incl. its previous
         * entry). Stop walking if we found an exact match or if we
         * hit the end of the free list.
         * If we have a candidate we use it and probably split it.
         * If no candidate was found we continue in step 2.
         *
         */
        while ((current != NULL) && (size != len))
        {
          if ((current->sz >= len) &&
              ((current->sz == len) ||
               (size == 0) ||
               (size > current->sz)))
          {
            candidate = current;
            before_candidate = before_current;
            size = current->sz;
          }

          before_current = current;
          current = current->nx;
        }

        if (candadate != NULL) /* found one with sz >= len */
        {
          if ((size == len) || /* full match or too small to split */
              (size - len < sizeof(struct __freelist)))
          {
            if (before_candidate == NULL) /* match is first in list */
            {
              __flp = candidate->nx;
            }
            else
            {
              before_candidate->nx = candidate->nx;
            }

            return &(candidate->nx);
          }
          else /* split candidate */
          {
            /* resize remaining entry */
            candidate->sz -= len + sizeof(current->sz);
            
            /* create chunk to be returnd */
            cp = ((char*) (&candidate->nx)) + candidate->sz;
            current = (struct __freelist*) cp;
              
            current->sz = len;

            return &(current->nx);
          }
        }

        /*
         * Step 2: If the request could not be satisfied from a
         * freelist entry, just prepare a new chunk.  This means we
         * need to obtain more memory first.  The largest address just
         * not allocated so far is remembered in the brkval variable.
         * Under Unix, the "break value" was the end of the data
         * segment as dynamically requested from the operating system.
         * Since we don't have an operating system, just make sure
         * that we don't collide with the stack.
         */
        if (__brkval == 0)
                __brkval = __malloc_heap_start;
        cp = __malloc_heap_end;
        if (cp == 0)
                cp = STACK_POINTER() - __malloc_margin;
        size = cp - __brkval;
        /*
         * Both tests below are needed to catch the case len >= 0xfffe.
         */
        if (size >= len && size >= len + sizeof(current->sz)) {
                current = (struct freelist *)__brkval;
                __brkval += len + sizeof(current->sz);
                current->sz = len;
                return &(current->nx);
        }
        /*
         * Step 3: There's no help, just fail. :-/
         */
        return 0;
}


Bertolt

-- 
Best regards,
 Bertolt                            mailto:address@hidden





reply via email to

[Prev in Thread] Current Thread [Next in Thread]