Beispiel #1
0
void _Mem_FreePool( mempool_t **pool, int musthave, int canthave, const char *filename, int fileline )
{
	mempool_t **chainAddress;
#ifdef SHOW_NONFREED
	memheader_t *mem;
#endif

	if( !( *pool ) )
		return;
	if( musthave && ( ( ( *pool )->flags & musthave ) != musthave ) )
		_Mem_Error( "Mem_FreePool: bad pool flags (musthave) (alloc at %s:%i)", filename, fileline );
	if( canthave && ( ( *pool )->flags & canthave ) )
		_Mem_Error( "Mem_FreePool: bad pool flags (canthave) (alloc at %s:%i)", filename, fileline );

	// recurse into children
	// note that children will be freed no matter if their flags
	// do not match musthave\canthave pair
	while( ( *pool )->child ) {
		mempool_t *tmp = ( *pool )->child;
		_Mem_FreePool( &tmp, 0, 0, filename, fileline );
	}

	assert( ( *pool )->sentinel1 == MEMHEADER_SENTINEL1 );
	assert( ( *pool )->sentinel2 == MEMHEADER_SENTINEL1 );

	if( ( *pool )->sentinel1 != MEMHEADER_SENTINEL1 )
		_Mem_Error( "Mem_FreePool: trashed pool sentinel 1 (allocpool at %s:%i, freepool at %s:%i)", ( *pool )->filename, ( *pool )->fileline, filename, fileline );
	if( ( *pool )->sentinel2 != MEMHEADER_SENTINEL1 )
		_Mem_Error( "Mem_FreePool: trashed pool sentinel 2 (allocpool at %s:%i, freepool at %s:%i)", ( *pool )->filename, ( *pool )->fileline, filename, fileline );

#ifdef SHOW_NONFREED
	if( ( *pool )->chain )
		Com_Printf( "Warning: Memory pool %s has resources that weren't freed:\n", ( *pool )->name );
	for( mem = ( *pool )->chain; mem; mem = mem->next )
	{
		Com_Printf( "%10i bytes allocated at %s:%i\n", mem->size, mem->filename, mem->fileline );
	}
#endif

	// unlink pool from chain
	if( ( *pool )->parent )
		for( chainAddress = &( *pool )->parent->child; *chainAddress && *chainAddress != *pool; chainAddress = &( ( *chainAddress )->next ) ) ;
	else
		for( chainAddress = &poolChain; *chainAddress && *chainAddress != *pool; chainAddress = &( ( *chainAddress )->next ) ) ;

	if( *chainAddress != *pool )
		_Mem_Error( "Mem_FreePool: pool already free (freepool at %s:%i)", filename, fileline );

	while( ( *pool )->chain )  // free memory owned by the pool
		Mem_Free( (void *)( (qbyte *)( *pool )->chain + sizeof( memheader_t ) ) );

	*chainAddress = ( *pool )->next;

	// free the pool itself
#ifdef MEMTRASH
	memset( *pool, 0xBF, sizeof( mempool_t ) );
#endif
	free( *pool );
	*pool = NULL;
}
Beispiel #2
0
void *_Mem_AllocExt( mempool_t *pool, size_t size, size_t alignment, int z, int musthave, int canthave, const char *filename, int fileline )
{
	void *base;
	size_t realsize;
	memheader_t *mem;

	if( size <= 0 )
		return NULL;

	// default to 16-bytes alignment
	if( !alignment )
		alignment = MEMALIGNMENT_DEFAULT;

	if( pool == NULL )
		_Mem_Error( "Mem_Alloc: pool == NULL (alloc at %s:%i)", filename, fileline );
	if( musthave && ( ( pool->flags & musthave ) != musthave ) )
		_Mem_Error( "Mem_Alloc: bad pool flags (musthave) (alloc at %s:%i)", filename, fileline );
	if( canthave && ( pool->flags & canthave ) )
		_Mem_Error( "Mem_Alloc: bad pool flags (canthave) (alloc at %s:%i)", filename, fileline );

	if( developerMemory && developerMemory->integer )
		Com_DPrintf( "Mem_Alloc: pool %s, file %s:%i, size %i bytes\n", pool->name, filename, fileline, size );

	pool->totalsize += size;
	realsize = sizeof( memheader_t ) + size + alignment + sizeof( int );

	pool->realsize += realsize;

	base = malloc( realsize );
	if( base == NULL )
		_Mem_Error( "Mem_Alloc: out of memory (alloc at %s:%i)", filename, fileline );

	// calculate address that aligns the end of the memheader_t to the specified alignment
	mem = ( memheader_t * )((((size_t)base + sizeof( memheader_t ) + (alignment-1)) & ~(alignment-1)) - sizeof( memheader_t ));
	mem->baseaddress = base;
	mem->filename = filename;
	mem->fileline = fileline;
	mem->size = size;
	mem->realsize = realsize;
	mem->pool = pool;
	mem->sentinel1 = MEMHEADER_SENTINEL1;

	// we have to use only a single byte for this sentinel, because it may not be aligned, and some platforms can't use unaligned accesses
	*( (qbyte *) mem + sizeof( memheader_t ) + mem->size ) = MEMHEADER_SENTINEL2;

	// append to head of list
	mem->next = pool->chain;
	mem->prev = NULL;
	pool->chain = mem;
	if( mem->next )
		mem->next->prev = mem;

	if( z )
		memset( (void *)( (qbyte *) mem + sizeof( memheader_t ) ), 0, mem->size );

	return (void *)( (qbyte *) mem + sizeof( memheader_t ) );
}
Beispiel #3
0
void _Mem_Free( void *data, int musthave, int canthave, const char *filename, int fileline )
{
	void *base;
	memheader_t *mem;
	mempool_t *pool;

	if( data == NULL )
		//_Mem_Error( "Mem_Free: data == NULL (called at %s:%i)", filename, fileline );
		return;

	mem = ( memheader_t * )( (qbyte *) data - sizeof( memheader_t ) );

	assert( mem->sentinel1 == MEMHEADER_SENTINEL1 );
	assert( *( (qbyte *) mem + sizeof( memheader_t ) + mem->size ) == MEMHEADER_SENTINEL2 );

	if( mem->sentinel1 != MEMHEADER_SENTINEL1 )
		_Mem_Error( "Mem_Free: trashed header sentinel 1 (alloc at %s:%i, free at %s:%i)", mem->filename, mem->fileline, filename, fileline );
	if( *( (qbyte *)mem + sizeof( memheader_t ) + mem->size ) != MEMHEADER_SENTINEL2 )
		_Mem_Error( "Mem_Free: trashed header sentinel 2 (alloc at %s:%i, free at %s:%i)", mem->filename, mem->fileline, filename, fileline );

	pool = mem->pool;
	if( musthave && ( ( pool->flags & musthave ) != musthave ) )
		_Mem_Error( "Mem_Free: bad pool flags (musthave) (alloc at %s:%i)", filename, fileline );
	if( canthave && ( pool->flags & canthave ) )
		_Mem_Error( "Mem_Free: bad pool flags (canthave) (alloc at %s:%i)", filename, fileline );

	if( developerMemory && developerMemory->integer )
		Com_DPrintf( "Mem_Free: pool %s, alloc %s:%i, free %s:%i, size %i bytes\n", pool->name, mem->filename, mem->fileline, filename, fileline, mem->size );

	QMutex_Lock( memMutex );

	// unlink memheader from doubly linked list
	if( ( mem->prev ? mem->prev->next != mem : pool->chain != mem ) || ( mem->next && mem->next->prev != mem ) )
		_Mem_Error( "Mem_Free: not allocated or double freed (free at %s:%i)", filename, fileline );

	if( mem->prev )
		mem->prev->next = mem->next;
	else
		pool->chain = mem->next;
	if( mem->next )
		mem->next->prev = mem->prev;

	// memheader has been unlinked, do the actual free now
	pool->totalsize -= mem->size;

	base = mem->baseaddress;
	pool->realsize -= mem->realsize;

	QMutex_Unlock( memMutex );

#ifdef MEMTRASH
	memset( mem, 0xBF, sizeof( memheader_t ) + mem->size + sizeof( int ) );
#endif

	free( base );
}
Beispiel #4
0
void _Mem_CheckSentinels( void *data, const char *filename, int fileline )
{
	memheader_t *mem;

	if( data == NULL )
		_Mem_Error( "Mem_CheckSentinels: data == NULL (sentinel check at %s:%i)", filename, fileline );

	mem = (memheader_t *)( (qbyte *) data - sizeof( memheader_t ) );

	assert( mem->sentinel1 == MEMHEADER_SENTINEL1 );
	assert( *( (qbyte *) mem + sizeof( memheader_t ) + mem->size ) == MEMHEADER_SENTINEL2 );

	if( mem->sentinel1 != MEMHEADER_SENTINEL1 )
		_Mem_Error( "Mem_CheckSentinels: trashed header sentinel 1 (block allocated at %s:%i, sentinel check at %s:%i)", mem->filename, mem->fileline, filename, fileline );
	if( *( (qbyte *) mem + sizeof( memheader_t ) + mem->size ) != MEMHEADER_SENTINEL2 )
		_Mem_Error( "Mem_CheckSentinels: trashed header sentinel 2 (block allocated at %s:%i, sentinel check at %s:%i)", mem->filename, mem->fileline, filename, fileline );
}
Beispiel #5
0
void _Mem_EmptyPool( mempool_t *pool, int musthave, int canthave, const char *filename, int fileline )
{
	mempool_t *child, *next;
#ifdef SHOW_NONFREED
	memheader_t *mem;
#endif

	if( pool == NULL )
		_Mem_Error( "Mem_EmptyPool: pool == NULL (emptypool at %s:%i)", filename, fileline );
	if( musthave && ( ( pool->flags & musthave ) != musthave ) )
		_Mem_Error( "Mem_EmptyPool: bad pool flags (musthave) (alloc at %s:%i)", filename, fileline );
	if( canthave && ( pool->flags & canthave ) )
		_Mem_Error( "Mem_EmptyPool: bad pool flags (canthave) (alloc at %s:%i)", filename, fileline );

	// recurse into children
	if( pool->child )
	{
		for( child = pool->child; child; child = next )
		{
			next = child->next;
			_Mem_EmptyPool( child, 0, 0, filename, fileline );
		}
	}

	assert( pool->sentinel1 == MEMHEADER_SENTINEL1 );
	assert( pool->sentinel2 == MEMHEADER_SENTINEL1 );

	if( pool->sentinel1 != MEMHEADER_SENTINEL1 )
		_Mem_Error( "Mem_EmptyPool: trashed pool sentinel 1 (allocpool at %s:%i, emptypool at %s:%i)", pool->filename, pool->fileline, filename, fileline );
	if( pool->sentinel2 != MEMHEADER_SENTINEL1 )
		_Mem_Error( "Mem_EmptyPool: trashed pool sentinel 2 (allocpool at %s:%i, emptypool at %s:%i)", pool->filename, pool->fileline, filename, fileline );

#ifdef SHOW_NONFREED
	if( pool->chain )
		Com_Printf( "Warning: Memory pool %s has resources that weren't freed:\n", pool->name );
	for( mem = pool->chain; mem; mem = mem->next )
	{
		Com_Printf( "%10i bytes allocated at %s:%i\n", mem->size, mem->filename, mem->fileline );
	}
#endif
	while( pool->chain )        // free memory owned by the pool
		Mem_Free( (void *)( (qbyte *) pool->chain + sizeof( memheader_t ) ) );
}
Beispiel #6
0
mempool_t *_Mem_AllocPool( mempool_t *parent, const char *name, int flags, const char *filename, int fileline )
{
	mempool_t *pool;

	if( parent && ( parent->flags & MEMPOOL_TEMPORARY ) )
		_Mem_Error( "Mem_AllocPool: nested temporary pools are not allowed (allocpool at %s:%i)", filename, fileline );
	if( flags & MEMPOOL_TEMPORARY )
		_Mem_Error( "Mem_AllocPool: tried to allocate temporary pool, use Mem_AllocTempPool instead (allocpool at %s:%i)", filename, fileline );

	pool = ( mempool_t* )malloc( sizeof( mempool_t ) );
	if( pool == NULL )
		_Mem_Error( "Mem_AllocPool: out of memory (allocpool at %s:%i)", filename, fileline );

	memset( pool, 0, sizeof( mempool_t ) );
	pool->sentinel1 = MEMHEADER_SENTINEL1;
	pool->sentinel2 = MEMHEADER_SENTINEL1;
	pool->filename = filename;
	pool->fileline = fileline;
	pool->flags = flags;
	pool->chain = NULL;
	pool->parent = parent;
	pool->child = NULL;
	pool->totalsize = 0;
	pool->realsize = sizeof( mempool_t );
	Q_strncpyz( pool->name, name, sizeof( pool->name ) );

	if( parent )
	{
		pool->next = parent->child;
		parent->child = pool;
	}
	else
	{
		pool->next = poolChain;
		poolChain = pool;
	}

	return pool;
}
Beispiel #7
0
static void _Mem_CheckSentinelsPool( mempool_t *pool, const char *filename, int fileline )
{
	memheader_t *mem;
	mempool_t *child;

	// recurse into children
	if( pool->child )
	{
		for( child = pool->child; child; child = child->next )
			_Mem_CheckSentinelsPool( child, filename, fileline );
	}

	assert( pool->sentinel1 == MEMHEADER_SENTINEL1 );
	assert( pool->sentinel2 == MEMHEADER_SENTINEL1 );

	if( pool->sentinel1 != MEMHEADER_SENTINEL1 )
		_Mem_Error( "_Mem_CheckSentinelsPool: trashed pool sentinel 1 (allocpool at %s:%i, sentinel check at %s:%i)", pool->filename, pool->fileline, filename, fileline );
	if( pool->sentinel2 != MEMHEADER_SENTINEL1 )
		_Mem_Error( "_Mem_CheckSentinelsPool: trashed pool sentinel 2 (allocpool at %s:%i, sentinel check at %s:%i)", pool->filename, pool->fileline, filename, fileline );

	for( mem = pool->chain; mem; mem = mem->next )
		_Mem_CheckSentinels( (void *)( (qbyte *) mem + sizeof( memheader_t ) ), filename, fileline );
}
Beispiel #8
0
// FIXME: rewrite this?
void *_Mem_Realloc( void *data, size_t size, const char *filename, int fileline )
{
	void *newdata;
	memheader_t *mem;

	if( data == NULL )
		_Mem_Error( "Mem_Realloc: data == NULL (called at %s:%i)", filename, fileline );
	if( size <= 0 )
	{
		Mem_Free( data );
		return NULL;
	}

	mem = ( memheader_t * )( (qbyte *) data - sizeof( memheader_t ) );
	if( size <= mem->size )
		return data;

	newdata = Mem_AllocExt( mem->pool, size, 0 );
	memcpy( newdata, data, mem->size );
	Mem_Free( data );

	return newdata;
}