00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034 #include <stdlib.h>
00035
00036 #include "TROOT.h"
00037 #include "TObjectTable.h"
00038 #include "TError.h"
00039 #include "TString.h"
00040 #include "TVirtualMutex.h"
00041 #include "TInterpreter.h"
00042
00043 #if !defined(R__NOSTATS)
00044 # define MEM_DEBUG
00045 # define MEM_STAT
00046 # define MEM_CHECKOBJECTPOINTERS
00047 #endif
00048
00049 #if defined(MEM_STAT) && !defined(MEM_DEBUG)
00050 # define MEM_DEBUG
00051 #endif
00052
00053 #ifdef MEM_DEBUG
00054 # ifdef R__B64
00055 # define storage_size(p) ((size_t)(((size_t*)p)[-1]))
00056 # else
00057 # define storage_size(p) ((size_t)(((int*)p)[-2]))
00058 # endif
00059 #else
00060 # define storage_size(p) ((size_t)0)
00061 #endif
00062
00063 #define PVOID (-1)
00064
00065 ULong_t TStorage::fgHeapBegin = (ULong_t)-1L;
00066 ULong_t TStorage::fgHeapEnd;
00067 size_t TStorage::fgMaxBlockSize;
00068 FreeHookFun_t TStorage::fgFreeHook;
00069 void *TStorage::fgFreeHookData;
00070 ReAllocFun_t TStorage::fgReAllocHook;
00071 ReAllocCFun_t TStorage::fgReAllocCHook;
00072 Bool_t TStorage::fgHasCustomNewDelete;
00073
00074
00075 ClassImp(TStorage)
00076
00077
00078
00079 static const char *gSpaceErr = "storage exhausted";
00080
00081 const size_t kObjMaxSize = 10024;
00082
00083 static Bool_t gMemStatistics;
00084 static Int_t gAllocated[kObjMaxSize], gFreed[kObjMaxSize];
00085 static Int_t gAllocatedTotal, gFreedTotal;
00086 static void **gTraceArray = 0;
00087 static Int_t gTraceCapacity = 10, gTraceIndex = 0,
00088 gMemSize = -1, gMemIndex = -1;
00089
00090
00091
00092 void TStorage::EnterStat(size_t size, void *p)
00093 {
00094
00095
00096
00097
00098
00099 TStorage::SetMaxBlockSize(TMath::Max(TStorage::GetMaxBlockSize(), size));
00100
00101 if (!gMemStatistics) return;
00102
00103 if ((Int_t)size == gMemSize) {
00104 if (gTraceIndex == gMemIndex)
00105 Fatal("EnterStat", "trapped allocation %d", gMemIndex);
00106
00107 if (!gTraceArray)
00108 gTraceArray = (void**) malloc(sizeof(void*)*gTraceCapacity);
00109
00110 if (gTraceIndex >= gTraceCapacity) {
00111 gTraceCapacity = gTraceCapacity*2;
00112 gTraceArray = (void**) realloc(gTraceArray, sizeof(void*)*gTraceCapacity);
00113 }
00114 gTraceArray[gTraceIndex++] = p;
00115 }
00116 if (size >= kObjMaxSize)
00117 gAllocated[kObjMaxSize-1]++;
00118 else
00119 gAllocated[size]++;
00120 gAllocatedTotal += size;
00121 }
00122
00123
00124 void TStorage::RemoveStat(void *vp)
00125 {
00126
00127
00128
00129 if (!gMemStatistics) return;
00130
00131 size_t size = storage_size(vp);
00132 if ((Int_t)size == gMemSize) {
00133 for (int i = 0; i < gTraceIndex; i++)
00134 if (gTraceArray[i] == vp) {
00135 gTraceArray[i] = 0;
00136 break;
00137 }
00138 }
00139 if (size >= kObjMaxSize)
00140 gFreed[kObjMaxSize-1]++;
00141 else
00142 gFreed[size]++;
00143 gFreedTotal += size;
00144 }
00145
00146
00147 void *TStorage::Alloc(size_t size)
00148 {
00149
00150
00151
00152 static const char *where = "TStorage::Alloc";
00153
00154 #ifndef WIN32
00155 void *vp = ::operator new[](size);
00156 #else
00157 void *vp = ::operator new(size);
00158 #endif
00159 if (vp == 0)
00160 Fatal(where, "%s", gSpaceErr);
00161
00162 return vp;
00163 }
00164
00165
00166 void TStorage::Dealloc(void *ptr)
00167 {
00168
00169
00170 #ifndef WIN32
00171 ::operator delete[](ptr);
00172 #else
00173 ::operator delete(ptr);
00174 #endif
00175 }
00176
00177
00178 void *TStorage::ReAlloc(void *ovp, size_t size)
00179 {
00180
00181
00182
00183 R__LOCKGUARD(gGlobalMutex);
00184
00185 if (fgReAllocHook && fgHasCustomNewDelete && !TROOT::MemCheck())
00186 return (*fgReAllocHook)(ovp, size);
00187
00188 static const char *where = "TStorage::ReAlloc";
00189
00190 #ifndef WIN32
00191 void *vp = ::operator new[](size);
00192 #else
00193 void *vp = ::operator new(size);
00194 #endif
00195 if (vp == 0)
00196 Fatal(where, "%s", gSpaceErr);
00197
00198 if (ovp == 0)
00199 return vp;
00200
00201 memmove(vp, ovp, size);
00202 #ifndef WIN32
00203 ::operator delete[](ovp);
00204 #else
00205 ::operator delete(ovp);
00206 #endif
00207 return vp;
00208 }
00209
00210
00211 void *TStorage::ReAlloc(void *ovp, size_t size, size_t oldsize)
00212 {
00213
00214
00215
00216
00217 R__LOCKGUARD(gGlobalMutex);
00218
00219 if (fgReAllocCHook && fgHasCustomNewDelete && !TROOT::MemCheck())
00220 return (*fgReAllocCHook)(ovp, size, oldsize);
00221
00222 static const char *where = "TStorage::ReAlloc";
00223
00224 if (oldsize == size)
00225 return ovp;
00226
00227 #ifndef WIN32
00228 void *vp = ::operator new[](size);
00229 #else
00230 void *vp = ::operator new(size);
00231 #endif
00232 if (vp == 0)
00233 Fatal(where, "%s", gSpaceErr);
00234
00235 if (ovp == 0)
00236 return vp;
00237
00238 if (size > oldsize) {
00239 memcpy(vp, ovp, oldsize);
00240 memset((char*)vp+oldsize, 0, size-oldsize);
00241 } else
00242 memcpy(vp, ovp, size);
00243 #ifndef WIN32
00244 ::operator delete[](ovp);
00245 #else
00246 ::operator delete(ovp);
00247 #endif
00248 return vp;
00249 }
00250
00251
00252 char *TStorage::ReAllocChar(char *ovp, size_t size, size_t oldsize)
00253 {
00254
00255
00256
00257
00258 R__LOCKGUARD(gGlobalMutex);
00259
00260 static const char *where = "TStorage::ReAllocChar";
00261
00262 char *vp;
00263 if (ovp == 0) {
00264 vp = new char[size];
00265 if (vp == 0)
00266 Fatal(where, "%s", gSpaceErr);
00267 return vp;
00268 }
00269 if (oldsize == size)
00270 return ovp;
00271
00272 vp = new char[size];
00273 if (vp == 0)
00274 Fatal(where, "%s", gSpaceErr);
00275 if (size > oldsize) {
00276 memcpy(vp, ovp, oldsize);
00277 memset((char*)vp+oldsize, 0, size-oldsize);
00278 } else
00279 memcpy(vp, ovp, size);
00280 delete [] ovp;
00281 return vp;
00282 }
00283
00284
00285 Int_t *TStorage::ReAllocInt(Int_t *ovp, size_t size, size_t oldsize)
00286 {
00287
00288
00289
00290
00291 R__LOCKGUARD(gGlobalMutex);
00292
00293 static const char *where = "TStorage::ReAllocInt";
00294
00295 Int_t *vp;
00296 if (ovp == 0) {
00297 vp = new Int_t[size];
00298 if (vp == 0)
00299 Fatal(where, "%s", gSpaceErr);
00300 return vp;
00301 }
00302 if (oldsize == size)
00303 return ovp;
00304
00305 vp = new Int_t[size];
00306 if (vp == 0)
00307 Fatal(where, "%s", gSpaceErr);
00308 if (size > oldsize) {
00309 memcpy(vp, ovp, oldsize*sizeof(Int_t));
00310 memset((Int_t*)vp+oldsize, 0, (size-oldsize)*sizeof(Int_t));
00311 } else
00312 memcpy(vp, ovp, size*sizeof(Int_t));
00313 delete [] ovp;
00314 return vp;
00315 }
00316
00317
00318 void *TStorage::ObjectAlloc(size_t sz)
00319 {
00320
00321
00322
00323
00324
00325
00326 R__LOCKGUARD(gGlobalMutex);
00327
00328 ULong_t space = (ULong_t) ::operator new(sz);
00329 AddToHeap(space, space+sz);
00330 return (void*) space;
00331 }
00332
00333
00334 void *TStorage::ObjectAlloc(size_t , void *vp)
00335 {
00336
00337
00338
00339
00340 return vp;
00341 }
00342
00343
00344 void TStorage::ObjectDealloc(void *vp)
00345 {
00346
00347
00348
00349 R__LOCKGUARD(gGlobalMutex);
00350
00351 #ifndef NOCINT
00352
00353 Long_t gvp = 0;
00354 if (gCint) gvp = gCint->Getgvp();
00355 if ((Long_t)vp == gvp && gvp != (Long_t)PVOID)
00356 return;
00357 #endif
00358 ::operator delete(vp);
00359 }
00360
00361
00362 void TStorage::ObjectDealloc(void *vp, void *ptr)
00363 {
00364
00365
00366 if (vp && ptr) { }
00367 }
00368
00369
00370 void TStorage::SetFreeHook(FreeHookFun_t fh, void *data)
00371 {
00372
00373
00374 fgFreeHook = fh;
00375 fgFreeHookData = data;
00376 }
00377
00378
00379 void TStorage::SetReAllocHooks(ReAllocFun_t rh1, ReAllocCFun_t rh2)
00380 {
00381
00382
00383
00384 fgReAllocHook = rh1;
00385 fgReAllocCHook = rh2;
00386 }
00387
00388
00389 void TStorage::PrintStatistics()
00390 {
00391
00392
00393
00394 R__LOCKGUARD(gGlobalMutex);
00395
00396 #if defined(MEM_DEBUG) && defined(MEM_STAT)
00397
00398 if (!gMemStatistics || !HasCustomNewDelete())
00399 return;
00400
00401
00402 Printf("Heap statistics");
00403 Printf("%12s%12s%12s%12s", "size", "alloc", "free", "diff");
00404 Printf("================================================");
00405
00406 int i;
00407 for (i = 0; i < (int)kObjMaxSize; i++)
00408 if (gAllocated[i] != gFreed[i])
00409
00410 Printf("%12d%12d%12d%12d", i, gAllocated[i], gFreed[i],
00411 gAllocated[i]-gFreed[i]);
00412
00413 if (gAllocatedTotal != gFreedTotal) {
00414 Printf("------------------------------------------------");
00415 Printf("Total: %12d%12d%12d", gAllocatedTotal, gFreedTotal,
00416 gAllocatedTotal-gFreedTotal);
00417 }
00418
00419 if (gMemSize != -1) {
00420 Printf("------------------------------------------------");
00421 for (i= 0; i < gTraceIndex; i++)
00422 if (gTraceArray[i])
00423 Printf("block %d of size %d not freed", i, gMemSize);
00424 }
00425 Printf("================================================");
00426 Printf(" ");
00427 #endif
00428 }
00429
00430
00431 void TStorage::EnableStatistics(int size, int ix)
00432 {
00433
00434
00435
00436
00437 #ifdef MEM_STAT
00438 gMemSize = size;
00439 gMemIndex = ix;
00440 gMemStatistics = kTRUE;
00441 #else
00442 int idum = size; int iidum = ix;
00443 #endif
00444 }
00445
00446
00447 ULong_t TStorage::GetHeapBegin()
00448 {
00449
00450 return fgHeapBegin;
00451 }
00452
00453
00454 ULong_t TStorage::GetHeapEnd()
00455 {
00456
00457 return fgHeapEnd;
00458 }
00459
00460
00461 void *TStorage::GetFreeHookData()
00462 {
00463
00464 return fgFreeHookData;
00465 }
00466
00467
00468 Bool_t TStorage::HasCustomNewDelete()
00469 {
00470
00471 return fgHasCustomNewDelete;
00472 }
00473
00474
00475 void TStorage::SetCustomNewDelete()
00476 {
00477
00478 fgHasCustomNewDelete = kTRUE;
00479 }
00480
00481 #ifdef WIN32
00482
00483
00484 void TStorage::AddToHeap(ULong_t begin, ULong_t end)
00485 {
00486
00487 if (begin < fgHeapBegin) fgHeapBegin = begin;
00488 if (end > fgHeapEnd) fgHeapEnd = end;
00489 }
00490
00491
00492 Bool_t TStorage::IsOnHeap(void *p)
00493 {
00494
00495 return (ULong_t)p >= fgHeapBegin && (ULong_t)p < fgHeapEnd;
00496 }
00497
00498
00499 size_t TStorage::GetMaxBlockSize()
00500 {
00501
00502 return fgMaxBlockSize;
00503 }
00504
00505
00506 void TStorage::SetMaxBlockSize(size_t size)
00507 {
00508
00509 fgMaxBlockSize = size;
00510 }
00511
00512
00513 FreeHookFun_t TStorage::GetFreeHook()
00514 {
00515
00516 return fgFreeHook;
00517 }
00518
00519 #endif