Be a bit more careful with memory alignemnt in halloc

darcs-hash:20060930121917-ac50b-6292696663684a38844b4c21360274b365e52969.gz
This commit is contained in:
axel 2006-09-30 22:19:17 +10:00
parent 92df4a6d91
commit 421ebcc2d7

View File

@ -24,9 +24,12 @@
#define HALLOC_BLOCK_SIZE 128 #define HALLOC_BLOCK_SIZE 128
/** /**
Maximum size of trailing halloc space to refuse to discard Maximum size of trailing halloc space to refuse to discard. This is
set to be larger on 64-bit platforms, since we don't want to get
'stuck' with an unusably small slice of memory, and what is
unusably small often depends on pointer size.
*/ */
#define HALLOC_SCRAP_SIZE 16 #define HALLOC_SCRAP_SIZE (4*sizeof(void *))
#ifdef HALLOC_DEBUG #ifdef HALLOC_DEBUG
/** /**
@ -71,24 +74,32 @@ typedef struct halloc
/** /**
Amount of free space in the scratch area Amount of free space in the scratch area
*/ */
size_t scratch_free; ssize_t scratch_free;
#if __STDC_VERSION__ < 199901L
/**
The actual data. Made to be of type long long to make sure memory alignment is in order.
*/
long long data[1]; // Waste one byte on non-C99 compilers... :-(
#else
long long data[];
#endif
} }
halloc_t; halloc_t;
static void *align_ptr( void *in )
{
unsigned long step = maxi(sizeof(double),sizeof(void *));
unsigned long inc = step-1;
unsigned long long_in = (long)in;
unsigned long long_out = ((long_in+inc)/step)*step;
return (void *)long_out;
}
static size_t align_sz( size_t in )
{
size_t step = maxi(sizeof(double),sizeof(void *));
size_t inc = step-1;
return ((in+inc)/step)*step;
}
/** /**
Get the offset of the halloc structure before a data block Get the offset of the halloc structure before a data block
*/ */
static halloc_t *halloc_from_data( void *data ) static halloc_t *halloc_from_data( void *data )
{ {
return (halloc_t *)(((char *)data) - sizeof( halloc_t ) ); return (halloc_t *)(((char *)data) - align_sz(sizeof( halloc_t ) ));
} }
/** /**
@ -104,7 +115,7 @@ static void late_free( void *data)
statistics, like number of allocations and number of internal calls statistics, like number of allocations and number of internal calls
to malloc. to malloc.
*/ */
static void woot() static void halloc_report()
{ {
if( getpid() == pid ) if( getpid() == pid )
{ {
@ -115,25 +126,40 @@ static void woot()
} }
#endif #endif
void *halloc( void *context, size_t size ) void *halloc( void *context, size_t size )
{ {
halloc_t *me, *parent; halloc_t *me, *parent;
if( context ) if( context )
{ {
void *res; void *res;
void *aligned;
#ifdef HALLOC_DEBUG #ifdef HALLOC_DEBUG
if( !child_count ) if( !child_count )
{ {
pid = getpid(); pid = getpid();
atexit( woot ); atexit( &halloc_report );
} }
child_count++; child_count++;
child_size += size; child_size += size;
#endif #endif
parent = halloc_from_data( context ); parent = halloc_from_data( context );
/*
Align memory address
*/
aligned = align_ptr( parent->scratch );
parent->scratch_free -= (aligned-parent->scratch);
if( parent->scratch_free < 0 )
parent->scratch_free=0;
parent->scratch = aligned;
if( size <= parent->scratch_free ) if( size <= parent->scratch_free )
{ {
res = parent->scratch; res = parent->scratch;
@ -169,18 +195,18 @@ void *halloc( void *context, size_t size )
} }
else else
{ {
me = (halloc_t *)calloc( 1, sizeof(halloc_t) + size + HALLOC_BLOCK_SIZE ); me = (halloc_t *)calloc( 1, align_sz(sizeof(halloc_t)) + align_sz(size) + HALLOC_BLOCK_SIZE );
if( !me ) if( !me )
return 0; return 0;
#ifdef HALLOC_DEBUG #ifdef HALLOC_DEBUG
parent_count++; parent_count++;
#endif #endif
me->scratch = ((char *)me) + sizeof(halloc_t) + size; me->scratch = ((char *)me) + align_sz(sizeof(halloc_t)) + align_sz(size);
me->scratch_free = HALLOC_BLOCK_SIZE; me->scratch_free = HALLOC_BLOCK_SIZE;
al_init( &me->children ); al_init( &me->children );
return &me->data; return ((char *)me) + align_sz(sizeof(halloc_t));
} }
} }