00001 
00021 #include <stdio.h>
00022 #include <stdlib.h>
00023 #include <string.h>
00024 #include <assert.h>
00025 #include "mem.h"
00026 
00030 
00031 struct Mem_Fixed_t_
00032 {
00033     
00034     int           nEntrySize;    
00035     int           nEntriesAlloc; 
00036     int           nEntriesUsed;  
00037     int           nEntriesMax;   
00038     char *        pEntriesFree;  
00039 
00040     
00041     int           nChunkSize;    
00042     int           nChunksAlloc;  
00043     int           nChunks;       
00044     char **       pChunks;       
00045 
00046     
00047     int           nMemoryUsed;   
00048     int           nMemoryAlloc;  
00049 };
00050 
00051 struct Mem_Flex_t_
00052 {
00053     
00054     int           nEntriesUsed;  
00055     char *        pCurrent;      
00056     char *        pEnd;          
00057 
00058     
00059     int           nChunkSize;    
00060     int           nChunksAlloc;  
00061     int           nChunks;       
00062     char **       pChunks;       
00063 
00064     
00065     int           nMemoryUsed;   
00066     int           nMemoryAlloc;  
00067 };
00068 
00069 struct Mem_Step_t_
00070 {
00071     int             nMems;    
00072     Mem_Fixed_t **  pMems;    
00073     int             nMapSize; 
00074     Mem_Fixed_t **  pMap;     
00075 };
00076 
00077 #define ALLOC(type, num)         ((type *) malloc(sizeof(type) * (num)))
00078 #define FREE(obj)                    ((obj) ? (free((char *) (obj)), (obj) = 0) : 0)
00079 #define REALLOC(type, obj, num) \
00080         ((obj) ? ((type *) realloc((char *)(obj), sizeof(type) * (num))) : \
00081              ((type *) malloc(sizeof(type) * (num))))
00082 
00086 
00099 Mem_Fixed_t * Mem_FixedStart( int nEntrySize )
00100 {
00101     Mem_Fixed_t * p;
00102 
00103     p = ALLOC( Mem_Fixed_t, 1 );
00104     memset( p, 0, sizeof(Mem_Fixed_t) );
00105 
00106     p->nEntrySize    = nEntrySize;
00107     p->nEntriesAlloc = 0;
00108     p->nEntriesUsed  = 0;
00109     p->pEntriesFree  = NULL;
00110 
00111     if ( nEntrySize * (1 << 10) < (1<<16) )
00112         p->nChunkSize = (1 << 10);
00113     else
00114         p->nChunkSize = (1<<16) / nEntrySize;
00115     if ( p->nChunkSize < 8 )
00116         p->nChunkSize = 8;
00117 
00118     p->nChunksAlloc  = 64;
00119     p->nChunks       = 0;
00120     p->pChunks       = ALLOC( char *, p->nChunksAlloc );
00121 
00122     p->nMemoryUsed   = 0;
00123     p->nMemoryAlloc  = 0;
00124     return p;
00125 }
00126 
00138 void Mem_FixedStop( Mem_Fixed_t * p, int fVerbose )
00139 {
00140     int i;
00141     if ( p == NULL )
00142         return;
00143     if ( fVerbose )
00144     {
00145         printf( "Fixed memory manager: Entry = %5d. Chunk = %5d. Chunks used = %5d.\n",
00146             p->nEntrySize, p->nChunkSize, p->nChunks );
00147         printf( "   Entries used = %8d. Entries peak = %8d. Memory used = %8d. Memory alloc = %8d.\n",
00148             p->nEntriesUsed, p->nEntriesMax, p->nEntrySize * p->nEntriesUsed, p->nMemoryAlloc );
00149     }
00150     for ( i = 0; i < p->nChunks; i++ )
00151         free( p->pChunks[i] );
00152     free( p->pChunks );
00153     free( p );
00154 }
00155 
00167 char * Mem_FixedEntryFetch( Mem_Fixed_t * p )
00168 {
00169     char * pTemp;
00170     int i;
00171 
00172     
00173     if ( p->nEntriesUsed == p->nEntriesAlloc )
00174     { 
00175         assert( p->pEntriesFree == NULL );
00176         if ( p->nChunks == p->nChunksAlloc )
00177         {
00178             p->nChunksAlloc *= 2;
00179             p->pChunks = REALLOC( char *, p->pChunks, p->nChunksAlloc ); 
00180         }
00181         p->pEntriesFree = ALLOC( char, p->nEntrySize * p->nChunkSize );
00182         p->nMemoryAlloc += p->nEntrySize * p->nChunkSize;
00183         
00184         pTemp = p->pEntriesFree;
00185         for ( i = 1; i < p->nChunkSize; i++ )
00186         {
00187             *((char **)pTemp) = pTemp + p->nEntrySize;
00188             pTemp += p->nEntrySize;
00189         }
00190         
00191         *((char **)pTemp) = NULL;
00192         
00193         p->pChunks[ p->nChunks++ ] = p->pEntriesFree;
00194         
00195         p->nEntriesAlloc += p->nChunkSize;
00196     }
00197     
00198     p->nEntriesUsed++;
00199     if ( p->nEntriesMax < p->nEntriesUsed )
00200         p->nEntriesMax = p->nEntriesUsed;
00201     
00202     pTemp = p->pEntriesFree;
00203     p->pEntriesFree = *((char **)pTemp);
00204     return pTemp;
00205 }
00206 
00218 void Mem_FixedEntryRecycle( Mem_Fixed_t * p, char * pEntry )
00219 {
00220     
00221     p->nEntriesUsed--;
00222     
00223     *((char **)pEntry) = p->pEntriesFree;
00224     p->pEntriesFree = pEntry;
00225 }
00226 
00238 void Mem_FixedRestart( Mem_Fixed_t * p )
00239 {
00240     int i;
00241     char * pTemp;
00242 
00243     
00244     for ( i = 1; i < p->nChunks; i++ )
00245         free( p->pChunks[i] );
00246     p->nChunks = 1;
00247     
00248     pTemp = p->pChunks[0];
00249     for ( i = 1; i < p->nChunkSize; i++ )
00250     {
00251         *((char **)pTemp) = pTemp + p->nEntrySize;
00252         pTemp += p->nEntrySize;
00253     }
00254     
00255     *((char **)pTemp) = NULL;
00256     
00257     p->pEntriesFree  = p->pChunks[0];
00258     
00259     p->nMemoryAlloc  = p->nEntrySize * p->nChunkSize;
00260     p->nMemoryUsed   = 0;
00261     p->nEntriesAlloc = p->nChunkSize;
00262     p->nEntriesUsed  = 0;
00263 }
00264 
00276 int Mem_FixedReadMemUsage( Mem_Fixed_t * p )
00277 {
00278     return p->nMemoryAlloc;
00279 }
00280 
00292 int Mem_FixedReadMaxEntriesUsed( Mem_Fixed_t * p )
00293 {
00294     return p->nEntriesMax;
00295 }
00296 
00297 
00298 
00310 Mem_Flex_t * Mem_FlexStart()
00311 {
00312     Mem_Flex_t * p;
00313 
00314     p = ALLOC( Mem_Flex_t, 1 );
00315     memset( p, 0, sizeof(Mem_Flex_t) );
00316 
00317     p->nEntriesUsed  = 0;
00318     p->pCurrent      = NULL;
00319     p->pEnd          = NULL;
00320 
00321     p->nChunkSize    = (1 << 14);
00322     p->nChunksAlloc  = 64;
00323     p->nChunks       = 0;
00324     p->pChunks       = ALLOC( char *, p->nChunksAlloc );
00325 
00326     p->nMemoryUsed   = 0;
00327     p->nMemoryAlloc  = 0;
00328     return p;
00329 }
00330 
00342 void Mem_FlexStop( Mem_Flex_t * p, int fVerbose )
00343 {
00344     int i;
00345     if ( p == NULL )
00346         return;
00347     if ( fVerbose )
00348     {
00349         printf( "Flexible memory manager: Chunk size = %d. Chunks used = %d.\n",
00350             p->nChunkSize, p->nChunks );
00351         printf( "   Entries used = %d. Memory used = %d. Memory alloc = %d.\n",
00352             p->nEntriesUsed, p->nMemoryUsed, p->nMemoryAlloc );
00353     }
00354     for ( i = 0; i < p->nChunks; i++ )
00355         free( p->pChunks[i] );
00356     free( p->pChunks );
00357     free( p );
00358 }
00359 
00371 char * Mem_FlexEntryFetch( Mem_Flex_t * p, int nBytes )
00372 {
00373     char * pTemp;
00374     
00375     if ( p->pCurrent == NULL || p->pCurrent + nBytes > p->pEnd )
00376     { 
00377         if ( p->nChunks == p->nChunksAlloc )
00378         {
00379             p->nChunksAlloc *= 2;
00380             p->pChunks = REALLOC( char *, p->pChunks, p->nChunksAlloc ); 
00381         }
00382         if ( nBytes > p->nChunkSize )
00383         {
00384             
00385             
00386             p->nChunkSize = 2 * nBytes;
00387         }
00388         p->pCurrent = ALLOC( char, p->nChunkSize );
00389         p->pEnd     = p->pCurrent + p->nChunkSize;
00390         p->nMemoryAlloc += p->nChunkSize;
00391         
00392         p->pChunks[ p->nChunks++ ] = p->pCurrent;
00393     }
00394     assert( p->pCurrent + nBytes <= p->pEnd );
00395     
00396     p->nEntriesUsed++;
00397     
00398     p->nMemoryUsed += nBytes;
00399     
00400     pTemp = p->pCurrent;
00401     p->pCurrent += nBytes;
00402     return pTemp;
00403 }
00404 
00416 void Mem_FlexRestart( Mem_Flex_t * p )
00417 {
00418     int i;
00419     if ( p->nChunks == 0 )
00420         return;
00421     
00422     for ( i = 1; i < p->nChunks; i++ )
00423         free( p->pChunks[i] );
00424     p->nChunks  = 1;
00425     p->nMemoryAlloc = p->nChunkSize;
00426     
00427     p->pCurrent = p->pChunks[0];
00428     p->pEnd     = p->pCurrent + p->nChunkSize;
00429     p->nEntriesUsed = 0;
00430     p->nMemoryUsed = 0;
00431 }
00432 
00444 int Mem_FlexReadMemUsage( Mem_Flex_t * p )
00445 {
00446     return p->nMemoryUsed;
00447 }
00448 
00449 
00450 
00451 
00452 
00473 Mem_Step_t * Mem_StepStart( int nSteps )
00474 {
00475     Mem_Step_t * p;
00476     int i, k;
00477     p = ALLOC( Mem_Step_t, 1 );
00478     memset( p, 0, sizeof(Mem_Step_t) );
00479     p->nMems = nSteps;
00480     
00481     p->pMems = ALLOC( Mem_Fixed_t *, p->nMems );
00482     for ( i = 0; i < p->nMems; i++ )
00483         p->pMems[i] = Mem_FixedStart( (8<<i) );
00484     
00485     p->nMapSize = (4<<p->nMems);
00486     p->pMap = ALLOC( Mem_Fixed_t *, p->nMapSize+1 );
00487     p->pMap[0] = NULL;
00488     for ( k = 1; k <= 4; k++ )
00489         p->pMap[k] = p->pMems[0];
00490     for ( i = 0; i < p->nMems; i++ )
00491         for ( k = (4<<i)+1; k <= (8<<i); k++ )
00492             p->pMap[k] = p->pMems[i];
00493 
00494 
00495     return p;
00496 }
00497 
00509 void Mem_StepStop( Mem_Step_t * p, int fVerbose )
00510 {
00511     int i;
00512     for ( i = 0; i < p->nMems; i++ )
00513         Mem_FixedStop( p->pMems[i], fVerbose );
00514 
00515 
00516 
00517 
00518 
00519 
00520     free( p->pMems );
00521     free( p->pMap );
00522     free( p );
00523 }
00524 
00536 char * Mem_StepEntryFetch( Mem_Step_t * p, int nBytes )
00537 {
00538     if ( nBytes == 0 )
00539         return NULL;
00540     if ( nBytes > p->nMapSize )
00541     {
00542 
00543 
00544 
00545 
00546 
00547 
00548 
00549 
00550 
00551 
00552 
00553 
00554         return ALLOC( char, nBytes );
00555     }
00556     return Mem_FixedEntryFetch( p->pMap[nBytes] );
00557 }
00558 
00559 
00571 void Mem_StepEntryRecycle( Mem_Step_t * p, char * pEntry, int nBytes )
00572 {
00573     if ( nBytes == 0 )
00574         return;
00575     if ( nBytes > p->nMapSize )
00576     {
00577         free( pEntry );
00578         return;
00579     }
00580     Mem_FixedEntryRecycle( p->pMap[nBytes], pEntry );
00581 }
00582 
00594 int Mem_StepReadMemUsage( Mem_Step_t * p )
00595 {
00596     int i, nMemTotal = 0;
00597     for ( i = 0; i < p->nMems; i++ )
00598         nMemTotal += p->pMems[i]->nMemoryAlloc;
00599     return nMemTotal;
00600 }
00601