[qfusion-cvs-commits] SF.net SVN: l33t: [806] trunk/qfusion/source/qcommon
Brought to you by:
digiman
From: qfusion s. c. <l33...@li...> - 2008-02-19 18:24:51
|
Revision: 806 http://l33t.svn.sourceforge.net/l33t/?rev=806&view=rev Author: digiman Date: 2008-02-19 10:24:33 -0800 (Tue, 19 Feb 2008) Log Message: ----------- Sync to warsow tree Fix free'ing of child pools Modified Paths: -------------- trunk/qfusion/source/qcommon/mem.c trunk/qfusion/source/qcommon/qcommon.h Modified: trunk/qfusion/source/qcommon/mem.c =================================================================== --- trunk/qfusion/source/qcommon/mem.c 2008-02-17 20:30:30 UTC (rev 805) +++ trunk/qfusion/source/qcommon/mem.c 2008-02-19 18:24:33 UTC (rev 806) @@ -23,7 +23,7 @@ cvar_t *developerMemory; -mempool_t *poolChain = NULL; +static mempool_t *poolChain = NULL; // used for temporary memory allocations around the engine, not for longterm // storage, if anything in this pool stays allocated during gameplay, it is @@ -33,7 +33,10 @@ // only for zone mempool_t *zoneMemPool; -void *_Mem_AllocExt( mempool_t *pool, int size, int z, int musthave, int canthave, const char *filename, int fileline ) +static qboolean memory_initialized = qfalse; +static qboolean commands_initialized = qfalse; + +void *_Mem_AllocExt( mempool_t *pool, size_t size, int z, int musthave, int canthave, const char *filename, int fileline ) { #ifdef MEMCLUMPING int i, j, k, needed, endbit, largest; @@ -46,9 +49,9 @@ if( pool == NULL ) Sys_Error( "Mem_Alloc: pool == NULL (alloc at %s:%i)", filename, fileline ); - if( musthave && ((pool->flags & musthave) != musthave) ) + if( musthave && ( ( pool->flags & musthave ) != musthave ) ) Sys_Error( "Mem_Alloc: bad pool flags (musthave) (alloc at %s:%i)", filename, fileline ); - if( canthave && (pool->flags & canthave) ) + if( canthave && ( pool->flags & canthave ) ) Sys_Error( "Mem_Alloc: bad pool flags (canthave) (alloc at %s:%i)", filename, fileline ); if( developerMemory && developerMemory->integer ) @@ -57,12 +60,14 @@ pool->totalsize += size; #ifdef MEMCLUMPING - if( size < 4096 ) { + if( size < 4096 ) + { // clumping - needed = (sizeof( memheader_t ) + size + sizeof( int ) + (MEMUNIT - 1)) / MEMUNIT; + needed = ( sizeof( memheader_t ) + size + sizeof( int ) + ( MEMUNIT - 1 ) ) / MEMUNIT; endbit = MEMBITS - needed; - for ( clumpChainPointer = &pool->clumpchain; *clumpChainPointer; clumpChainPointer = &(*clumpChainPointer)->chain ) { + for( clumpChainPointer = &pool->clumpchain; *clumpChainPointer; clumpChainPointer = &( *clumpChainPointer )->chain ) + { clump = *clumpChainPointer; if( clump->sentinel1 != MEMCLUMP_SENTINEL ) @@ -70,16 +75,19 @@ if( clump->sentinel2 != MEMCLUMP_SENTINEL ) Sys_Error( "Mem_Alloc: trashed clump sentinel 2 (alloc at %s:%d)", filename, fileline ); - if( clump->largestavailable >= needed ) { + if( clump->largestavailable >= needed ) + { largest = 0; - for( i = 0; i < endbit; i++ ) { - if( clump->bits[i >> 5] & (1 << (i & 31)) ) + for( i = 0; i < endbit; i++ ) + { + if( clump->bits[i >> 5] & ( 1 << ( i & 31 ) ) ) continue; k = i + needed; - for( j = i; i < k; i++ ) { - if( clump->bits[i >> 5] & (1 << (i & 31)) ) + for( j = i; i < k; i++ ) + { + if( clump->bits[i >> 5] & ( 1 << ( i & 31 ) ) ) goto loopcontinue; } @@ -114,13 +122,15 @@ j = 0; choseclump: - mem = ( memheader_t * )(( qbyte * ) clump->block + j * MEMUNIT); + mem = ( memheader_t * )( ( qbyte * ) clump->block + j * MEMUNIT ); mem->clump = clump; clump->blocksinuse += needed; for( i = j + needed; j < i; j++ ) - clump->bits[j >> 5] |= (1 << (j & 31)); - } else { + clump->bits[j >> 5] |= ( 1 << ( j & 31 ) ); + } + else + { // big allocations are not clumped #endif pool->realsize += sizeof( memheader_t ) + size + sizeof( int ); @@ -141,39 +151,41 @@ 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; + *( (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 ) + if( mem->next ) mem->next->prev = mem; if( z ) - memset((void *)((qbyte *) mem + sizeof(memheader_t)), 0, mem->size); + memset( (void *)( (qbyte *) mem + sizeof( memheader_t ) ), 0, mem->size ); - return (void *)((qbyte *) mem + sizeof(memheader_t)); + return (void *)( (qbyte *) mem + sizeof( memheader_t ) ); } -void *_Mem_Alloc( mempool_t *pool, int size, int musthave, int canthave, const char *filename, int fileline ) { +void *_Mem_Alloc( mempool_t *pool, size_t size, int musthave, int canthave, const char *filename, int fileline ) +{ return _Mem_AllocExt( pool, size, 1, musthave, canthave, filename, fileline ); } // FIXME: rewrite this? -void *_Mem_Realloc( void *data, int size, const char *filename, int fileline ) +void *_Mem_Realloc( void *data, size_t size, const char *filename, int fileline ) { void *newdata; memheader_t *mem; if( data == NULL ) Sys_Error( "Mem_Realloc: data == NULL (called at %s:%i)", filename, fileline ); - if( size <= 0 ) { + if( size <= 0 ) + { Mem_Free( data ); return NULL; } - mem = ( memheader_t * )((qbyte *) data - sizeof(memheader_t)); + mem = ( memheader_t * )( (qbyte *) data - sizeof( memheader_t ) ); if( size <= mem->size ) return data; @@ -184,7 +196,7 @@ return newdata; } -void _Mem_Free( void *data, int musthave, int canthave, const char *filename, int fileline ) +void _Mem_Free( void *data, int musthave, int canthave, const char *filename, int fileline ) { #ifdef MEMCLUMPING int i, firstblock, endblock; @@ -194,27 +206,30 @@ mempool_t *pool; if( data == NULL ) -// Sys_Error( "Mem_Free: data == NULL (called at %s:%i)", filename, fileline ); + //Sys_Error( "Mem_Free: data == NULL (called at %s:%i)", filename, fileline ); return; - mem = ( memheader_t * )((qbyte *) data - sizeof(memheader_t)); + 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 ) Sys_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 ) + if( *( (qbyte *)mem + sizeof( memheader_t ) + mem->size ) != MEMHEADER_SENTINEL2 ) Sys_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) ) + if( musthave && ( ( pool->flags & musthave ) != musthave ) ) Sys_Error( "Mem_Free: bad pool flags (musthave) (alloc at %s:%i)", filename, fileline ); - if( canthave && (pool->flags & canthave) ) + if( canthave && ( pool->flags & canthave ) ) Sys_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 ); // unlink memheader from doubly linked list - if( (mem->prev ? mem->prev->next != mem : pool->chain != mem) || (mem->next && mem->next->prev != mem) ) + if( ( mem->prev ? mem->prev->next != mem : pool->chain != mem ) || ( mem->next && mem->next->prev != mem ) ) Sys_Error( "Mem_Free: not allocated or double freed (free at %s:%i)", filename, fileline ); if( mem->prev ) @@ -228,42 +243,52 @@ pool->totalsize -= mem->size; #ifdef MEMCLUMPING - if ( (clump = mem->clump) ) { + if( ( clump = mem->clump ) ) + { if( clump->sentinel1 != MEMCLUMP_SENTINEL ) Sys_Error( "Mem_Free: trashed clump sentinel 1 (free at %s:%i)", filename, fileline ); if( clump->sentinel2 != MEMCLUMP_SENTINEL ) Sys_Error( "Mem_Free: trashed clump sentinel 2 (free at %s:%i)", filename, fileline ); - firstblock = ((qbyte *) mem - (qbyte *) clump->block); - if( firstblock & (MEMUNIT - 1) ) + firstblock = ( (qbyte *) mem - (qbyte *) clump->block ); + if( firstblock & ( MEMUNIT - 1 ) ) Sys_Error( "Mem_Free: address not valid in clump (free at %s:%i)", filename, fileline ); firstblock /= MEMUNIT; - endblock = firstblock + ((sizeof(memheader_t) + mem->size + sizeof(int) + (MEMUNIT - 1)) / MEMUNIT); + endblock = firstblock + ( ( sizeof( memheader_t ) + mem->size + sizeof( int ) + ( MEMUNIT - 1 ) ) / MEMUNIT ); clump->blocksinuse -= endblock - firstblock; // could use &, but we know the bit is set - for( i = firstblock;i < endblock; i++ ) - clump->bits[i >> 5] -= (1 << (i & 31)); + for( i = firstblock; i < endblock; i++ ) + clump->bits[i >> 5] -= ( 1 << ( i & 31 ) ); - if( clump->blocksinuse <= 0 ) { // unlink from chain - for( clumpChainPointer = &pool->clumpchain; *clumpChainPointer; clumpChainPointer = &(*clumpChainPointer)->chain ) { - if( *clumpChainPointer == clump ) { + if( clump->blocksinuse <= 0 ) + { + // unlink from chain + for( clumpChainPointer = &pool->clumpchain; *clumpChainPointer; clumpChainPointer = &( *clumpChainPointer )->chain ) + { + if( *clumpChainPointer == clump ) + { *clumpChainPointer = clump->chain; break; } } - pool->realsize -= sizeof(memclump_t); + pool->realsize -= sizeof( memclump_t ); #ifdef MEMTRASH - memset( clump, 0xBF, sizeof(memclump_t) ); + memset( clump, 0xBF, sizeof( memclump_t ) ); #endif free( clump ); - } else { // clump still has some allocations + } + else + { + // clump still has some allocations // force re-check of largest available space on next alloc clump->largestavailable = MEMBITS - clump->blocksinuse; } - } else { + } + else + { #endif pool->realsize -= sizeof( memheader_t ) + mem->size + sizeof( int ); #ifdef MEMTRASH @@ -279,12 +304,12 @@ { mempool_t *pool; - if( parent && (parent->flags & MEMPOOL_TEMPORARY) ) + if( parent && ( parent->flags & MEMPOOL_TEMPORARY ) ) Sys_Error( "Mem_AllocPool: nested temporary pools are not allowed (allocpool at %s:%i)", filename, fileline ); if( flags & MEMPOOL_TEMPORARY ) Sys_Error( "Mem_AllocPool: tried to allocate temporary pool, use Mem_AllocTempPool instead (allocpool at %s:%i)", filename, fileline ); - pool = malloc( sizeof(mempool_t) ); + pool = malloc( sizeof( mempool_t ) ); if( pool == NULL ) Sys_Error( "Mem_AllocPool: out of memory (allocpool at %s:%i)", filename, fileline ); @@ -301,10 +326,13 @@ pool->realsize = sizeof( mempool_t ); Q_strncpyz( pool->name, name, sizeof( pool->name ) ); - if( parent ) { + if( parent ) + { pool->next = parent->child; parent->child = pool; - } else { + } + else + { pool->next = poolChain; poolChain = pool; } @@ -324,46 +352,66 @@ void _Mem_FreePool( mempool_t **pool, int musthave, int canthave, const char *filename, int fileline ) { - mempool_t **chainAddress, **next; + mempool_t **chainAddress; +#ifdef SHOW_NONFREED + memheader_t *mem; +#endif - if( !(*pool) ) + if( !( *pool ) ) return; - if ( musthave && (((*pool)->flags & musthave) != musthave) ) + if( musthave && ( ( ( *pool )->flags & musthave ) != musthave ) ) Sys_Error( "Mem_FreePool: bad pool flags (musthave) (alloc at %s:%i)", filename, fileline ); - if ( canthave && ((*pool)->flags & canthave) ) + if( canthave && ( ( *pool )->flags & canthave ) ) Sys_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 + // note that children will be freed no matter if their flags // do not match musthave\canthave pair - if( (*pool)->child ) { - for( chainAddress = &(*pool)->child; *chainAddress; chainAddress = next ) { - next = &((*chainAddress)->next); - _Mem_FreePool( chainAddress, 0, 0, filename, fileline ); + if( ( *pool )->child ) + { + mempool_t *tmp, *next; + for( chainAddress = &( *pool )->child; *chainAddress; chainAddress = &next ) + { + next = ( *chainAddress )->next; + tmp = *chainAddress; + _Mem_FreePool( &tmp, 0, 0, filename, fileline ); } } - - if( (*pool)->sentinel1 != MEMHEADER_SENTINEL1 ) - Sys_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 ) - Sys_Error( "Mem_FreePool: trashed pool sentinel 2 (allocpool at %s:%i, freepool at %s:%i)", (*pool)->filename, (*pool)->fileline, filename, fileline ); + assert( ( *pool )->sentinel1 == MEMHEADER_SENTINEL1 ); + assert( ( *pool )->sentinel2 == MEMHEADER_SENTINEL1 ); + + if( ( *pool )->sentinel1 != MEMHEADER_SENTINEL1 ) + Sys_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 ) + Sys_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) ); + if( ( *pool )->parent ) + for( chainAddress = &( *pool )->parent->child; *chainAddress && *chainAddress != *pool; chainAddress = &( ( *chainAddress )->next ) ) ; else - for( chainAddress = &poolChain; *chainAddress && *chainAddress != *pool; chainAddress = &((*chainAddress)->next) ); + for( chainAddress = &poolChain; *chainAddress && *chainAddress != *pool; chainAddress = &( ( *chainAddress )->next ) ) ; if( *chainAddress != *pool ) Sys_Error( "Mem_FreePool: pool already free (freepool at %s:%i)", filename, fileline ); - *chainAddress = (*pool)->next; - while( (*pool)->chain ) // free memory owned by the pool - Mem_Free( (void *)((qbyte *)(*pool)->chain + sizeof(memheader_t)) ); + 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) ); + memset( *pool, 0xBF, sizeof( mempool_t ) ); #endif free( *pool ); *pool = NULL; @@ -372,29 +420,45 @@ 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 ) Sys_Error( "Mem_EmptyPool: pool == NULL (emptypool at %s:%i)", filename, fileline ); - if( musthave && ((pool->flags & musthave) != musthave) ) + if( musthave && ( ( pool->flags & musthave ) != musthave ) ) Sys_Error( "Mem_EmptyPool: bad pool flags (musthave) (alloc at %s:%i)", filename, fileline ); - if( canthave && (pool->flags & canthave) ) + if( canthave && ( pool->flags & canthave ) ) Sys_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 ) { + 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 ) Sys_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 ) Sys_Error( "Mem_EmptyPool: trashed pool sentinel 2 (allocpool at %s:%i, emptypool at %s:%i)", pool->filename, pool->fileline, filename, fileline ); - while( pool->chain ) // free memory owned by the pool - Mem_Free( (void *)((qbyte *) pool->chain + sizeof(memheader_t)) ); +#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 ) ) ); } void _Mem_CheckSentinels( void *data, const char *filename, int fileline ) @@ -404,16 +468,23 @@ if( data == NULL ) Sys_Error( "Mem_CheckSentinels: data == NULL (sentinel check at %s:%i)", filename, fileline ); - mem = (memheader_t *)((qbyte *) data - sizeof(memheader_t)); + 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 ) Sys_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 ) + if( *( (qbyte *) mem + sizeof( memheader_t ) + mem->size ) != MEMHEADER_SENTINEL2 ) Sys_Error( "Mem_CheckSentinels: trashed header sentinel 2 (block allocated at %s:%i, sentinel check at %s:%i)", mem->filename, mem->fileline, filename, fileline ); } #ifdef MEMCLUMPING static void _Mem_CheckClumpSentinels( memclump_t *clump, const char *filename, int fileline ) { + assert( clump->sentinel1 == MEMCLUMP_SENTINEL ); + assert( clump->sentinel2 == MEMCLUMP_SENTINEL ); + // this isn't really very useful if( clump->sentinel1 != MEMCLUMP_SENTINEL ) Sys_Error( "Mem_CheckClumpSentinels: trashed sentinel 1 (sentinel check at %s:%i)", filename, fileline ); @@ -422,7 +493,7 @@ } #endif -void _Mem_CheckSentinelsPool( mempool_t *pool, const char *filename, int fileline ) +static void _Mem_CheckSentinelsPool( mempool_t *pool, const char *filename, int fileline ) { memheader_t *mem; #ifdef MEMCLUMPING @@ -431,18 +502,22 @@ mempool_t *child; // recurse into children - if ( pool->child ) { + 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 ) Sys_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 ) Sys_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); + _Mem_CheckSentinels( (void *)( (qbyte *) mem + sizeof( memheader_t ) ), filename, fileline ); #ifdef MEMCLUMPING for( clump = pool->clumpchain; clump; clump = clump->chain ) @@ -458,34 +533,36 @@ _Mem_CheckSentinelsPool( pool, filename, fileline ); } -void Mem_CountPoolStats( mempool_t *pool, int *count, int *size, int *realsize ) +static void Mem_CountPoolStats( mempool_t *pool, int *count, int *size, int *realsize ) { mempool_t *child; // recurse into children - if( pool->child ) { + if( pool->child ) + { for( child = pool->child; child; child = child->next ) Mem_CountPoolStats( child, count, size, realsize ); } if( count ) - (*count)++; + ( *count )++; if( size ) - (*size) += pool->totalsize; + ( *size ) += pool->totalsize; if( realsize ) - (*realsize) += pool->realsize; + ( *realsize ) += pool->realsize; } -void Mem_PrintStats (void) +static void Mem_PrintStats( void ) { int count, size, real; int total, totalsize, realsize; mempool_t *pool; memheader_t *mem; - Mem_CheckSentinelsGlobal (); + Mem_CheckSentinelsGlobal(); - for( total = 0, totalsize = 0, realsize = 0, pool = poolChain; pool; pool = pool->next ) { + for( total = 0, totalsize = 0, realsize = 0, pool = poolChain; pool; pool = pool->next ) + { count = 0; size = 0; real = 0; Mem_CountPoolStats( pool, &count, &size, &real ); total += count; totalsize += size; realsize += real; @@ -495,58 +572,66 @@ realsize, realsize / 1048576.0 ); // temporary pools are not nested - for ( pool = poolChain; pool; pool = pool->next ) { - if ( (pool->flags & MEMPOOL_TEMPORARY) && pool->chain ) { + for( pool = poolChain; pool; pool = pool->next ) + { + if( ( pool->flags & MEMPOOL_TEMPORARY ) && pool->chain ) + { Com_Printf( "%i bytes (%.3fMB) (%i bytes (%.3fMB actual)) of temporary memory still allocated (Leak!)\n", pool->totalsize, pool->totalsize / 1048576.0, pool->realsize, pool->realsize / 1048576.0 ); Com_Printf( "listing temporary memory allocations for %s:\n", pool->name ); - for( mem = tempMemPool->chain; mem; mem = mem->next) + for( mem = tempMemPool->chain; mem; mem = mem->next ) Com_Printf( "%10i bytes allocated at %s:%i\n", mem->size, mem->filename, mem->fileline ); } } } -void Mem_PrintPoolStats( mempool_t *pool, int listchildren, int listallocations ) +static void Mem_PrintPoolStats( mempool_t *pool, int listchildren, int listallocations ) { mempool_t *child; memheader_t *mem; int totalsize = 0, realsize = 0; - Mem_CountPoolStats ( pool, NULL, &totalsize, &realsize ); + Mem_CountPoolStats( pool, NULL, &totalsize, &realsize ); - if ( pool->parent ) { + if( pool->parent ) + { if( pool->lastchecksize != 0 && totalsize != pool->lastchecksize ) - Com_Printf( "%6ik (%6ik actual) %s:%s (%i byte change)\n", (totalsize + 1023) / 1024, (realsize + 1023) / 1024, pool->parent->name, pool->name, totalsize - pool->lastchecksize ); + Com_Printf( "%6ik (%6ik actual) %s:%s (%i byte change)\n", ( totalsize + 1023 ) / 1024, ( realsize + 1023 ) / 1024, pool->parent->name, pool->name, totalsize - pool->lastchecksize ); else - Com_Printf( "%6ik (%6ik actual) %s:%s\n", (totalsize + 1023) / 1024, (realsize + 1023) / 1024, pool->parent->name, pool->name ); - } else { + Com_Printf( "%6ik (%6ik actual) %s:%s\n", ( totalsize + 1023 ) / 1024, ( realsize + 1023 ) / 1024, pool->parent->name, pool->name ); + } + else + { if( pool->lastchecksize != 0 && totalsize != pool->lastchecksize ) - Com_Printf( "%6ik (%6ik actual) %s (%i byte change)\n", (totalsize + 1023) / 1024, (realsize + 1023) / 1024, pool->name, totalsize - pool->lastchecksize ); + Com_Printf( "%6ik (%6ik actual) %s (%i byte change)\n", ( totalsize + 1023 ) / 1024, ( realsize + 1023 ) / 1024, pool->name, totalsize - pool->lastchecksize ); else - Com_Printf( "%6ik (%6ik actual) %s\n", (totalsize + 1023) / 1024, (realsize + 1023) / 1024, pool->name ); + Com_Printf( "%6ik (%6ik actual) %s\n", ( totalsize + 1023 ) / 1024, ( realsize + 1023 ) / 1024, pool->name ); } pool->lastchecksize = totalsize; - if( listallocations ) { + if( listallocations ) + { for( mem = pool->chain; mem; mem = mem->next ) - Com_Printf ("%10i bytes allocated at %s:%i\n", mem->size, mem->filename, mem->fileline); + Com_Printf( "%10i bytes allocated at %s:%i\n", mem->size, mem->filename, mem->fileline ); } - if( listchildren ) { - if( pool->child ) { + if( listchildren ) + { + if( pool->child ) + { for( child = pool->child; child; child = child->next ) - Mem_PrintPoolStats ( child, listchildren, listallocations ); + Mem_PrintPoolStats( child, listchildren, listallocations ); } } } -void Mem_PrintList( int listchildren, int listallocations ) +static void Mem_PrintList( int listchildren, int listallocations ) { mempool_t *pool; - Mem_CheckSentinelsGlobal (); + Mem_CheckSentinelsGlobal(); Com_Printf( "memory pool list:\n" "size name\n" ); @@ -554,31 +639,49 @@ Mem_PrintPoolStats( pool, listchildren, listallocations ); } -void MemList_f( void ) +static void MemList_f( void ) { - switch ( Cmd_Argc () ) { + mempool_t *pool; + + switch( Cmd_Argc() ) + { case 1: Mem_PrintList( qtrue, qfalse ); - Mem_PrintStats (); + Mem_PrintStats(); break; case 2: - if( !Q_stricmp( Cmd_Argv( 1 ), "all" ) ) { + if( !Q_stricmp( Cmd_Argv( 1 ), "all" ) ) + { Mem_PrintList( qtrue, qtrue ); - Mem_PrintStats (); + Mem_PrintStats(); break; } - // drop through + + for( pool = poolChain; pool; pool = pool->next ) + { + if( !Q_stricmp( pool->name, Cmd_Args() ) ) + { + Com_Printf( "memory pool list:\n" "size name\n" ); + Mem_PrintPoolStats( pool, qtrue, qtrue ); + break; + } + } + + if( pool ) + break; + + // fall through default: - Com_Printf( "MemList_f: unrecognized options\nusage: memlist [all]\n" ); + Com_Printf( "MemList_f: unrecognized options\nusage: memlist [all|pool]\n" ); break; } } -void MemStats_f( void ) +static void MemStats_f( void ) { - Mem_CheckSentinelsGlobal (); - Mem_PrintStats (); + Mem_CheckSentinelsGlobal(); + Mem_PrintStats(); } @@ -589,8 +692,12 @@ */ void Memory_Init( void ) { + assert( !memory_initialized ); + zoneMemPool = Mem_AllocPool( NULL, "Zone" ); tempMemPool = Mem_AllocTempPool( "Temporary Memory" ); + + memory_initialized = qtrue; } /* @@ -600,10 +707,14 @@ */ void Memory_InitCommands( void ) { + assert( !commands_initialized ); + developerMemory = Cvar_Get( "developerMemory", "0", 0 ); Cmd_AddCommand( "memlist", MemList_f ); Cmd_AddCommand( "memstats", MemStats_f ); + + commands_initialized = qtrue; } /* @@ -615,26 +726,43 @@ */ void Memory_Shutdown( void ) { - static qboolean isdown = qfalse; mempool_t *pool, *next; - if( isdown ) + if( !memory_initialized ) return; // set the cvar to NULL so nothing is printed to non-existing console developerMemory = NULL; - Cmd_RemoveCommand( "memlist" ); - Cmd_RemoveCommand( "memstats" ); + Mem_CheckSentinelsGlobal(); - isdown = qtrue; + Mem_FreePool( &zoneMemPool ); + Mem_FreePool( &tempMemPool ); - Mem_CheckSentinelsGlobal (); - - for( pool = poolChain; pool; pool = next ){ + for( pool = poolChain; pool; pool = next ) + { // do it here, because pool is to be freed // and the chain will be broken next = pool->next; +#ifdef SHOW_NONFREED + Com_Printf( "Warning: Memory pool %s was never freed\n", pool->name ); +#endif Mem_FreePool( &pool ); } + + memory_initialized = qfalse; } + +/* +======================== +Memory_ShutdownCommands +======================== +*/ +void Memory_ShutdownCommands( void ) +{ + if( !commands_initialized ) + return; + + Cmd_RemoveCommand( "memlist" ); + Cmd_RemoveCommand( "memstats" ); +} Modified: trunk/qfusion/source/qcommon/qcommon.h =================================================================== --- trunk/qfusion/source/qcommon/qcommon.h 2008-02-17 20:30:30 UTC (rev 805) +++ trunk/qfusion/source/qcommon/qcommon.h 2008-02-19 18:24:33 UTC (rev 806) @@ -837,9 +837,9 @@ void Memory_InitCommands (void); void Memory_Shutdown (void); -void *_Mem_AllocExt ( mempool_t *pool, int size, int z, int musthave, int canthave, const char *filename, int fileline ); -void *_Mem_Alloc ( mempool_t *pool, int size, int musthave, int canthave, const char *filename, int fileline ); -void *_Mem_Realloc ( void *data, int size, const char *filename, int fileline ); +void *_Mem_AllocExt ( mempool_t *pool, size_t size, int z, int musthave, int canthave, const char *filename, int fileline ); +void *_Mem_Alloc ( mempool_t *pool, size_t size, int musthave, int canthave, const char *filename, int fileline ); +void *_Mem_Realloc ( void *data, size_t size, const char *filename, int fileline ); void _Mem_Free ( void *data, int musthave, int canthave, const char *filename, int fileline ); mempool_t *_Mem_AllocPool ( mempool_t *parent, const char *name, int flags, const char *filename, int fileline ); mempool_t *_Mem_AllocTempPool ( const char *name, const char *filename, int fileline ); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |