00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include <memory.h>
00023 #include <malloc.h>
00024 #include <assert.h>
00025
00026 #ifndef NDEBUG
00027 #define _CRTDBG_MAP_ALLOC
00028 #include <crtdbg.h>
00029 #endif
00030
00031 #include "ram.h"
00032
00033
00034
00035
00036
00037 #ifdef NDEBUG
00038
00039 #ifndef MINIMAL_CONFIG
00040 #define MINIMAL_CONFIG
00041 #endif
00042 #else
00043
00044 #ifdef MINIMAL_CONFIG
00045 #undef MINIMAL_CONFIG
00046 #endif
00047 #endif
00048
00049
00050 #ifndef GENESISDLLVERSION
00051 void *StupidUnusedPointer;
00052 #endif
00053
00054
00055 static int geRam_CriticalAllocationCount = 0;
00056
00057 static geRam_CriticalCallbackFunction geRam_CriticalCallback = NULL;
00058
00059
00060
00061
00062
00063
00064 GENESISAPI int geRam_EnableCriticalCallback(int add)
00065 {
00066 geRam_CriticalAllocationCount += add;
00067 return geRam_CriticalAllocationCount;
00068 }
00069
00070
00071
00072
00073
00074
00075 GENESISAPI geRam_CriticalCallbackFunction geRam_SetCriticalCallback
00076 (
00077 geRam_CriticalCallbackFunction critical_callback
00078 )
00079 {
00080 geRam_CriticalCallbackFunction OldCallback;
00081
00082 OldCallback = geRam_CriticalCallback;
00083 geRam_CriticalCallback = critical_callback;
00084 return OldCallback;
00085 }
00086
00087
00088
00089
00090
00091 static int geRam_DoCriticalCallback
00092 (
00093 void
00094 )
00095 {
00096 if ((geRam_CriticalAllocationCount != 0) && (geRam_CriticalCallback != NULL))
00097 {
00098 return geRam_CriticalCallback ();
00099 }
00100 else
00101 {
00102 return 0;
00103 }
00104 }
00105
00106
00107 GENESISAPI void * geRam_AllocateClear(uint32 size)
00108 {
00109 void * mem;
00110 size = (size + 3)&(~(uint32)3);
00111 mem = geRam_Allocate(size);
00112 if ( mem )
00113 {
00114 memset(mem,0,size);
00115 }
00116 return mem;
00117 }
00118
00119 #ifdef MINIMAL_CONFIG
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131 void *geRam_Allocate
00132 (
00133 uint32 size
00134 )
00135 {
00136 void *p;
00137
00138 do
00139 {
00140 p = malloc(size);
00141 } while ((p == NULL) && (geRam_DoCriticalCallback ()));
00142
00143 return p;
00144 }
00145
00146
00147 void geRam_Free_
00148 (
00149 void *ptr
00150 )
00151 {
00152 free (ptr);
00153 }
00154
00155
00156
00157 GENESISAPI void *geRam_Realloc
00158 (
00159 void *ptr,
00160 uint32 newsize
00161 )
00162 {
00163 char *p;
00164 char * NewPtr;
00165
00166 if (ptr == NULL)
00167 {
00168 return geRam_Allocate (newsize);
00169 }
00170
00171
00172 if (newsize == 0)
00173 {
00174 geRam_Free (ptr);
00175 return NULL;
00176 }
00177
00178 p = ptr;
00179 do
00180 {
00181 NewPtr = (char *)realloc (p, newsize);
00182 } while ((NewPtr == NULL) && (geRam_DoCriticalCallback ()));
00183
00184 return NewPtr;
00185 }
00186
00187 #else // MINIMAL_CONFIG
00188
00189
00190
00191
00192
00193
00194
00195 int32 geRam_CurrentlyUsed = 0;
00196 int32 geRam_MaximumUsed = 0;
00197 int32 geRam_NumberOfAllocations = 0;
00198 int32 geRam_MaximumNumberOfAllocations = 0;
00199
00200
00201 static char MemStamp[] = {"!CHECKME!"};
00202 static const int MemStampSize = sizeof (MemStamp);
00203 static const int SizeSize = sizeof (uint32);
00204
00205 #define HEADER_SIZE (((SizeSize + MemStampSize)+7)&(~(uint32)7))
00206 #define EXTRA_SIZE (((HEADER_SIZE + MemStampSize)+7)&(~(uint32)7))
00207 static const unsigned char AllocFillerByte = (unsigned char)0xA5;
00208 static const unsigned char FreeFillerByte = (unsigned char)0xB6;
00209
00210
00211
00212
00213
00214
00215
00216
00217 typedef enum
00218 {
00219 DONT_INITIALIZE = 0,
00220 INITIALIZE_MEMORY = 1
00221 } geRam_MemoryInitialization;
00222
00223 static void geRam_SetupBlock
00224 (
00225 char * p,
00226 uint32 size,
00227 geRam_MemoryInitialization InitMem
00228 )
00229 {
00230 if (InitMem == INITIALIZE_MEMORY)
00231 {
00232
00233 memset (p+HEADER_SIZE, AllocFillerByte, size);
00234 }
00235
00236
00237 *((uint32 *)p) = size;
00238
00239
00240 memcpy (p+SizeSize, MemStamp, MemStampSize);
00241
00242
00243 memcpy (p+HEADER_SIZE+size, MemStamp, MemStampSize);
00244 }
00245
00246 #ifndef NDEBUG
00247 GENESISAPI void* _geRam_DebugAllocate(uint32 size, const char* pFile, int line)
00248 {
00249 char *p;
00250
00251 do
00252 {
00253 p = (char*)_malloc_dbg (size + EXTRA_SIZE, _NORMAL_BLOCK, pFile, line);
00254 } while ((p == NULL) && geRam_DoCriticalCallback ());
00255
00256 if (p == NULL)
00257 {
00258 return NULL;
00259 }
00260
00261
00262 geRam_SetupBlock (p, size, INITIALIZE_MEMORY);
00263
00264
00265 geRam_NumberOfAllocations++;
00266 geRam_CurrentlyUsed += size;
00267
00268 if (geRam_NumberOfAllocations > geRam_MaximumNumberOfAllocations)
00269 {
00270 geRam_MaximumNumberOfAllocations = geRam_NumberOfAllocations;
00271 }
00272 if (geRam_CurrentlyUsed > geRam_MaximumUsed)
00273 {
00274 geRam_MaximumUsed = geRam_CurrentlyUsed;
00275 }
00276
00277 return p+HEADER_SIZE;
00278 }
00279
00280 #else // NDEBUG
00281
00282 GENESISAPI void * geRam_Allocate (uint32 size)
00283 {
00284 char *p;
00285
00286 do
00287 {
00288 p = (char*)malloc (size + EXTRA_SIZE);
00289 } while ((p == NULL) && geRam_DoCriticalCallback ());
00290
00291 if (p == NULL)
00292 {
00293 return NULL;
00294 }
00295
00296
00297 geRam_SetupBlock (p, size, INITIALIZE_MEMORY);
00298
00299
00300 geRam_NumberOfAllocations++;
00301 geRam_CurrentlyUsed += size;
00302
00303 if (geRam_NumberOfAllocations > geRam_MaximumNumberOfAllocations)
00304 {
00305 geRam_MaximumNumberOfAllocations = geRam_NumberOfAllocations;
00306 }
00307 if (geRam_CurrentlyUsed > geRam_MaximumUsed)
00308 {
00309 geRam_MaximumUsed = geRam_CurrentlyUsed;
00310 }
00311
00312 return p+HEADER_SIZE;
00313 }
00314 #endif // NDEBUG
00315
00316 static char * ram_verify_block
00317 (
00318 void * ptr
00319 )
00320 {
00321 char * p = ptr;
00322 uint32 size;
00323
00324 if (p == NULL)
00325 {
00326 assert (0 && "freeing NULL");
00327 return NULL;
00328 }
00329
00330
00331 p -= HEADER_SIZE;
00332
00333
00334 size = *((uint32 *)p);
00335
00336
00337 if (memcmp (p+SizeSize, MemStamp, MemStampSize) != 0)
00338 {
00339 assert (0 && "ram_verify_block: Memory block corrupted at front");
00340 return NULL;
00341 }
00342
00343
00344 if (memcmp (p+HEADER_SIZE+size, MemStamp, MemStampSize) != 0)
00345 {
00346 assert (0 && "ram_verify_block: Memory block corrupted at tail");
00347 return NULL;
00348 }
00349
00350 return p;
00351 }
00352
00353 GENESISAPI void geRam_Free_ (void *ptr)
00354 {
00355 char *p;
00356 uint32 size;
00357
00358
00359 p = ram_verify_block (ptr);
00360 if (p == NULL)
00361 {
00362 return;
00363 }
00364
00365
00366 size = *((uint32 *)p);
00367
00368
00369 memset (p, FreeFillerByte, size+EXTRA_SIZE);
00370
00371
00372 free (p);
00373
00374
00375 geRam_NumberOfAllocations--;
00376 assert ((geRam_NumberOfAllocations >= 0) && "free()d more ram than you allocated!");
00377
00378 geRam_CurrentlyUsed -= size;
00379 assert ((geRam_CurrentlyUsed >= 0) && "free()d more ram than you allocated!");
00380 }
00381
00382 #ifndef NDEBUG
00383
00384 GENESISAPI void * _geRam_DebugRealloc (void *ptr, uint32 newsize, const char* pFile, int line)
00385 {
00386 char *p;
00387 char * NewPtr;
00388 uint32 size;
00389
00390
00391 if (ptr == NULL)
00392 {
00393 return _geRam_DebugAllocate(newsize, pFile, line);
00394 }
00395
00396
00397 p = ram_verify_block (ptr);
00398 if (p == NULL)
00399 {
00400 return NULL;
00401 }
00402
00403
00404 if (newsize == 0)
00405 {
00406 geRam_Free (ptr);
00407 return NULL;
00408 }
00409
00410
00411 size = *((uint32 *)p);
00412
00413 do
00414 {
00415 NewPtr = (char *)_realloc_dbg(p, newsize+EXTRA_SIZE, _NORMAL_BLOCK, pFile, line);
00416 } while ((NewPtr == NULL) && geRam_DoCriticalCallback ());
00417
00418
00419 if (NewPtr == NULL)
00420 {
00421 return NULL;
00422 }
00423
00424 geRam_SetupBlock (NewPtr, newsize, DONT_INITIALIZE);
00425
00426 geRam_CurrentlyUsed += (newsize - size);
00427 if (geRam_CurrentlyUsed > geRam_MaximumUsed)
00428 {
00429 geRam_MaximumUsed = geRam_CurrentlyUsed;
00430 }
00431 assert ((geRam_CurrentlyUsed >= 0) && "free()d more ram than you allocated!");
00432
00433 return NewPtr + HEADER_SIZE;
00434 }
00435
00436 #else // NDEBUG
00437
00438 GENESISAPI void * geRam_Realloc (void *ptr, uint32 newsize)
00439 {
00440 char *p;
00441 char * NewPtr;
00442 uint32 size;
00443
00444
00445 if (ptr == NULL)
00446 {
00447 return geRam_Allocate (newsize);
00448 }
00449
00450
00451 p = ram_verify_block (ptr);
00452 if (p == NULL)
00453 {
00454 return NULL;
00455 }
00456
00457
00458 if (newsize == 0)
00459 {
00460 geRam_Free (ptr);
00461 return NULL;
00462 }
00463
00464
00465 size = *((uint32 *)p);
00466
00467 do
00468 {
00469 NewPtr = (char *)realloc (p, newsize+EXTRA_SIZE);
00470 } while ((NewPtr == NULL) && geRam_DoCriticalCallback ());
00471
00472
00473 if (NewPtr == NULL)
00474 {
00475 return NULL;
00476 }
00477
00478 geRam_SetupBlock (NewPtr, newsize, DONT_INITIALIZE);
00479
00480 geRam_CurrentlyUsed += (newsize - size);
00481 if (geRam_CurrentlyUsed > geRam_MaximumUsed)
00482 {
00483 geRam_MaximumUsed = geRam_CurrentlyUsed;
00484 }
00485 assert ((geRam_CurrentlyUsed >= 0) && "free()d more ram than you allocated!");
00486
00487 return NewPtr + HEADER_SIZE;
00488 }
00489
00490 #endif // NDEBUG
00491
00492 #ifndef NDEBUG
00493
00494 GENESISAPI void geRam_ReportAllocations(void)
00495 {
00496 _CrtDumpMemoryLeaks();
00497 }
00498
00499 #endif
00500
00501
00502
00503 GENESISAPI void geRam_AddAllocation (int n, uint32 size)
00504 {
00505
00506 geRam_NumberOfAllocations += n;
00507 geRam_CurrentlyUsed += size;
00508
00509 if (geRam_NumberOfAllocations > geRam_MaximumNumberOfAllocations)
00510 {
00511 geRam_MaximumNumberOfAllocations = geRam_NumberOfAllocations;
00512 }
00513 if (geRam_CurrentlyUsed > geRam_MaximumUsed)
00514 {
00515 geRam_MaximumUsed = geRam_CurrentlyUsed;
00516 }
00517 }
00518
00519 #endif // MINIMAL_CONFIG
00520
00521
00522 #ifndef NDEBUG
00523 geBoolean geRam_IsValidPtr(void *ptr)
00524 {
00525 char * p = ptr;
00526 uint32 size;
00527
00528 if (p == NULL) return GE_FALSE;
00529
00530
00531 p -= HEADER_SIZE;
00532
00533
00534 size = *((uint32 *)p);
00535
00536
00537 if (memcmp (p+SizeSize, MemStamp, MemStampSize) != 0)
00538 {
00539 return GE_FALSE;
00540 }
00541
00542
00543 if (memcmp (p+HEADER_SIZE+size, MemStamp, MemStampSize) != 0)
00544 {
00545 return GE_FALSE;
00546 }
00547
00548 return GE_TRUE;
00549 }
00550 #endif