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