00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include <string.h>
00023 #include <assert.h>
00024
00025 #include "mempool.h"
00026 #include "ram.h"
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041 #define RamCalloc(size) geRam_AllocateClear(size)
00042 #define RamFree(mem) geRam_Free(mem)
00043 #define RamRealloc(mem,size) geRam_Realloc(mem,size)
00044
00045 #ifndef memclear
00046 #define memclear(mem,size) memset(mem,0,size);
00047 #endif
00048
00049
00050
00051
00052 typedef struct MemBlock MemBlock;
00053 struct MemBlock
00054 {
00055 MemBlock * Next;
00056 char * MemBase;
00057 char * MemPtr;
00058 int MemLength;
00059 int MemFree;
00060 };
00061
00062
00063 struct MemPool
00064 {
00065 int HunkLength;
00066 MemBlock * CurMemBlock;
00067 MemBlock * MemList;
00068 int AutoExtendNumItems;
00069 int NumFreedHunks;
00070 int MaxNumFreedHunks;
00071 void ** FreedHunks;
00072 int NumItemsActive;
00073 };
00074
00075 int MemBlock_IsValid(MemBlock *mb)
00076 {
00077 if ( ! mb ) return 0;
00078 if ( mb->Next )
00079 {
00080 if ( ! MemBlock_IsValid(mb->Next) )
00081 return 0;
00082 }
00083
00084 assert( geRam_IsValidPtr(mb->MemBase) );
00085
00086 if ( mb->MemFree < 0 || mb->MemFree > mb->MemLength )
00087 return 0;
00088 if ( mb->MemPtr != mb->MemBase + (mb->MemLength - mb->MemFree) )
00089 return 0;
00090 return 1;
00091 }
00092
00093 int MemPool_IsValid(MemPool * Pool)
00094 {
00095 if ( ! Pool ) return 0;
00096 if ( Pool->NumFreedHunks < 0 || Pool->AutoExtendNumItems < 0
00097 || Pool->MaxNumFreedHunks < 0 || Pool->NumItemsActive || Pool->HunkLength )
00098 return 0;
00099 if ( Pool->NumFreedHunks >= Pool->MaxNumFreedHunks ) return 0;
00100
00101
00102
00103
00104 return MemBlock_IsValid(Pool->MemList);
00105 }
00106
00107 MemPool * MemPool_Create (int HunkLength,int NumHunks,int AutoExtendNumItems)
00108 {
00109 MemPool * Ret;
00110
00111 if ( (Ret = RamCalloc(sizeof(MemPool))) == NULL )
00112 return(NULL);
00113
00114 Ret->HunkLength = (HunkLength+3)&(~3);
00115 Ret->CurMemBlock = NULL;
00116 Ret->MemList = NULL;
00117 Ret->NumFreedHunks = 0;
00118 Ret->MaxNumFreedHunks = 16;
00119 Ret->AutoExtendNumItems = AutoExtendNumItems;
00120 Ret->NumItemsActive = 0;
00121
00122 if ( (Ret->FreedHunks = RamCalloc(Ret->MaxNumFreedHunks*sizeof(void *))) == NULL )
00123 {
00124 RamFree(Ret);
00125 return(NULL);
00126 }
00127
00128 if ( ! MemPool_Extend(Ret,NumHunks) )
00129 {
00130 RamFree(Ret->FreedHunks);
00131 RamFree(Ret);
00132 return(NULL);
00133 }
00134
00135 return(Ret);
00136 }
00137
00138 void MemPool_Destroy(MemPool ** pPool)
00139 {
00140 MemBlock * CurMemBlock;
00141 MemBlock * NextMemBlock;
00142 MemPool * Pool;
00143
00144 assert(pPool);
00145
00146 Pool = *pPool;
00147
00148 if ( Pool == NULL ) return;
00149
00150 CurMemBlock = Pool->MemList;
00151 while(CurMemBlock)
00152 {
00153 RamFree(CurMemBlock->MemBase);
00154 NextMemBlock = CurMemBlock->Next;
00155 RamFree(CurMemBlock);
00156 CurMemBlock = NextMemBlock;
00157 }
00158
00159 RamFree(Pool->FreedHunks);
00160 RamFree(Pool);
00161
00162 *pPool = NULL;
00163 }
00164
00165 void * MemPool_GetHunk (MemPool * Pool)
00166 {
00167 void * Ret;
00168 MemBlock * CurMemBlock;
00169
00170 if ( Pool->NumFreedHunks > 0 )
00171 {
00172 Pool->NumFreedHunks--;
00173 Ret = Pool->FreedHunks[Pool->NumFreedHunks];
00174
00175 goto GotHunk;
00176 }
00177
00178 if ( (CurMemBlock = Pool->CurMemBlock) == NULL )
00179 return(NULL);
00180
00181 if ( CurMemBlock->MemFree < Pool->HunkLength )
00182 {
00183 if ( ! MemPool_Extend(Pool,Pool->AutoExtendNumItems) )
00184 return(NULL);
00185 CurMemBlock = Pool->CurMemBlock;
00186 }
00187
00188 Ret = (void *) CurMemBlock->MemPtr;
00189
00190 CurMemBlock->MemFree -= Pool->HunkLength;
00191 CurMemBlock->MemPtr += Pool->HunkLength;
00192
00193 GotHunk:
00194
00195
00196
00197
00198 Pool->NumItemsActive++;
00199
00200 return(Ret);
00201 }
00202
00203 void MemPool_Reset(MemPool * Pool)
00204 {
00205 MemBlock * CurMemBlock;
00206
00207 Pool->NumFreedHunks = 0;
00208 Pool->NumItemsActive = 0;
00209 Pool->CurMemBlock = Pool->MemList;
00210
00211 for( CurMemBlock = Pool->MemList; CurMemBlock ; CurMemBlock = CurMemBlock->Next)
00212 {
00213 CurMemBlock->MemFree = CurMemBlock->MemLength;
00214 CurMemBlock->MemPtr = CurMemBlock->MemBase;
00215
00216 memclear(CurMemBlock->MemBase,CurMemBlock->MemLength);
00217 }
00218 }
00219
00220 int MemPool_Extend(MemPool * Pool, int NumHunks)
00221 {
00222 MemBlock * NewMemBlock;
00223
00224 NewMemBlock = Pool->MemList;
00225 while ( NewMemBlock )
00226 {
00227 if ( NewMemBlock->MemFree > Pool->HunkLength )
00228 {
00229 Pool->CurMemBlock = NewMemBlock;
00230 return(1);
00231 }
00232 NewMemBlock = NewMemBlock->Next;
00233 }
00234
00235 if ( (NewMemBlock = RamCalloc(sizeof(MemBlock))) == NULL )
00236 return(0);
00237
00238 NewMemBlock->MemLength = NumHunks * Pool->HunkLength;
00239 NewMemBlock->MemFree = NewMemBlock->MemLength;
00240
00241 if ( (NewMemBlock->MemBase = RamCalloc(NewMemBlock->MemLength)) == NULL )
00242 {
00243 RamFree(NewMemBlock);
00244 return(0);
00245 }
00246
00247 NewMemBlock->MemPtr = NewMemBlock->MemBase;
00248
00249 NewMemBlock->Next = Pool->MemList;
00250 Pool->MemList = NewMemBlock;
00251
00252 Pool->CurMemBlock = NewMemBlock;
00253
00254 return(1);
00255 }
00256
00257 int MemPool_FreeHunk(MemPool * Pool,void * Hunk)
00258 {
00259 assert( Pool );
00260
00261
00262
00263
00264
00265 if ( Pool->NumFreedHunks >= Pool->MaxNumFreedHunks )
00266 {
00267 Pool->MaxNumFreedHunks <<= 1;
00268
00269 Pool->FreedHunks = RamRealloc(Pool->FreedHunks,Pool->MaxNumFreedHunks*sizeof(void *));
00270 assert(Pool->FreedHunks);
00271 if ( ! Pool->FreedHunks )
00272 return(0);
00273 }
00274
00275 Pool->FreedHunks[Pool->NumFreedHunks] = Hunk;
00276 Pool->NumFreedHunks++;
00277
00278 Pool->NumItemsActive--;
00279
00280 memclear(Hunk,Pool->HunkLength);
00281
00282 return(1);
00283 }
00284
00285
00286 static MemBlock * WalkMemBlock;
00287 static char *WalkPtr,*WalkPtrEnd;
00288 static MemPool * LastPool;
00289
00290 void * MemPool_WalkNext(MemPool *Pool,void *Hunk)
00291 {
00292 if ( ! Pool ) return NULL;
00293 if ( ! Hunk )
00294 {
00295 LastPool = Pool;
00296 WalkMemBlock = Pool->MemList;
00297 if ( ! WalkMemBlock ) return NULL;
00298 WalkPtr = WalkMemBlock->MemBase;
00299 WalkPtrEnd = WalkPtr + (WalkMemBlock->MemLength - WalkMemBlock->MemFree);
00300 }
00301 else
00302 {
00303 assert( Pool == LastPool );
00304 assert( WalkPtr == Hunk );
00305 rewalk:
00306 WalkPtr += Pool->HunkLength;
00307 if ( WalkPtr >= WalkPtrEnd )
00308 {
00309 WalkMemBlock = WalkMemBlock->Next;
00310 if ( ! WalkMemBlock ) return NULL;
00311 WalkPtr = WalkMemBlock->MemBase;
00312 WalkPtrEnd = WalkPtr + (WalkMemBlock->MemLength - WalkMemBlock->MemFree);
00313 }
00314 }
00315
00316
00317
00318 {
00319 int i;
00320 for(i=0;i<Pool->NumFreedHunks;i++)
00321 {
00322 if ( WalkPtr == Pool->FreedHunks[i] )
00323 {
00324 Hunk = WalkPtr;
00325 goto rewalk;
00326 }
00327 }
00328 }
00329
00330 return WalkPtr;
00331 }