/* alloc.c - memory allocator for fixed size blocks */
/*
This code is replacement for malloc() and free(). It takes advantage
of the fact that all of my memory allocation is of known fixed-size
blocks. This particular implementation, however, is extremely general
and will do allocation of any number of different fixed-size blocks.
I will just give a simple example here. To allocate struct foo's, declare a handle to the foo space as:
struct freelist_head foo_freelist;
Initialize it:
memory_init(&foo_freelist,sizeof(struct foo),1000,200);
Here we have asked for an initial allocation of 1000 foo's. When that
runs out, further allocations will automatically be performed 200
foo's at a time. (Each allocation calls sbrk() so you want to
minimize them.)
To actually allocate and deallocate foo's, it helps to define two
macros as follow:
#define foo_new() (struct foo *)new(&foo_freelist)
#define foo_destroy(x) destroy(&oct_freelist_head,(Freelist *)(char *)x)
Now you can say things like:
foo1 = foo_new();
foo_destroy(foo1);
*/
#include
#include
#include "express/alloc.h"
#include "express/error.h"
/* just in case we are compiling by hand */
#ifndef ALLOC
#define ALLOC
#endif /*ALLOC*/
/** chop up big block into linked list of small blocks
* return 0 for failure
* \param flh freelist head
* \param bytes new memory size
*/
Freelist * create_freelist( struct freelist_head * flh, int bytes ) {
Freelist * current = ( Freelist * )malloc( bytes );
if( current == 0 ) {
return( 0 );
}
flh->freelist = current;
#ifndef NOSTAT
flh->create++;
/* set max to point to end of freelist */
if( ( char * )flh->freelist + bytes > ( char * )flh->max ) {
flh->max = ( char * )flh->freelist + bytes;
}
#endif
while( ( char * )current + flh->size <
( ( char * )flh->freelist + bytes ) ) {
current->next = ( Freelist * )( ¤t->memory + flh->size );
current = current->next;
}
current->next = NULL;
return( current );
}
void
_ALLOCinitialize() {
#ifdef DEBUG_MALLOC
malloc_debug( 2 );
#endif
}
/**
* \param flh freelist head
* \param size size of a single element
* \param alloc1 number to allocate initially
* \param alloc2 number to allocate if we run out
*/
void ALLOCinitialize( struct freelist_head * flh, unsigned int size, int alloc1, int alloc2 ) {
flh->size_elt = size; /* kludge for calloc-like behavior */
#ifndef NOSTAT
flh->alloc = flh->dealloc = flh->create = 0;
flh->max = 0;
#endif
/* make block large enough to hold the linked list pointer */
flh->size = ( size > sizeof( Freelist * ) ? size : sizeof( Freelist * ) );
/* set up for future allocations */
flh->bytes = flh->size * alloc2;
#ifdef REAL_MALLOC
return;
/*NOTREACHED*/
#else
if( 0 == create_freelist( flh, flh->size * alloc1 ) ) {
ERRORnospace();
}
#ifdef SPACE_PROFILE
flh->count = 0;
#endif /*SPACE_PROFILE*/
#endif
}
void * ALLOC_new( struct freelist_head * flh ) {
void *obj;
#ifndef NOSTAT
flh->alloc++;
#endif
#ifdef REAL_MALLOC
return( calloc( 1, flh->size_elt ) );
/*NOTREACHED*/
#else
if( flh->freelist == NULL && 0 == create_freelist( flh, flh->bytes ) ) {
ERRORnospace();
}
obj = &flh->freelist->memory;
flh->freelist = flh->freelist->next;
#ifndef NOSTAT
if( obj > flh->max ) {
abort();
}
#endif
#ifdef SPACE_PROFILE
flh->count++;
#endif /*SPACE_PROFILE*/
/* calloc-like */
memset( obj, 0, flh->size_elt );
return( obj );
#endif
}
void ALLOC_destroy( struct freelist_head * flh, Freelist * link ) {
#ifndef NOSTAT
flh->dealloc++;
#endif
#ifdef REAL_MALLOC
free( link );
return;
/*NOTREACHED*/
#else
link->next = flh->freelist;
flh->freelist = link;
#ifdef SPACE_PROFILE
flh->count--;
#endif /*SPACE_PROFILE*/
#endif
}
#ifdef ALLOC_MAIN
struct freelist_head oct_freelist;
#define new_oct() (struct oct *)new(&oct_freelist)
#define destroy_oct(oct) (destroy(&oct_freelist,(Freelist *)(char *)oct))
struct oct {
char a[16];
};
main() {
struct oct * o1, *o2, *o3, *o4, *o5, *o6;
memory_init( &oct_freelist, sizeof( struct oct ), 5, 2 );
o1 = new_oct();
fprintf( stderr, "o1 = %x\n", o1 );
o2 = new_oct();
fprintf( stderr, "o2 = %x\n", o2 );
o3 = new_oct();
fprintf( stderr, "o3 = %x\n", o3 );
o4 = new_oct();
fprintf( stderr, "o4 = %x\n", o4 );
o5 = new_oct();
fprintf( stderr, "o5 = %x\n", o5 );
o6 = new_oct();
fprintf( stderr, "o6 = %x\n", o6 );
destroy_oct( o1 );
destroy_oct( o2 );
o1 = new_oct();
fprintf( stderr, "o1 = %x\n", o1 );
o2 = new_oct();
fprintf( stderr, "o2 = %x\n", o2 );
o3 = new_oct();
fprintf( stderr, "o3 = %x\n", o3 );
o4 = new_oct();
fprintf( stderr, "o4 = %x\n", o4 );
o5 = new_oct();
fprintf( stderr, "o5 = %x\n", o5 );
}
#endif /*ALLOC_MAIN*/