Back to index

cell-binutils  2.17cvs20070401
Classes | Defines | Functions
objalloc.c File Reference
#include "config.h"
#include "ansidecl.h"
#include "objalloc.h"
#include <stdio.h>
#include <stddef.h>

Go to the source code of this file.

Classes

struct  objalloc_chunk

Defines

#define CHUNK_HEADER_SIZE
#define CHUNK_SIZE   (4096 - 32)
#define BIG_REQUEST   (512)

Functions

PTR malloc (size_t)
void free (PTR)
struct objallocobjalloc_create (void)
PTR _objalloc_alloc (struct objalloc *o, unsigned long len)
void objalloc_free (struct objalloc *o)
void objalloc_free_block (struct objalloc *o, PTR block)

Class Documentation

struct objalloc_chunk

Definition at line 58 of file objalloc.c.

Collaboration diagram for objalloc_chunk:
Class Members
char * current_ptr
struct objalloc_chunk * next

Define Documentation

#define BIG_REQUEST   (512)

Definition at line 81 of file objalloc.c.

Value:
((sizeof (struct objalloc_chunk) + OBJALLOC_ALIGN - 1)  \
   &~ (OBJALLOC_ALIGN - 1))

Definition at line 70 of file objalloc.c.

#define CHUNK_SIZE   (4096 - 32)

Definition at line 77 of file objalloc.c.


Function Documentation

Definition at line 115 of file objalloc.c.

{
  /* We avoid confusion from zero sized objects by always allocating
     at least 1 byte.  */
  if (len == 0)
    len = 1;

  len = (len + OBJALLOC_ALIGN - 1) &~ (OBJALLOC_ALIGN - 1);

  if (len <= o->current_space)
    {
      o->current_ptr += len;
      o->current_space -= len;
      return (PTR) (o->current_ptr - len);
    }

  if (len >= BIG_REQUEST)
    {
      char *ret;
      struct objalloc_chunk *chunk;

      ret = (char *) malloc (CHUNK_HEADER_SIZE + len);
      if (ret == NULL)
       return NULL;

      chunk = (struct objalloc_chunk *) ret;
      chunk->next = (struct objalloc_chunk *) o->chunks;
      chunk->current_ptr = o->current_ptr;

      o->chunks = (PTR) chunk;

      return (PTR) (ret + CHUNK_HEADER_SIZE);
    }
  else
    {
      struct objalloc_chunk *chunk;

      chunk = (struct objalloc_chunk *) malloc (CHUNK_SIZE);
      if (chunk == NULL)
       return NULL;
      chunk->next = (struct objalloc_chunk *) o->chunks;
      chunk->current_ptr = NULL;

      o->current_ptr = (char *) chunk + CHUNK_HEADER_SIZE;
      o->current_space = CHUNK_SIZE - CHUNK_HEADER_SIZE;

      o->chunks = (PTR) chunk;

      return objalloc_alloc (o, len);
    }
}

Here is the call graph for this function:

void free ( PTR  )
PTR malloc ( size_t  )
struct objalloc* objalloc_create ( void  ) [read]

Definition at line 86 of file objalloc.c.

{
  struct objalloc *ret;
  struct objalloc_chunk *chunk;

  ret = (struct objalloc *) malloc (sizeof *ret);
  if (ret == NULL)
    return NULL;

  ret->chunks = (PTR) malloc (CHUNK_SIZE);
  if (ret->chunks == NULL)
    {
      free (ret);
      return NULL;
    }

  chunk = (struct objalloc_chunk *) ret->chunks;
  chunk->next = NULL;
  chunk->current_ptr = NULL;

  ret->current_ptr = (char *) chunk + CHUNK_HEADER_SIZE;
  ret->current_space = CHUNK_SIZE - CHUNK_HEADER_SIZE;

  return ret;
}

Here is the call graph for this function:

Here is the caller graph for this function:

void objalloc_free ( struct objalloc o)

Definition at line 170 of file objalloc.c.

{
  struct objalloc_chunk *l;

  l = (struct objalloc_chunk *) o->chunks;
  while (l != NULL)
    {
      struct objalloc_chunk *next;

      next = l->next;
      free (l);
      l = next;
    }

  free (o);
}

Here is the call graph for this function:

Here is the caller graph for this function:

void objalloc_free_block ( struct objalloc o,
PTR  block 
)

Definition at line 191 of file objalloc.c.

{
  struct objalloc_chunk *p, *small;
  char *b = (char *) block;

  /* First set P to the chunk which contains the block we are freeing,
     and set Q to the last small object chunk we see before P.  */
  small = NULL;
  for (p = (struct objalloc_chunk *) o->chunks; p != NULL; p = p->next)
    {
      if (p->current_ptr == NULL)
       {
         if (b > (char *) p && b < (char *) p + CHUNK_SIZE)
           break;
         small = p;
       }
      else
       {
         if (b == (char *) p + CHUNK_HEADER_SIZE)
           break;
       }
    }

  /* If we can't find the chunk, the caller has made a mistake.  */
  if (p == NULL)
    abort ();

  if (p->current_ptr == NULL)
    {
      struct objalloc_chunk *q;
      struct objalloc_chunk *first;

      /* The block is in a chunk containing small objects.  We can
        free every chunk through SMALL, because they have certainly
        been allocated more recently.  After SMALL, we will not see
        any chunks containing small objects; we can free any big
        chunk if the current_ptr is greater than or equal to B.  We
        can then reset the new current_ptr to B.  */

      first = NULL;
      q = (struct objalloc_chunk *) o->chunks;
      while (q != p)
       {
         struct objalloc_chunk *next;

         next = q->next;
         if (small != NULL)
           {
             if (small == q)
              small = NULL;
             free (q);
           }
         else if (q->current_ptr > b)
           free (q);
         else if (first == NULL)
           first = q;

         q = next;
       }

      if (first == NULL)
       first = p;
      o->chunks = (PTR) first;

      /* Now start allocating from this small block again.  */
      o->current_ptr = b;
      o->current_space = ((char *) p + CHUNK_SIZE) - b;
    }
  else
    {
      struct objalloc_chunk *q;
      char *current_ptr;

      /* This block is in a large chunk by itself.  We can free
         everything on the list up to and including this block.  We
         then start allocating from the next chunk containing small
         objects, setting current_ptr from the value stored with the
         large chunk we are freeing.  */

      current_ptr = p->current_ptr;
      p = p->next;

      q = (struct objalloc_chunk *) o->chunks;
      while (q != p)
       {
         struct objalloc_chunk *next;

         next = q->next;
         free (q);
         q = next;
       }

      o->chunks = (PTR) p;

      while (p->current_ptr != NULL)
       p = p->next;

      o->current_ptr = current_ptr;
      o->current_space = ((char *) p + CHUNK_SIZE) - current_ptr;
    }
}

Here is the call graph for this function: