17d0a6c19SBarry Smith 2e5c89e4eSSatish Balay /* 3e5c89e4eSSatish Balay Interface to malloc() and free(). This code allows for 4e5c89e4eSSatish Balay logging of memory usage and some error checking 5e5c89e4eSSatish Balay */ 6c6db04a5SJed Brown #include <petscsys.h> /*I "petscsys.h" I*/ 7665c2dedSJed Brown #include <petscviewer.h> 8e5c89e4eSSatish Balay #if defined(PETSC_HAVE_MALLOC_H) 9e5c89e4eSSatish Balay #include <malloc.h> 10e5c89e4eSSatish Balay #endif 11e5c89e4eSSatish Balay 12e5c89e4eSSatish Balay 13e5c89e4eSSatish Balay /* 14e5c89e4eSSatish Balay These are defined in mal.c and ensure that malloced space is PetscScalar aligned 15e5c89e4eSSatish Balay */ 16*95c0884eSLisandro Dalcin PETSC_EXTERN PetscErrorCode PetscMallocAlign(size_t,int,const char[],const char[],void**); 17*95c0884eSLisandro Dalcin PETSC_EXTERN PetscErrorCode PetscFreeAlign(void*,int,const char[],const char[]); 18*95c0884eSLisandro Dalcin PETSC_EXTERN PetscErrorCode PetscReallocAlign(size_t,int,const char[],const char[],void**); 19*95c0884eSLisandro Dalcin PETSC_EXTERN PetscErrorCode PetscTrMallocDefault(size_t,int,const char[],const char[],void**); 20*95c0884eSLisandro Dalcin PETSC_EXTERN PetscErrorCode PetscTrFreeDefault(void*,int,const char[],const char[]); 21*95c0884eSLisandro Dalcin PETSC_EXTERN PetscErrorCode PetscTrReallocDefault(size_t,int,const char[],const char[],void**); 22e5c89e4eSSatish Balay 23e5c89e4eSSatish Balay 240700a824SBarry Smith #define CLASSID_VALUE ((PetscClassId) 0xf0e0d0c9) 250700a824SBarry Smith #define ALREADY_FREED ((PetscClassId) 0x0f0e0d9c) 26e5c89e4eSSatish Balay 27e5c89e4eSSatish Balay typedef struct _trSPACE { 28e5c89e4eSSatish Balay size_t size; 29e5c89e4eSSatish Balay int id; 30e5c89e4eSSatish Balay int lineno; 31e5c89e4eSSatish Balay const char *filename; 32e5c89e4eSSatish Balay const char *functionname; 330700a824SBarry Smith PetscClassId classid; 348bf1f09cSShri Abhyankar #if defined(PETSC_USE_DEBUG) 35e5c89e4eSSatish Balay PetscStack stack; 36e5c89e4eSSatish Balay #endif 37e5c89e4eSSatish Balay struct _trSPACE *next,*prev; 38e5c89e4eSSatish Balay } TRSPACE; 39e5c89e4eSSatish Balay 4025b53cc9SJed Brown /* HEADER_BYTES is the number of bytes in a PetscMalloc() header. 4125b53cc9SJed Brown It is sizeof(TRSPACE) padded to be a multiple of PETSC_MEMALIGN. 4225b53cc9SJed Brown */ 43e5c89e4eSSatish Balay 44a64a8e02SBarry Smith #define HEADER_BYTES ((sizeof(TRSPACE)+(PETSC_MEMALIGN-1)) & ~(PETSC_MEMALIGN-1)) 45e5c89e4eSSatish Balay 46e5c89e4eSSatish Balay 4725b53cc9SJed Brown /* This union is used to insure that the block passed to the user retains 4825b53cc9SJed Brown a minimum alignment of PETSC_MEMALIGN. 4925b53cc9SJed Brown */ 50e5c89e4eSSatish Balay typedef union { 51e5c89e4eSSatish Balay TRSPACE sp; 5225b53cc9SJed Brown char v[HEADER_BYTES]; 53e5c89e4eSSatish Balay } TrSPACE; 54e5c89e4eSSatish Balay 55b022a5c1SBarry Smith 56e5c89e4eSSatish Balay static size_t TRallocated = 0; 57e5c89e4eSSatish Balay static int TRfrags = 0; 58f0ba7cfcSLisandro Dalcin static TRSPACE *TRhead = NULL; 59e5c89e4eSSatish Balay static int TRid = 0; 60ace3abfcSBarry Smith static PetscBool TRdebugLevel = PETSC_FALSE; 61e5c89e4eSSatish Balay static size_t TRMaxMem = 0; 62e5c89e4eSSatish Balay /* 63e5c89e4eSSatish Balay Arrays to log information on all Mallocs 64e5c89e4eSSatish Balay */ 65f0ba7cfcSLisandro Dalcin static int PetscLogMallocMax = 10000; 66f0ba7cfcSLisandro Dalcin static int PetscLogMalloc = -1; 67574034a9SJed Brown static size_t PetscLogMallocThreshold = 0; 68e5c89e4eSSatish Balay static size_t *PetscLogMallocLength; 69efca3c55SSatish Balay static const char **PetscLogMallocFile,**PetscLogMallocFunction; 70e5c89e4eSSatish Balay 71*95c0884eSLisandro Dalcin PETSC_INTERN PetscErrorCode PetscSetUseTrMalloc_Private(void) 72b022a5c1SBarry Smith { 73b022a5c1SBarry Smith PetscErrorCode ierr; 74b022a5c1SBarry Smith 75b022a5c1SBarry Smith PetscFunctionBegin; 76b022a5c1SBarry Smith ierr = PetscMallocSet(PetscTrMallocDefault,PetscTrFreeDefault);CHKERRQ(ierr); 773221ece2SMatthew G. Knepley PetscTrRealloc = PetscTrReallocDefault; 78a297a907SKarl Rupp 79b022a5c1SBarry Smith TRallocated = 0; 80b022a5c1SBarry Smith TRfrags = 0; 81f0ba7cfcSLisandro Dalcin TRhead = NULL; 82b022a5c1SBarry Smith TRid = 0; 83b022a5c1SBarry Smith TRdebugLevel = PETSC_FALSE; 84b022a5c1SBarry Smith TRMaxMem = 0; 85b022a5c1SBarry Smith PetscLogMallocMax = 10000; 86b022a5c1SBarry Smith PetscLogMalloc = -1; 87b022a5c1SBarry Smith PetscFunctionReturn(0); 88b022a5c1SBarry Smith } 89b022a5c1SBarry Smith 90e5c89e4eSSatish Balay /*@C 91e5c89e4eSSatish Balay PetscMallocValidate - Test the memory for corruption. This can be used to 92e5c89e4eSSatish Balay check for memory overwrites. 93e5c89e4eSSatish Balay 94e5c89e4eSSatish Balay Input Parameter: 95e5c89e4eSSatish Balay + line - line number where call originated. 96e5c89e4eSSatish Balay . function - name of function calling 97efca3c55SSatish Balay - file - file where function is 98e5c89e4eSSatish Balay 99e5c89e4eSSatish Balay Return value: 100e5c89e4eSSatish Balay The number of errors detected. 101e5c89e4eSSatish Balay 102e5c89e4eSSatish Balay Output Effect: 103e5c89e4eSSatish Balay Error messages are written to stdout. 104e5c89e4eSSatish Balay 105e5c89e4eSSatish Balay Level: advanced 106e5c89e4eSSatish Balay 107e5c89e4eSSatish Balay Notes: 108e5c89e4eSSatish Balay You should generally use CHKMEMQ as a short cut for calling this 109e5c89e4eSSatish Balay routine. 110e5c89e4eSSatish Balay 111efca3c55SSatish Balay The line, function, file are given by the C preprocessor as 112e5c89e4eSSatish Balay 113e5c89e4eSSatish Balay The Fortran calling sequence is simply PetscMallocValidate(ierr) 114e5c89e4eSSatish Balay 115e5c89e4eSSatish Balay No output is generated if there are no problems detected. 116e5c89e4eSSatish Balay 117e5c89e4eSSatish Balay .seealso: CHKMEMQ 118e5c89e4eSSatish Balay 119e5c89e4eSSatish Balay @*/ 120efca3c55SSatish Balay PetscErrorCode PetscMallocValidate(int line,const char function[],const char file[]) 121e5c89e4eSSatish Balay { 1226c093d5bSvictor TRSPACE *head,*lasthead; 123e5c89e4eSSatish Balay char *a; 1240700a824SBarry Smith PetscClassId *nend; 125e5c89e4eSSatish Balay 126e5c89e4eSSatish Balay PetscFunctionBegin; 1276c093d5bSvictor head = TRhead; lasthead = NULL; 128e5c89e4eSSatish Balay while (head) { 1290700a824SBarry Smith if (head->classid != CLASSID_VALUE) { 130efca3c55SSatish Balay (*PetscErrorPrintf)("PetscMallocValidate: error detected at %s() line %d in %s\n",function,line,file); 131e5c89e4eSSatish Balay (*PetscErrorPrintf)("Memory at address %p is corrupted\n",head); 132e5c89e4eSSatish Balay (*PetscErrorPrintf)("Probably write past beginning or end of array\n"); 133efca3c55SSatish Balay if (lasthead) (*PetscErrorPrintf)("Last intact block allocated in %s() line %d in %s\n",lasthead->functionname,lasthead->lineno,lasthead->filename); 134e32f2f54SBarry Smith SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEMC," "); 135e5c89e4eSSatish Balay } 136e5c89e4eSSatish Balay a = (char*)(((TrSPACE*)head) + 1); 1370700a824SBarry Smith nend = (PetscClassId*)(a + head->size); 1380700a824SBarry Smith if (*nend != CLASSID_VALUE) { 139efca3c55SSatish Balay (*PetscErrorPrintf)("PetscMallocValidate: error detected at %s() line %d in %s\n",function,line,file); 140e5c89e4eSSatish Balay if (*nend == ALREADY_FREED) { 141e5c89e4eSSatish Balay (*PetscErrorPrintf)("Memory [id=%d(%.0f)] at address %p already freed\n",head->id,(PetscLogDouble)head->size,a); 142e32f2f54SBarry Smith SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEMC," "); 143e5c89e4eSSatish Balay } else { 144e5c89e4eSSatish Balay (*PetscErrorPrintf)("Memory [id=%d(%.0f)] at address %p is corrupted (probably write past end of array)\n",head->id,(PetscLogDouble)head->size,a); 145efca3c55SSatish Balay (*PetscErrorPrintf)("Memory originally allocated in %s() line %d in %s\n",head->functionname,head->lineno,head->filename); 146e32f2f54SBarry Smith SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEMC," "); 147e5c89e4eSSatish Balay } 148e5c89e4eSSatish Balay } 1496c093d5bSvictor lasthead = head; 150e5c89e4eSSatish Balay head = head->next; 151e5c89e4eSSatish Balay } 152e5c89e4eSSatish Balay PetscFunctionReturn(0); 153e5c89e4eSSatish Balay } 154e5c89e4eSSatish Balay 155e5c89e4eSSatish Balay /* 156e5c89e4eSSatish Balay PetscTrMallocDefault - Malloc with tracing. 157e5c89e4eSSatish Balay 158e5c89e4eSSatish Balay Input Parameters: 159e5c89e4eSSatish Balay + a - number of bytes to allocate 160e5c89e4eSSatish Balay . lineno - line number where used. Use __LINE__ for this 161efca3c55SSatish Balay - filename - file name where used. Use __FILE__ for this 162e5c89e4eSSatish Balay 163e5c89e4eSSatish Balay Returns: 164e5c89e4eSSatish Balay double aligned pointer to requested storage, or null if not 165e5c89e4eSSatish Balay available. 166e5c89e4eSSatish Balay */ 167efca3c55SSatish Balay PetscErrorCode PetscTrMallocDefault(size_t a,int lineno,const char function[],const char filename[],void **result) 168e5c89e4eSSatish Balay { 169e5c89e4eSSatish Balay TRSPACE *head; 170e5c89e4eSSatish Balay char *inew; 171e5c89e4eSSatish Balay size_t nsize; 172e5c89e4eSSatish Balay PetscErrorCode ierr; 173e5c89e4eSSatish Balay 174e5c89e4eSSatish Balay PetscFunctionBegin; 175f0ba7cfcSLisandro Dalcin /* Do not try to handle empty blocks */ 176f0ba7cfcSLisandro Dalcin if (!a) { *result = NULL; PetscFunctionReturn(0); } 177f0ba7cfcSLisandro Dalcin 178e5c89e4eSSatish Balay if (TRdebugLevel) { 179efca3c55SSatish Balay ierr = PetscMallocValidate(lineno,function,filename); if (ierr) PetscFunctionReturn(ierr); 180e5c89e4eSSatish Balay } 181e5c89e4eSSatish Balay 18225b53cc9SJed Brown nsize = (a + (PETSC_MEMALIGN-1)) & ~(PETSC_MEMALIGN-1); 183efca3c55SSatish Balay ierr = PetscMallocAlign(nsize+sizeof(TrSPACE)+sizeof(PetscClassId),lineno,function,filename,(void**)&inew);CHKERRQ(ierr); 184e5c89e4eSSatish Balay 185e5c89e4eSSatish Balay head = (TRSPACE*)inew; 186e5c89e4eSSatish Balay inew += sizeof(TrSPACE); 187e5c89e4eSSatish Balay 188e5c89e4eSSatish Balay if (TRhead) TRhead->prev = head; 189e5c89e4eSSatish Balay head->next = TRhead; 190e5c89e4eSSatish Balay TRhead = head; 191f0ba7cfcSLisandro Dalcin head->prev = NULL; 192e5c89e4eSSatish Balay head->size = nsize; 193e5c89e4eSSatish Balay head->id = TRid; 194e5c89e4eSSatish Balay head->lineno = lineno; 195e5c89e4eSSatish Balay 196e5c89e4eSSatish Balay head->filename = filename; 197e5c89e4eSSatish Balay head->functionname = function; 1980700a824SBarry Smith head->classid = CLASSID_VALUE; 1990700a824SBarry Smith *(PetscClassId*)(inew + nsize) = CLASSID_VALUE; 200e5c89e4eSSatish Balay 201e5c89e4eSSatish Balay TRallocated += nsize; 202a297a907SKarl Rupp if (TRallocated > TRMaxMem) TRMaxMem = TRallocated; 203e5c89e4eSSatish Balay TRfrags++; 204e5c89e4eSSatish Balay 2058bf1f09cSShri Abhyankar #if defined(PETSC_USE_DEBUG) 20676386721SLisandro Dalcin if (PetscStackActive()) { 2075c25fcd7SBarry Smith ierr = PetscStackCopy(petscstack,&head->stack);CHKERRQ(ierr); 2082c9581d2SBarry Smith /* fix the line number to where the malloc() was called, not the PetscFunctionBegin; */ 2092c9581d2SBarry Smith head->stack.line[head->stack.currentsize-2] = lineno; 2109de0f6ecSBarry Smith } else { 2119de0f6ecSBarry Smith head->stack.currentsize = 0; 21276386721SLisandro Dalcin } 213e5c89e4eSSatish Balay #endif 214e5c89e4eSSatish Balay 215e5c89e4eSSatish Balay /* 216e5c89e4eSSatish Balay Allow logging of all mallocs made 217e5c89e4eSSatish Balay */ 218574034a9SJed Brown if (PetscLogMalloc > -1 && PetscLogMalloc < PetscLogMallocMax && a >= PetscLogMallocThreshold) { 219e5c89e4eSSatish Balay if (!PetscLogMalloc) { 220e5c89e4eSSatish Balay PetscLogMallocLength = (size_t*)malloc(PetscLogMallocMax*sizeof(size_t)); 221e32f2f54SBarry Smith if (!PetscLogMallocLength) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM," "); 222a297a907SKarl Rupp 223a2ea699eSBarry Smith PetscLogMallocFile = (const char**)malloc(PetscLogMallocMax*sizeof(char*)); 224e32f2f54SBarry Smith if (!PetscLogMallocFile) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM," "); 225a297a907SKarl Rupp 226a2ea699eSBarry Smith PetscLogMallocFunction = (const char**)malloc(PetscLogMallocMax*sizeof(char*)); 227e32f2f54SBarry Smith if (!PetscLogMallocFunction) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM," "); 228e5c89e4eSSatish Balay } 229e5c89e4eSSatish Balay PetscLogMallocLength[PetscLogMalloc] = nsize; 230e5c89e4eSSatish Balay PetscLogMallocFile[PetscLogMalloc] = filename; 231e5c89e4eSSatish Balay PetscLogMallocFunction[PetscLogMalloc++] = function; 232e5c89e4eSSatish Balay } 233e5c89e4eSSatish Balay *result = (void*)inew; 234e5c89e4eSSatish Balay PetscFunctionReturn(0); 235e5c89e4eSSatish Balay } 236e5c89e4eSSatish Balay 237e5c89e4eSSatish Balay 238e5c89e4eSSatish Balay /* 239e5c89e4eSSatish Balay PetscTrFreeDefault - Free with tracing. 240e5c89e4eSSatish Balay 241e5c89e4eSSatish Balay Input Parameters: 242e5c89e4eSSatish Balay . a - pointer to a block allocated with PetscTrMalloc 243e5c89e4eSSatish Balay . lineno - line number where used. Use __LINE__ for this 244e5c89e4eSSatish Balay . file - file name where used. Use __FILE__ for this 245e5c89e4eSSatish Balay */ 246efca3c55SSatish Balay PetscErrorCode PetscTrFreeDefault(void *aa,int line,const char function[],const char file[]) 247e5c89e4eSSatish Balay { 248e5c89e4eSSatish Balay char *a = (char*)aa; 249e5c89e4eSSatish Balay TRSPACE *head; 250e5c89e4eSSatish Balay char *ahead; 251e5c89e4eSSatish Balay PetscErrorCode ierr; 2520700a824SBarry Smith PetscClassId *nend; 253e5c89e4eSSatish Balay 254e5c89e4eSSatish Balay PetscFunctionBegin; 255e5c89e4eSSatish Balay /* Do not try to handle empty blocks */ 25649d7da52SJed Brown if (!a) PetscFunctionReturn(0); 257e5c89e4eSSatish Balay 258e5c89e4eSSatish Balay if (TRdebugLevel) { 259efca3c55SSatish Balay ierr = PetscMallocValidate(line,function,file);CHKERRQ(ierr); 260e5c89e4eSSatish Balay } 261e5c89e4eSSatish Balay 262e5c89e4eSSatish Balay ahead = a; 263e5c89e4eSSatish Balay a = a - sizeof(TrSPACE); 264e5c89e4eSSatish Balay head = (TRSPACE*)a; 265e5c89e4eSSatish Balay 2660700a824SBarry Smith if (head->classid != CLASSID_VALUE) { 267efca3c55SSatish Balay (*PetscErrorPrintf)("PetscTrFreeDefault() called from %s() line %d in %s\n",function,line,file); 268e5c89e4eSSatish Balay (*PetscErrorPrintf)("Block at address %p is corrupted; cannot free;\nmay be block not allocated with PetscMalloc()\n",a); 269e32f2f54SBarry Smith SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEMC,"Bad location or corrupted memory"); 270e5c89e4eSSatish Balay } 2710700a824SBarry Smith nend = (PetscClassId*)(ahead + head->size); 2720700a824SBarry Smith if (*nend != CLASSID_VALUE) { 273e5c89e4eSSatish Balay if (*nend == ALREADY_FREED) { 274efca3c55SSatish Balay (*PetscErrorPrintf)("PetscTrFreeDefault() called from %s() line %d in %s\n",function,line,file); 275e5c89e4eSSatish Balay (*PetscErrorPrintf)("Block [id=%d(%.0f)] at address %p was already freed\n",head->id,(PetscLogDouble)head->size,a + sizeof(TrSPACE)); 276e5c89e4eSSatish Balay if (head->lineno > 0 && head->lineno < 50000 /* sanity check */) { 277efca3c55SSatish Balay (*PetscErrorPrintf)("Block freed in %s() line %d in %s\n",head->functionname,head->lineno,head->filename); 278e5c89e4eSSatish Balay } else { 279efca3c55SSatish Balay (*PetscErrorPrintf)("Block allocated in %s() line %d in %s\n",head->functionname,-head->lineno,head->filename); 280e5c89e4eSSatish Balay } 281e32f2f54SBarry Smith SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Memory already freed"); 282e5c89e4eSSatish Balay } else { 283e5c89e4eSSatish Balay /* Damaged tail */ 284efca3c55SSatish Balay (*PetscErrorPrintf)("PetscTrFreeDefault() called from %s() line %d in %s\n",function,line,file); 285e5c89e4eSSatish Balay (*PetscErrorPrintf)("Block [id=%d(%.0f)] at address %p is corrupted (probably write past end of array)\n",head->id,(PetscLogDouble)head->size,a); 286efca3c55SSatish Balay (*PetscErrorPrintf)("Block allocated in %s() line %d in %s\n",head->functionname,head->lineno,head->filename); 287e32f2f54SBarry Smith SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEMC,"Corrupted memory"); 288e5c89e4eSSatish Balay } 289e5c89e4eSSatish Balay } 290e5c89e4eSSatish Balay /* Mark the location freed */ 291e5c89e4eSSatish Balay *nend = ALREADY_FREED; 292e5c89e4eSSatish Balay /* Save location where freed. If we suspect the line number, mark as allocated location */ 293e5c89e4eSSatish Balay if (line > 0 && line < 50000) { 294e5c89e4eSSatish Balay head->lineno = line; 295e5c89e4eSSatish Balay head->filename = file; 296e5c89e4eSSatish Balay head->functionname = function; 297e5c89e4eSSatish Balay } else { 298e5c89e4eSSatish Balay head->lineno = -head->lineno; 299e5c89e4eSSatish Balay } 300e5c89e4eSSatish Balay /* zero out memory - helps to find some reuse of already freed memory */ 301e5c89e4eSSatish Balay ierr = PetscMemzero(aa,head->size);CHKERRQ(ierr); 302e5c89e4eSSatish Balay 303e5c89e4eSSatish Balay TRallocated -= head->size; 304e5c89e4eSSatish Balay TRfrags--; 305e5c89e4eSSatish Balay if (head->prev) head->prev->next = head->next; 306e5c89e4eSSatish Balay else TRhead = head->next; 307e5c89e4eSSatish Balay 308e5c89e4eSSatish Balay if (head->next) head->next->prev = head->prev; 309efca3c55SSatish Balay ierr = PetscFreeAlign(a,line,function,file);CHKERRQ(ierr); 310e5c89e4eSSatish Balay PetscFunctionReturn(0); 311e5c89e4eSSatish Balay } 312e5c89e4eSSatish Balay 313e5c89e4eSSatish Balay 3143221ece2SMatthew G. Knepley 3153221ece2SMatthew G. Knepley /* 3163221ece2SMatthew G. Knepley PetscTrReallocDefault - Realloc with tracing. 3173221ece2SMatthew G. Knepley 3183221ece2SMatthew G. Knepley Input Parameters: 3193221ece2SMatthew G. Knepley + len - number of bytes to allocate 3203221ece2SMatthew G. Knepley . lineno - line number where used. Use __LINE__ for this 3213221ece2SMatthew G. Knepley . filename - file name where used. Use __FILE__ for this 3223221ece2SMatthew G. Knepley - result - double aligned pointer to initial storage. 3233221ece2SMatthew G. Knepley 3243221ece2SMatthew G. Knepley Output Parameter: 3253221ece2SMatthew G. Knepley . result - double aligned pointer to requested storage, or null if not available. 3263221ece2SMatthew G. Knepley 3273221ece2SMatthew G. Knepley Level: developer 3283221ece2SMatthew G. Knepley 3293221ece2SMatthew G. Knepley .seealso: PetscTrMallocDefault(), PetscTrFreeDefault() 3303221ece2SMatthew G. Knepley */ 3313221ece2SMatthew G. Knepley PetscErrorCode PetscTrReallocDefault(size_t len, int lineno, const char function[], const char filename[], void **result) 3323221ece2SMatthew G. Knepley { 3333221ece2SMatthew G. Knepley char *a = (char *) *result; 3343221ece2SMatthew G. Knepley TRSPACE *head; 3353221ece2SMatthew G. Knepley char *ahead, *inew; 3363221ece2SMatthew G. Knepley PetscClassId *nend; 3373221ece2SMatthew G. Knepley size_t nsize; 3383221ece2SMatthew G. Knepley PetscErrorCode ierr; 3393221ece2SMatthew G. Knepley 3403221ece2SMatthew G. Knepley PetscFunctionBegin; 341c22f1541SToby Isaac /* Realloc to zero = free */ 342c22f1541SToby Isaac if (!len) { 343c22f1541SToby Isaac ierr = PetscTrFreeDefault(*result,lineno,function,filename);CHKERRQ(ierr); 344c22f1541SToby Isaac *result = NULL; 345c22f1541SToby Isaac PetscFunctionReturn(0); 346c22f1541SToby Isaac } 3473221ece2SMatthew G. Knepley 3483221ece2SMatthew G. Knepley if (TRdebugLevel) {ierr = PetscMallocValidate(lineno,function,filename); if (ierr) PetscFunctionReturn(ierr);} 3493221ece2SMatthew G. Knepley 3503221ece2SMatthew G. Knepley ahead = a; 3513221ece2SMatthew G. Knepley a = a - sizeof(TrSPACE); 3523221ece2SMatthew G. Knepley head = (TRSPACE *) a; 3533221ece2SMatthew G. Knepley inew = a; 3543221ece2SMatthew G. Knepley 3553221ece2SMatthew G. Knepley if (head->classid != CLASSID_VALUE) { 3563221ece2SMatthew G. Knepley (*PetscErrorPrintf)("PetscTrReallocDefault() called from %s() line %d in %s\n",function,lineno,filename); 3573221ece2SMatthew G. Knepley (*PetscErrorPrintf)("Block at address %p is corrupted; cannot free;\nmay be block not allocated with PetscMalloc()\n",a); 3583221ece2SMatthew G. Knepley SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEMC,"Bad location or corrupted memory"); 3593221ece2SMatthew G. Knepley } 3603221ece2SMatthew G. Knepley nend = (PetscClassId *)(ahead + head->size); 3613221ece2SMatthew G. Knepley if (*nend != CLASSID_VALUE) { 3623221ece2SMatthew G. Knepley if (*nend == ALREADY_FREED) { 3633221ece2SMatthew G. Knepley (*PetscErrorPrintf)("PetscTrReallocDefault() called from %s() line %d in %s\n",function,lineno,filename); 3643221ece2SMatthew G. Knepley (*PetscErrorPrintf)("Block [id=%d(%.0f)] at address %p was already freed\n",head->id,(PetscLogDouble)head->size,a + sizeof(TrSPACE)); 3653221ece2SMatthew G. Knepley if (head->lineno > 0 && head->lineno < 50000 /* sanity check */) { 3663221ece2SMatthew G. Knepley (*PetscErrorPrintf)("Block freed in %s() line %d in %s\n",head->functionname,head->lineno,head->filename); 3673221ece2SMatthew G. Knepley } else { 3683221ece2SMatthew G. Knepley (*PetscErrorPrintf)("Block allocated in %s() line %d in %s\n",head->functionname,-head->lineno,head->filename); 3693221ece2SMatthew G. Knepley } 3703221ece2SMatthew G. Knepley SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Memory already freed"); 3713221ece2SMatthew G. Knepley } else { 3723221ece2SMatthew G. Knepley /* Damaged tail */ 3733221ece2SMatthew G. Knepley (*PetscErrorPrintf)("PetscTrReallocDefault() called from %s() line %d in %s\n",function,lineno,filename); 3743221ece2SMatthew G. Knepley (*PetscErrorPrintf)("Block [id=%d(%.0f)] at address %p is corrupted (probably write past end of array)\n",head->id,(PetscLogDouble)head->size,a); 3753221ece2SMatthew G. Knepley (*PetscErrorPrintf)("Block allocated in %s() line %d in %s\n",head->functionname,head->lineno,head->filename); 3763221ece2SMatthew G. Knepley SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEMC,"Corrupted memory"); 3773221ece2SMatthew G. Knepley } 3783221ece2SMatthew G. Knepley } 3793221ece2SMatthew G. Knepley 3803221ece2SMatthew G. Knepley TRallocated -= head->size; 3813221ece2SMatthew G. Knepley TRfrags--; 3823221ece2SMatthew G. Knepley if (head->prev) head->prev->next = head->next; 3833221ece2SMatthew G. Knepley else TRhead = head->next; 3843221ece2SMatthew G. Knepley if (head->next) head->next->prev = head->prev; 3853221ece2SMatthew G. Knepley 3863221ece2SMatthew G. Knepley nsize = (len + (PETSC_MEMALIGN-1)) & ~(PETSC_MEMALIGN-1); 3873221ece2SMatthew G. Knepley ierr = PetscReallocAlign(nsize+sizeof(TrSPACE)+sizeof(PetscClassId),lineno,function,filename,(void**)&inew);CHKERRQ(ierr); 3883221ece2SMatthew G. Knepley 3893221ece2SMatthew G. Knepley head = (TRSPACE*)inew; 3903221ece2SMatthew G. Knepley inew += sizeof(TrSPACE); 3913221ece2SMatthew G. Knepley 3923221ece2SMatthew G. Knepley if (TRhead) TRhead->prev = head; 3933221ece2SMatthew G. Knepley head->next = TRhead; 3943221ece2SMatthew G. Knepley TRhead = head; 3953221ece2SMatthew G. Knepley head->prev = NULL; 3963221ece2SMatthew G. Knepley head->size = nsize; 3973221ece2SMatthew G. Knepley head->id = TRid; 3983221ece2SMatthew G. Knepley head->lineno = lineno; 3993221ece2SMatthew G. Knepley 4003221ece2SMatthew G. Knepley head->filename = filename; 4013221ece2SMatthew G. Knepley head->functionname = function; 4023221ece2SMatthew G. Knepley head->classid = CLASSID_VALUE; 4033221ece2SMatthew G. Knepley *(PetscClassId*)(inew + nsize) = CLASSID_VALUE; 4043221ece2SMatthew G. Knepley 4053221ece2SMatthew G. Knepley TRallocated += nsize; 4063221ece2SMatthew G. Knepley if (TRallocated > TRMaxMem) TRMaxMem = TRallocated; 4073221ece2SMatthew G. Knepley TRfrags++; 4083221ece2SMatthew G. Knepley 4093221ece2SMatthew G. Knepley #if defined(PETSC_USE_DEBUG) 4103221ece2SMatthew G. Knepley if (PetscStackActive()) { 4113221ece2SMatthew G. Knepley ierr = PetscStackCopy(petscstack,&head->stack);CHKERRQ(ierr); 4123221ece2SMatthew G. Knepley /* fix the line number to where the malloc() was called, not the PetscFunctionBegin; */ 4133221ece2SMatthew G. Knepley head->stack.line[head->stack.currentsize-2] = lineno; 4143221ece2SMatthew G. Knepley } else { 4153221ece2SMatthew G. Knepley head->stack.currentsize = 0; 4163221ece2SMatthew G. Knepley } 4173221ece2SMatthew G. Knepley #endif 4183221ece2SMatthew G. Knepley 4193221ece2SMatthew G. Knepley /* 4203221ece2SMatthew G. Knepley Allow logging of all mallocs made 4213221ece2SMatthew G. Knepley */ 4223221ece2SMatthew G. Knepley if (PetscLogMalloc > -1 && PetscLogMalloc < PetscLogMallocMax && len >= PetscLogMallocThreshold) { 4233221ece2SMatthew G. Knepley if (!PetscLogMalloc) { 4243221ece2SMatthew G. Knepley PetscLogMallocLength = (size_t*)malloc(PetscLogMallocMax*sizeof(size_t)); 4253221ece2SMatthew G. Knepley if (!PetscLogMallocLength) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM," "); 4263221ece2SMatthew G. Knepley 4273221ece2SMatthew G. Knepley PetscLogMallocFile = (const char**)malloc(PetscLogMallocMax*sizeof(char*)); 4283221ece2SMatthew G. Knepley if (!PetscLogMallocFile) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM," "); 4293221ece2SMatthew G. Knepley 4303221ece2SMatthew G. Knepley PetscLogMallocFunction = (const char**)malloc(PetscLogMallocMax*sizeof(char*)); 4313221ece2SMatthew G. Knepley if (!PetscLogMallocFunction) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM," "); 4323221ece2SMatthew G. Knepley } 4333221ece2SMatthew G. Knepley PetscLogMallocLength[PetscLogMalloc] = nsize; 4343221ece2SMatthew G. Knepley PetscLogMallocFile[PetscLogMalloc] = filename; 4353221ece2SMatthew G. Knepley PetscLogMallocFunction[PetscLogMalloc++] = function; 4363221ece2SMatthew G. Knepley } 4373221ece2SMatthew G. Knepley *result = (void*)inew; 4383221ece2SMatthew G. Knepley PetscFunctionReturn(0); 4393221ece2SMatthew G. Knepley } 4403221ece2SMatthew G. Knepley 4413221ece2SMatthew G. Knepley 442fe7fb379SMatthew Knepley /*@C 4430841954dSBarry Smith PetscMemoryView - Shows the amount of memory currently being used 444e5c89e4eSSatish Balay in a communicator. 445e5c89e4eSSatish Balay 446e5c89e4eSSatish Balay Collective on PetscViewer 447e5c89e4eSSatish Balay 448e5c89e4eSSatish Balay Input Parameter: 449e5c89e4eSSatish Balay + viewer - the viewer that defines the communicator 450e5c89e4eSSatish Balay - message - string printed before values 451e5c89e4eSSatish Balay 4520841954dSBarry Smith Options Database: 4530841954dSBarry Smith + -malloc - have PETSc track how much memory it has allocated 4540841954dSBarry Smith - -memory_view - during PetscFinalize() have this routine called 4550841954dSBarry Smith 456e5c89e4eSSatish Balay Level: intermediate 457e5c89e4eSSatish Balay 458e5c89e4eSSatish Balay Concepts: memory usage 459e5c89e4eSSatish Balay 4600841954dSBarry Smith .seealso: PetscMallocDump(), PetscMemoryGetCurrentUsage(), PetscMemorySetGetMaximumUsage() 461e5c89e4eSSatish Balay @*/ 4620841954dSBarry Smith PetscErrorCode PetscMemoryView(PetscViewer viewer,const char message[]) 463e5c89e4eSSatish Balay { 4640841954dSBarry Smith PetscLogDouble allocated,allocatedmax,resident,residentmax,gallocated,gallocatedmax,gresident,gresidentmax,maxgallocated,maxgallocatedmax,maxgresident,maxgresidentmax; 4650841954dSBarry Smith PetscLogDouble mingallocated,mingallocatedmax,mingresident,mingresidentmax; 466e5c89e4eSSatish Balay PetscErrorCode ierr; 467e5c89e4eSSatish Balay MPI_Comm comm; 468e5c89e4eSSatish Balay 469e5c89e4eSSatish Balay PetscFunctionBegin; 470e5c89e4eSSatish Balay if (!viewer) viewer = PETSC_VIEWER_STDOUT_WORLD; 471e5c89e4eSSatish Balay ierr = PetscMallocGetCurrentUsage(&allocated);CHKERRQ(ierr); 4720841954dSBarry Smith ierr = PetscMallocGetMaximumUsage(&allocatedmax);CHKERRQ(ierr); 473e5c89e4eSSatish Balay ierr = PetscMemoryGetCurrentUsage(&resident);CHKERRQ(ierr); 474e5c89e4eSSatish Balay ierr = PetscMemoryGetMaximumUsage(&residentmax);CHKERRQ(ierr); 475e5c89e4eSSatish Balay if (residentmax > 0) residentmax = PetscMax(resident,residentmax); 476e5c89e4eSSatish Balay ierr = PetscObjectGetComm((PetscObject)viewer,&comm);CHKERRQ(ierr); 477e5c89e4eSSatish Balay ierr = PetscViewerASCIIPrintf(viewer,message);CHKERRQ(ierr); 478e5c89e4eSSatish Balay if (resident && residentmax && allocated) { 4790841954dSBarry Smith ierr = MPI_Reduce(&residentmax,&gresidentmax,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);CHKERRQ(ierr); 4800841954dSBarry Smith ierr = MPI_Reduce(&residentmax,&maxgresidentmax,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);CHKERRQ(ierr); 4810841954dSBarry Smith ierr = MPI_Reduce(&residentmax,&mingresidentmax,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);CHKERRQ(ierr); 4820841954dSBarry Smith ierr = PetscViewerASCIIPrintf(viewer,"Maximum (over computational time) process memory: total %5.4e max %5.4e min %5.4e\n",gresidentmax,maxgresidentmax,mingresidentmax);CHKERRQ(ierr); 4830841954dSBarry Smith ierr = MPI_Reduce(&resident,&gresident,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);CHKERRQ(ierr); 4840841954dSBarry Smith ierr = MPI_Reduce(&resident,&maxgresident,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);CHKERRQ(ierr); 4850841954dSBarry Smith ierr = MPI_Reduce(&resident,&mingresident,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);CHKERRQ(ierr); 4860841954dSBarry Smith ierr = PetscViewerASCIIPrintf(viewer,"Current process memory: total %5.4e max %5.4e min %5.4e\n",gresident,maxgresident,mingresident);CHKERRQ(ierr); 4870841954dSBarry Smith ierr = MPI_Reduce(&allocatedmax,&gallocatedmax,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);CHKERRQ(ierr); 4880841954dSBarry Smith ierr = MPI_Reduce(&allocatedmax,&maxgallocatedmax,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);CHKERRQ(ierr); 4890841954dSBarry Smith ierr = MPI_Reduce(&allocatedmax,&mingallocatedmax,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);CHKERRQ(ierr); 4900841954dSBarry Smith ierr = PetscViewerASCIIPrintf(viewer,"Maximum (over computational time) space PetscMalloc()ed: total %5.4e max %5.4e min %5.4e\n",gallocatedmax,maxgallocatedmax,mingallocatedmax);CHKERRQ(ierr); 4910841954dSBarry Smith ierr = MPI_Reduce(&allocated,&gallocated,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);CHKERRQ(ierr); 4920841954dSBarry Smith ierr = MPI_Reduce(&allocated,&maxgallocated,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);CHKERRQ(ierr); 4930841954dSBarry Smith ierr = MPI_Reduce(&allocated,&mingallocated,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);CHKERRQ(ierr); 4940841954dSBarry Smith ierr = PetscViewerASCIIPrintf(viewer,"Current space PetscMalloc()ed: total %5.4e max %5.4e min %5.4e\n",gallocated,maxgallocated,mingallocated);CHKERRQ(ierr); 495e5c89e4eSSatish Balay } else if (resident && residentmax) { 4960841954dSBarry Smith ierr = MPI_Reduce(&residentmax,&gresidentmax,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);CHKERRQ(ierr); 4970841954dSBarry Smith ierr = MPI_Reduce(&residentmax,&maxgresidentmax,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);CHKERRQ(ierr); 4980841954dSBarry Smith ierr = MPI_Reduce(&residentmax,&mingresidentmax,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);CHKERRQ(ierr); 4990841954dSBarry Smith ierr = PetscViewerASCIIPrintf(viewer,"Maximum (over computational time) process memory: total %5.4e max %5.4e min %5.4e\n",gresidentmax,maxgresidentmax,mingresidentmax);CHKERRQ(ierr); 5000841954dSBarry Smith ierr = MPI_Reduce(&resident,&gresident,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);CHKERRQ(ierr); 5010841954dSBarry Smith ierr = MPI_Reduce(&resident,&maxgresident,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);CHKERRQ(ierr); 5020841954dSBarry Smith ierr = MPI_Reduce(&resident,&mingresident,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);CHKERRQ(ierr); 5030841954dSBarry Smith ierr = PetscViewerASCIIPrintf(viewer,"Current process memory: total %5.4e max %5.4e min %5.4e\n",gresident,maxgresident,mingresident);CHKERRQ(ierr); 504e5c89e4eSSatish Balay } else if (resident && allocated) { 5050841954dSBarry Smith ierr = MPI_Reduce(&resident,&gresident,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);CHKERRQ(ierr); 5060841954dSBarry Smith ierr = MPI_Reduce(&resident,&maxgresident,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);CHKERRQ(ierr); 5070841954dSBarry Smith ierr = MPI_Reduce(&resident,&mingresident,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);CHKERRQ(ierr); 5080841954dSBarry Smith ierr = PetscViewerASCIIPrintf(viewer,"Current process memory: total %5.4e max %5.4e min %5.4e\n",gresident,maxgresident,mingresident);CHKERRQ(ierr); 5090841954dSBarry Smith ierr = MPI_Reduce(&allocated,&gallocated,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);CHKERRQ(ierr); 5100841954dSBarry Smith ierr = MPI_Reduce(&allocated,&maxgallocated,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);CHKERRQ(ierr); 5110841954dSBarry Smith ierr = MPI_Reduce(&allocated,&mingallocated,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);CHKERRQ(ierr); 5120841954dSBarry Smith ierr = PetscViewerASCIIPrintf(viewer,"Current space PetscMalloc()ed: total %5.4e max %5.4e min %5.4e\n",gallocated,maxgallocated,mingallocated);CHKERRQ(ierr); 5130841954dSBarry Smith ierr = PetscViewerASCIIPrintf(viewer,"Run with -memory_view to get maximum memory usage\n");CHKERRQ(ierr); 514e5c89e4eSSatish Balay } else if (allocated) { 5150841954dSBarry Smith ierr = MPI_Reduce(&allocated,&gallocated,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);CHKERRQ(ierr); 5160841954dSBarry Smith ierr = MPI_Reduce(&allocated,&maxgallocated,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);CHKERRQ(ierr); 5170841954dSBarry Smith ierr = MPI_Reduce(&allocated,&mingallocated,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);CHKERRQ(ierr); 5180841954dSBarry Smith ierr = PetscViewerASCIIPrintf(viewer,"Current space PetscMalloc()ed: total %5.4e max %5.4e min %5.4e\n",gallocated,maxgallocated,mingallocated);CHKERRQ(ierr); 5190841954dSBarry Smith ierr = PetscViewerASCIIPrintf(viewer,"Run with -memory_view to get maximum memory usage\n");CHKERRQ(ierr); 5200841954dSBarry Smith ierr = PetscViewerASCIIPrintf(viewer,"OS cannot compute process memory\n");CHKERRQ(ierr); 521e5c89e4eSSatish Balay } else { 522e5c89e4eSSatish Balay ierr = PetscViewerASCIIPrintf(viewer,"Run with -malloc to get statistics on PetscMalloc() calls\nOS cannot compute process memory\n");CHKERRQ(ierr); 523e5c89e4eSSatish Balay } 524e5c89e4eSSatish Balay ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 525e5c89e4eSSatish Balay PetscFunctionReturn(0); 526e5c89e4eSSatish Balay } 527e5c89e4eSSatish Balay 52846eb3923SBarry Smith /*@ 529e5c89e4eSSatish Balay PetscMallocGetCurrentUsage - gets the current amount of memory used that was PetscMalloc()ed 530e5c89e4eSSatish Balay 531e5c89e4eSSatish Balay Not Collective 532e5c89e4eSSatish Balay 533e5c89e4eSSatish Balay Output Parameters: 534e5c89e4eSSatish Balay . space - number of bytes currently allocated 535e5c89e4eSSatish Balay 536e5c89e4eSSatish Balay Level: intermediate 537e5c89e4eSSatish Balay 538e5c89e4eSSatish Balay Concepts: memory usage 539e5c89e4eSSatish Balay 540e5c89e4eSSatish Balay .seealso: PetscMallocDump(), PetscMallocDumpLog(), PetscMallocGetMaximumUsage(), PetscMemoryGetCurrentUsage(), 541e5c89e4eSSatish Balay PetscMemoryGetMaximumUsage() 542e5c89e4eSSatish Balay @*/ 5437087cfbeSBarry Smith PetscErrorCode PetscMallocGetCurrentUsage(PetscLogDouble *space) 544e5c89e4eSSatish Balay { 545e5c89e4eSSatish Balay PetscFunctionBegin; 546e5c89e4eSSatish Balay *space = (PetscLogDouble) TRallocated; 547e5c89e4eSSatish Balay PetscFunctionReturn(0); 548e5c89e4eSSatish Balay } 549e5c89e4eSSatish Balay 550dc37d89fSBarry Smith /*@ 551e5c89e4eSSatish Balay PetscMallocGetMaximumUsage - gets the maximum amount of memory used that was PetscMalloc()ed at any time 552e5c89e4eSSatish Balay during this run. 553e5c89e4eSSatish Balay 554e5c89e4eSSatish Balay Not Collective 555e5c89e4eSSatish Balay 556e5c89e4eSSatish Balay Output Parameters: 557e5c89e4eSSatish Balay . space - maximum number of bytes ever allocated at one time 558e5c89e4eSSatish Balay 559e5c89e4eSSatish Balay Level: intermediate 560e5c89e4eSSatish Balay 561e5c89e4eSSatish Balay Concepts: memory usage 562e5c89e4eSSatish Balay 563e5c89e4eSSatish Balay .seealso: PetscMallocDump(), PetscMallocDumpLog(), PetscMallocGetMaximumUsage(), PetscMemoryGetCurrentUsage(), 564e5c89e4eSSatish Balay PetscMemoryGetCurrentUsage() 565e5c89e4eSSatish Balay @*/ 5667087cfbeSBarry Smith PetscErrorCode PetscMallocGetMaximumUsage(PetscLogDouble *space) 567e5c89e4eSSatish Balay { 568e5c89e4eSSatish Balay PetscFunctionBegin; 569e5c89e4eSSatish Balay *space = (PetscLogDouble) TRMaxMem; 570e5c89e4eSSatish Balay PetscFunctionReturn(0); 571e5c89e4eSSatish Balay } 572e5c89e4eSSatish Balay 573a64a8e02SBarry Smith #if defined(PETSC_USE_DEBUG) 574a64a8e02SBarry Smith /*@C 575a64a8e02SBarry Smith PetscMallocGetStack - returns a pointer to the stack for the location in the program a call to PetscMalloc() was used to obtain that memory 576a64a8e02SBarry Smith 577a64a8e02SBarry Smith Collective on PETSC_COMM_WORLD 578a64a8e02SBarry Smith 579a64a8e02SBarry Smith Input Parameter: 580a64a8e02SBarry Smith . ptr - the memory location 581a64a8e02SBarry Smith 582a64a8e02SBarry Smith Output Paramter: 583a64a8e02SBarry Smith . stack - the stack indicating where the program allocated this memory 584a64a8e02SBarry Smith 585a64a8e02SBarry Smith Level: intermediate 586a64a8e02SBarry Smith 587a64a8e02SBarry Smith .seealso: PetscMallocGetCurrentUsage(), PetscMallocDumpLog() 588a64a8e02SBarry Smith @*/ 589a64a8e02SBarry Smith PetscErrorCode PetscMallocGetStack(void *ptr,PetscStack **stack) 590a64a8e02SBarry Smith { 591a64a8e02SBarry Smith TRSPACE *head; 592a64a8e02SBarry Smith 593a64a8e02SBarry Smith PetscFunctionBegin; 594a64a8e02SBarry Smith head = (TRSPACE*) (((char*)ptr) - HEADER_BYTES); 595a64a8e02SBarry Smith *stack = &head->stack; 596a64a8e02SBarry Smith PetscFunctionReturn(0); 597a64a8e02SBarry Smith } 59876386721SLisandro Dalcin #else 59976386721SLisandro Dalcin PetscErrorCode PetscMallocGetStack(void *ptr,void **stack) 60076386721SLisandro Dalcin { 60176386721SLisandro Dalcin PetscFunctionBegin; 602f0ba7cfcSLisandro Dalcin *stack = NULL; 60376386721SLisandro Dalcin PetscFunctionReturn(0); 60476386721SLisandro Dalcin } 605a64a8e02SBarry Smith #endif 606a64a8e02SBarry Smith 607e5c89e4eSSatish Balay /*@C 608e5c89e4eSSatish Balay PetscMallocDump - Dumps the allocated memory blocks to a file. The information 609e5c89e4eSSatish Balay printed is: size of space (in bytes), address of space, id of space, 610e5c89e4eSSatish Balay file in which space was allocated, and line number at which it was 611e5c89e4eSSatish Balay allocated. 612e5c89e4eSSatish Balay 613e5c89e4eSSatish Balay Collective on PETSC_COMM_WORLD 614e5c89e4eSSatish Balay 615e5c89e4eSSatish Balay Input Parameter: 616e5c89e4eSSatish Balay . fp - file pointer. If fp is NULL, stdout is assumed. 617e5c89e4eSSatish Balay 618e5c89e4eSSatish Balay Options Database Key: 619e5c89e4eSSatish Balay . -malloc_dump - Dumps unfreed memory during call to PetscFinalize() 620e5c89e4eSSatish Balay 621e5c89e4eSSatish Balay Level: intermediate 622e5c89e4eSSatish Balay 623e5c89e4eSSatish Balay Fortran Note: 624e5c89e4eSSatish Balay The calling sequence in Fortran is PetscMallocDump(integer ierr) 625e5c89e4eSSatish Balay The fp defaults to stdout. 626e5c89e4eSSatish Balay 62795452b02SPatrick Sanan Notes: 62895452b02SPatrick Sanan uses MPI_COMM_WORLD, because this may be called in PetscFinalize() after PETSC_COMM_WORLD 629e5c89e4eSSatish Balay has been freed. 630e5c89e4eSSatish Balay 631e5c89e4eSSatish Balay Concepts: memory usage 632e5c89e4eSSatish Balay Concepts: memory bleeding 633e5c89e4eSSatish Balay Concepts: bleeding memory 634e5c89e4eSSatish Balay 6359e9a1f8fSvictor .seealso: PetscMallocGetCurrentUsage(), PetscMallocDumpLog() 636e5c89e4eSSatish Balay @*/ 6377087cfbeSBarry Smith PetscErrorCode PetscMallocDump(FILE *fp) 638e5c89e4eSSatish Balay { 639e5c89e4eSSatish Balay TRSPACE *head; 6405486ca60SMatthew G. Knepley PetscInt libAlloc = 0; 641e5c89e4eSSatish Balay PetscErrorCode ierr; 642e5c89e4eSSatish Balay PetscMPIInt rank; 643e5c89e4eSSatish Balay 644e5c89e4eSSatish Balay PetscFunctionBegin; 645e5c89e4eSSatish Balay ierr = MPI_Comm_rank(MPI_COMM_WORLD,&rank);CHKERRQ(ierr); 646da9f1d6bSBarry Smith if (!fp) fp = PETSC_STDOUT; 647e5c89e4eSSatish Balay head = TRhead; 648e5c89e4eSSatish Balay while (head) { 6495486ca60SMatthew G. Knepley PetscBool isLib; 6505486ca60SMatthew G. Knepley 6515486ca60SMatthew G. Knepley ierr = PetscStrcmp(head->functionname, "PetscDLLibraryOpen", &isLib);CHKERRQ(ierr); 6525486ca60SMatthew G. Knepley libAlloc += head->size; 6535486ca60SMatthew G. Knepley head = head->next; 6545486ca60SMatthew G. Knepley } 6555486ca60SMatthew G. Knepley if (TRallocated - libAlloc > 0) fprintf(fp,"[%d]Total space allocated %.0f bytes\n",rank,(PetscLogDouble)TRallocated); 6565486ca60SMatthew G. Knepley head = TRhead; 6575486ca60SMatthew G. Knepley while (head) { 6585486ca60SMatthew G. Knepley PetscBool isLib; 6595486ca60SMatthew G. Knepley 6605486ca60SMatthew G. Knepley ierr = PetscStrcmp(head->functionname, "PetscDLLibraryOpen", &isLib);CHKERRQ(ierr); 6615486ca60SMatthew G. Knepley if (!isLib) { 662efca3c55SSatish Balay fprintf(fp,"[%2d]%.0f bytes %s() line %d in %s\n",rank,(PetscLogDouble)head->size,head->functionname,head->lineno,head->filename); 6638bf1f09cSShri Abhyankar #if defined(PETSC_USE_DEBUG) 664e5c89e4eSSatish Balay ierr = PetscStackPrint(&head->stack,fp);CHKERRQ(ierr); 665e5c89e4eSSatish Balay #endif 6665486ca60SMatthew G. Knepley } 667e5c89e4eSSatish Balay head = head->next; 668e5c89e4eSSatish Balay } 669e5c89e4eSSatish Balay PetscFunctionReturn(0); 670e5c89e4eSSatish Balay } 671e5c89e4eSSatish Balay 672e5c89e4eSSatish Balay /* ---------------------------------------------------------------------------- */ 673e5c89e4eSSatish Balay 674dc37d89fSBarry Smith /*@ 675e5c89e4eSSatish Balay PetscMallocSetDumpLog - Activates logging of all calls to PetscMalloc(). 676e5c89e4eSSatish Balay 677e5c89e4eSSatish Balay Not Collective 678e5c89e4eSSatish Balay 679e5c89e4eSSatish Balay Options Database Key: 680574034a9SJed Brown + -malloc_log <filename> - Activates PetscMallocDumpLog() 681574034a9SJed Brown - -malloc_log_threshold <min> - Activates logging and sets a minimum size 682e5c89e4eSSatish Balay 683e5c89e4eSSatish Balay Level: advanced 684e5c89e4eSSatish Balay 685574034a9SJed Brown .seealso: PetscMallocDump(), PetscMallocDumpLog(), PetscMallocSetDumpLogThreshold() 686e5c89e4eSSatish Balay @*/ 6877087cfbeSBarry Smith PetscErrorCode PetscMallocSetDumpLog(void) 688e5c89e4eSSatish Balay { 68921b680ceSJed Brown PetscErrorCode ierr; 69021b680ceSJed Brown 691e5c89e4eSSatish Balay PetscFunctionBegin; 692e5c89e4eSSatish Balay PetscLogMalloc = 0; 693a297a907SKarl Rupp 69421b680ceSJed Brown ierr = PetscMemorySetGetMaximumUsage();CHKERRQ(ierr); 695e5c89e4eSSatish Balay PetscFunctionReturn(0); 696e5c89e4eSSatish Balay } 697e5c89e4eSSatish Balay 698dc37d89fSBarry Smith /*@ 699574034a9SJed Brown PetscMallocSetDumpLogThreshold - Activates logging of all calls to PetscMalloc(). 700574034a9SJed Brown 701574034a9SJed Brown Not Collective 702574034a9SJed Brown 703574034a9SJed Brown Input Arguments: 704574034a9SJed Brown . logmin - minimum allocation size to log, or PETSC_DEFAULT 705574034a9SJed Brown 706574034a9SJed Brown Options Database Key: 707574034a9SJed Brown + -malloc_log <filename> - Activates PetscMallocDumpLog() 708574034a9SJed Brown - -malloc_log_threshold <min> - Activates logging and sets a minimum size 709574034a9SJed Brown 710574034a9SJed Brown Level: advanced 711574034a9SJed Brown 712574034a9SJed Brown .seealso: PetscMallocDump(), PetscMallocDumpLog(), PetscMallocSetDumpLog() 713574034a9SJed Brown @*/ 714574034a9SJed Brown PetscErrorCode PetscMallocSetDumpLogThreshold(PetscLogDouble logmin) 715574034a9SJed Brown { 716574034a9SJed Brown PetscErrorCode ierr; 717574034a9SJed Brown 718574034a9SJed Brown PetscFunctionBegin; 719574034a9SJed Brown ierr = PetscMallocSetDumpLog();CHKERRQ(ierr); 720574034a9SJed Brown if (logmin < 0) logmin = 0.0; /* PETSC_DEFAULT or PETSC_DECIDE */ 721574034a9SJed Brown PetscLogMallocThreshold = (size_t)logmin; 722574034a9SJed Brown PetscFunctionReturn(0); 723574034a9SJed Brown } 724574034a9SJed Brown 725dc37d89fSBarry Smith /*@ 72618a2528dSJed Brown PetscMallocGetDumpLog - Determine whether all calls to PetscMalloc() are being logged 72718a2528dSJed Brown 72818a2528dSJed Brown Not Collective 72918a2528dSJed Brown 73018a2528dSJed Brown Output Arguments 73118a2528dSJed Brown . logging - PETSC_TRUE if logging is active 73218a2528dSJed Brown 73318a2528dSJed Brown Options Database Key: 73418a2528dSJed Brown . -malloc_log - Activates PetscMallocDumpLog() 73518a2528dSJed Brown 73618a2528dSJed Brown Level: advanced 73718a2528dSJed Brown 73818a2528dSJed Brown .seealso: PetscMallocDump(), PetscMallocDumpLog() 73918a2528dSJed Brown @*/ 74018a2528dSJed Brown PetscErrorCode PetscMallocGetDumpLog(PetscBool *logging) 74118a2528dSJed Brown { 74218a2528dSJed Brown 74318a2528dSJed Brown PetscFunctionBegin; 74418a2528dSJed Brown *logging = (PetscBool)(PetscLogMalloc >= 0); 74518a2528dSJed Brown PetscFunctionReturn(0); 74618a2528dSJed Brown } 74718a2528dSJed Brown 748e5c89e4eSSatish Balay /*@C 749e5c89e4eSSatish Balay PetscMallocDumpLog - Dumps the log of all calls to PetscMalloc(); also calls 75021b680ceSJed Brown PetscMemoryGetMaximumUsage() 751e5c89e4eSSatish Balay 752e5c89e4eSSatish Balay Collective on PETSC_COMM_WORLD 753e5c89e4eSSatish Balay 754e5c89e4eSSatish Balay Input Parameter: 7550298fd71SBarry Smith . fp - file pointer; or NULL 756e5c89e4eSSatish Balay 757e5c89e4eSSatish Balay Options Database Key: 758e5c89e4eSSatish Balay . -malloc_log - Activates PetscMallocDumpLog() 759e5c89e4eSSatish Balay 760e5c89e4eSSatish Balay Level: advanced 761e5c89e4eSSatish Balay 762e5c89e4eSSatish Balay Fortran Note: 763e5c89e4eSSatish Balay The calling sequence in Fortran is PetscMallocDumpLog(integer ierr) 764e5c89e4eSSatish Balay The fp defaults to stdout. 765e5c89e4eSSatish Balay 766e5c89e4eSSatish Balay .seealso: PetscMallocGetCurrentUsage(), PetscMallocDump(), PetscMallocSetDumpLog() 767e5c89e4eSSatish Balay @*/ 7687087cfbeSBarry Smith PetscErrorCode PetscMallocDumpLog(FILE *fp) 769e5c89e4eSSatish Balay { 770e5c89e4eSSatish Balay PetscInt i,j,n,dummy,*perm; 771e5c89e4eSSatish Balay size_t *shortlength; 772f56c2debSBarry Smith int *shortcount,err; 773e5c89e4eSSatish Balay PetscMPIInt rank,size,tag = 1212 /* very bad programming */; 774ace3abfcSBarry Smith PetscBool match; 775e5c89e4eSSatish Balay const char **shortfunction; 776e5c89e4eSSatish Balay PetscLogDouble rss; 777e5c89e4eSSatish Balay MPI_Status status; 778e5c89e4eSSatish Balay PetscErrorCode ierr; 779e5c89e4eSSatish Balay 780e5c89e4eSSatish Balay PetscFunctionBegin; 781e5c89e4eSSatish Balay ierr = MPI_Comm_rank(MPI_COMM_WORLD,&rank);CHKERRQ(ierr); 782e5c89e4eSSatish Balay ierr = MPI_Comm_size(MPI_COMM_WORLD,&size);CHKERRQ(ierr); 783e5c89e4eSSatish Balay /* 784e5c89e4eSSatish Balay Try to get the data printed in order by processor. This will only sometimes work 785e5c89e4eSSatish Balay */ 786f56c2debSBarry Smith err = fflush(fp); 787e32f2f54SBarry Smith if (err) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"fflush() failed on file"); 788f56c2debSBarry Smith 789e5c89e4eSSatish Balay ierr = MPI_Barrier(MPI_COMM_WORLD);CHKERRQ(ierr); 790e5c89e4eSSatish Balay if (rank) { 791e5c89e4eSSatish Balay ierr = MPI_Recv(&dummy,1,MPIU_INT,rank-1,tag,MPI_COMM_WORLD,&status);CHKERRQ(ierr); 792e5c89e4eSSatish Balay } 793e5c89e4eSSatish Balay 794768aa557SSatish Balay if (PetscLogMalloc < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"PetscMallocDumpLog() called without call to PetscMallocSetDumpLog() this is often due to\n setting the option -malloc_log AFTER PetscInitialize() with PetscOptionsInsert() or PetscOptionsInsertFile()"); 795768aa557SSatish Balay 796da9f1d6bSBarry Smith if (!fp) fp = PETSC_STDOUT; 797f3d65365SJed Brown ierr = PetscMemoryGetMaximumUsage(&rss);CHKERRQ(ierr); 798e5c89e4eSSatish Balay if (rss) { 799f3d65365SJed Brown ierr = PetscFPrintf(MPI_COMM_WORLD,fp,"[%d] Maximum memory PetscMalloc()ed %.0f maximum size of entire process %.0f\n",rank,(PetscLogDouble)TRMaxMem,rss);CHKERRQ(ierr); 800e5c89e4eSSatish Balay } else { 801e5c89e4eSSatish Balay ierr = PetscFPrintf(MPI_COMM_WORLD,fp,"[%d] Maximum memory PetscMalloc()ed %.0f OS cannot compute size of entire process\n",rank,(PetscLogDouble)TRMaxMem);CHKERRQ(ierr); 802e5c89e4eSSatish Balay } 803e32f2f54SBarry Smith shortcount = (int*)malloc(PetscLogMalloc*sizeof(int));if (!shortcount) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM,"Out of memory"); 804e32f2f54SBarry Smith shortlength = (size_t*)malloc(PetscLogMalloc*sizeof(size_t));if (!shortlength) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM,"Out of memory"); 805e32f2f54SBarry Smith shortfunction = (const char**)malloc(PetscLogMalloc*sizeof(char*));if (!shortfunction) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM,"Out of memory"); 80697b9d747SJed Brown for (i=0,n=0; i<PetscLogMalloc; i++) { 807e5c89e4eSSatish Balay for (j=0; j<n; j++) { 808e5c89e4eSSatish Balay ierr = PetscStrcmp(shortfunction[j],PetscLogMallocFunction[i],&match);CHKERRQ(ierr); 809e5c89e4eSSatish Balay if (match) { 810e5c89e4eSSatish Balay shortlength[j] += PetscLogMallocLength[i]; 81159ffdab8SBarry Smith shortcount[j]++; 812e5c89e4eSSatish Balay goto foundit; 813e5c89e4eSSatish Balay } 814e5c89e4eSSatish Balay } 815e5c89e4eSSatish Balay shortfunction[n] = PetscLogMallocFunction[i]; 816e5c89e4eSSatish Balay shortlength[n] = PetscLogMallocLength[i]; 81759ffdab8SBarry Smith shortcount[n] = 1; 818e5c89e4eSSatish Balay n++; 819e5c89e4eSSatish Balay foundit:; 820e5c89e4eSSatish Balay } 821e5c89e4eSSatish Balay 822e32f2f54SBarry Smith perm = (PetscInt*)malloc(n*sizeof(PetscInt));if (!perm) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM,"Out of memory"); 823e5c89e4eSSatish Balay for (i=0; i<n; i++) perm[i] = i; 824e5c89e4eSSatish Balay ierr = PetscSortStrWithPermutation(n,(const char**)shortfunction,perm);CHKERRQ(ierr); 825e5c89e4eSSatish Balay 826e5c89e4eSSatish Balay ierr = PetscFPrintf(MPI_COMM_WORLD,fp,"[%d] Memory usage sorted by function\n",rank);CHKERRQ(ierr); 827e5c89e4eSSatish Balay for (i=0; i<n; i++) { 82859ffdab8SBarry Smith ierr = PetscFPrintf(MPI_COMM_WORLD,fp,"[%d] %d %.0f %s()\n",rank,shortcount[perm[i]],(PetscLogDouble)shortlength[perm[i]],shortfunction[perm[i]]);CHKERRQ(ierr); 829e5c89e4eSSatish Balay } 830e5c89e4eSSatish Balay free(perm); 831e5c89e4eSSatish Balay free(shortlength); 83259ffdab8SBarry Smith free(shortcount); 833e5c89e4eSSatish Balay free((char**)shortfunction); 834f56c2debSBarry Smith err = fflush(fp); 835e32f2f54SBarry Smith if (err) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"fflush() failed on file"); 836e5c89e4eSSatish Balay if (rank != size-1) { 837e5c89e4eSSatish Balay ierr = MPI_Send(&dummy,1,MPIU_INT,rank+1,tag,MPI_COMM_WORLD);CHKERRQ(ierr); 838e5c89e4eSSatish Balay } 839e5c89e4eSSatish Balay PetscFunctionReturn(0); 840e5c89e4eSSatish Balay } 841e5c89e4eSSatish Balay 842e5c89e4eSSatish Balay /* ---------------------------------------------------------------------------- */ 843e5c89e4eSSatish Balay 844dc37d89fSBarry Smith /*@ 845e5c89e4eSSatish Balay PetscMallocDebug - Turns on/off debugging for the memory management routines. 846e5c89e4eSSatish Balay 847e5c89e4eSSatish Balay Not Collective 848e5c89e4eSSatish Balay 849e5c89e4eSSatish Balay Input Parameter: 850e5c89e4eSSatish Balay . level - PETSC_TRUE or PETSC_FALSE 851e5c89e4eSSatish Balay 852e5c89e4eSSatish Balay Level: intermediate 853e5c89e4eSSatish Balay 854e5c89e4eSSatish Balay .seealso: CHKMEMQ(), PetscMallocValidate() 855e5c89e4eSSatish Balay @*/ 8567087cfbeSBarry Smith PetscErrorCode PetscMallocDebug(PetscBool level) 857e5c89e4eSSatish Balay { 858e5c89e4eSSatish Balay PetscFunctionBegin; 859e5c89e4eSSatish Balay TRdebugLevel = level; 860e5c89e4eSSatish Balay PetscFunctionReturn(0); 861e5c89e4eSSatish Balay } 8620acecf5bSBarry Smith 863dc37d89fSBarry Smith /*@ 8640acecf5bSBarry Smith PetscMallocGetDebug - Indicates if any PETSc is doing ANY memory debugging. 8650acecf5bSBarry Smith 8660acecf5bSBarry Smith Not Collective 8670acecf5bSBarry Smith 8680acecf5bSBarry Smith Output Parameter: 8690acecf5bSBarry Smith . flg - PETSC_TRUE if any debugger 8700acecf5bSBarry Smith 8710acecf5bSBarry Smith Level: intermediate 8720acecf5bSBarry Smith 8730acecf5bSBarry Smith Note that by default, the debug version always does some debugging unless you run with -malloc no 8740acecf5bSBarry Smith 8750acecf5bSBarry Smith 8760acecf5bSBarry Smith .seealso: CHKMEMQ(), PetscMallocValidate() 8770acecf5bSBarry Smith @*/ 8780acecf5bSBarry Smith PetscErrorCode PetscMallocGetDebug(PetscBool *flg) 8790acecf5bSBarry Smith { 8800acecf5bSBarry Smith PetscFunctionBegin; 8810acecf5bSBarry Smith if (PetscTrMalloc == PetscTrMallocDefault) *flg = PETSC_TRUE; 8820acecf5bSBarry Smith else *flg = PETSC_FALSE; 8830acecf5bSBarry Smith PetscFunctionReturn(0); 8840acecf5bSBarry Smith } 885