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 */ 1695c0884eSLisandro Dalcin PETSC_EXTERN PetscErrorCode PetscMallocAlign(size_t,int,const char[],const char[],void**); 1795c0884eSLisandro Dalcin PETSC_EXTERN PetscErrorCode PetscFreeAlign(void*,int,const char[],const char[]); 1895c0884eSLisandro Dalcin PETSC_EXTERN PetscErrorCode PetscReallocAlign(size_t,int,const char[],const char[],void**); 1995c0884eSLisandro Dalcin PETSC_EXTERN PetscErrorCode PetscTrMallocDefault(size_t,int,const char[],const char[],void**); 2095c0884eSLisandro Dalcin PETSC_EXTERN PetscErrorCode PetscTrFreeDefault(void*,int,const char[],const char[]); 2195c0884eSLisandro 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 7195c0884eSLisandro 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 } 347*f590eff4SLisandro Dalcin /* Realloc with NULL = malloc */ 348*f590eff4SLisandro Dalcin if (!*result) { 349*f590eff4SLisandro Dalcin ierr = PetscTrMallocDefault(len,lineno,function,filename,result);CHKERRQ(ierr); 350*f590eff4SLisandro Dalcin PetscFunctionReturn(0); 351*f590eff4SLisandro Dalcin } 3523221ece2SMatthew G. Knepley 3533221ece2SMatthew G. Knepley if (TRdebugLevel) {ierr = PetscMallocValidate(lineno,function,filename); if (ierr) PetscFunctionReturn(ierr);} 3543221ece2SMatthew G. Knepley 3553221ece2SMatthew G. Knepley ahead = a; 3563221ece2SMatthew G. Knepley a = a - sizeof(TrSPACE); 3573221ece2SMatthew G. Knepley head = (TRSPACE *) a; 3583221ece2SMatthew G. Knepley inew = a; 3593221ece2SMatthew G. Knepley 3603221ece2SMatthew G. Knepley if (head->classid != CLASSID_VALUE) { 3613221ece2SMatthew G. Knepley (*PetscErrorPrintf)("PetscTrReallocDefault() called from %s() line %d in %s\n",function,lineno,filename); 3623221ece2SMatthew G. Knepley (*PetscErrorPrintf)("Block at address %p is corrupted; cannot free;\nmay be block not allocated with PetscMalloc()\n",a); 3633221ece2SMatthew G. Knepley SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEMC,"Bad location or corrupted memory"); 3643221ece2SMatthew G. Knepley } 3653221ece2SMatthew G. Knepley nend = (PetscClassId *)(ahead + head->size); 3663221ece2SMatthew G. Knepley if (*nend != CLASSID_VALUE) { 3673221ece2SMatthew G. Knepley if (*nend == ALREADY_FREED) { 3683221ece2SMatthew G. Knepley (*PetscErrorPrintf)("PetscTrReallocDefault() called from %s() line %d in %s\n",function,lineno,filename); 3693221ece2SMatthew G. Knepley (*PetscErrorPrintf)("Block [id=%d(%.0f)] at address %p was already freed\n",head->id,(PetscLogDouble)head->size,a + sizeof(TrSPACE)); 3703221ece2SMatthew G. Knepley if (head->lineno > 0 && head->lineno < 50000 /* sanity check */) { 3713221ece2SMatthew G. Knepley (*PetscErrorPrintf)("Block freed in %s() line %d in %s\n",head->functionname,head->lineno,head->filename); 3723221ece2SMatthew G. Knepley } else { 3733221ece2SMatthew G. Knepley (*PetscErrorPrintf)("Block allocated in %s() line %d in %s\n",head->functionname,-head->lineno,head->filename); 3743221ece2SMatthew G. Knepley } 3753221ece2SMatthew G. Knepley SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Memory already freed"); 3763221ece2SMatthew G. Knepley } else { 3773221ece2SMatthew G. Knepley /* Damaged tail */ 3783221ece2SMatthew G. Knepley (*PetscErrorPrintf)("PetscTrReallocDefault() called from %s() line %d in %s\n",function,lineno,filename); 3793221ece2SMatthew 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); 3803221ece2SMatthew G. Knepley (*PetscErrorPrintf)("Block allocated in %s() line %d in %s\n",head->functionname,head->lineno,head->filename); 3813221ece2SMatthew G. Knepley SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEMC,"Corrupted memory"); 3823221ece2SMatthew G. Knepley } 3833221ece2SMatthew G. Knepley } 3843221ece2SMatthew G. Knepley 3853221ece2SMatthew G. Knepley TRallocated -= head->size; 3863221ece2SMatthew G. Knepley TRfrags--; 3873221ece2SMatthew G. Knepley if (head->prev) head->prev->next = head->next; 3883221ece2SMatthew G. Knepley else TRhead = head->next; 3893221ece2SMatthew G. Knepley if (head->next) head->next->prev = head->prev; 3903221ece2SMatthew G. Knepley 3913221ece2SMatthew G. Knepley nsize = (len + (PETSC_MEMALIGN-1)) & ~(PETSC_MEMALIGN-1); 3923221ece2SMatthew G. Knepley ierr = PetscReallocAlign(nsize+sizeof(TrSPACE)+sizeof(PetscClassId),lineno,function,filename,(void**)&inew);CHKERRQ(ierr); 3933221ece2SMatthew G. Knepley 3943221ece2SMatthew G. Knepley head = (TRSPACE*)inew; 3953221ece2SMatthew G. Knepley inew += sizeof(TrSPACE); 3963221ece2SMatthew G. Knepley 3973221ece2SMatthew G. Knepley if (TRhead) TRhead->prev = head; 3983221ece2SMatthew G. Knepley head->next = TRhead; 3993221ece2SMatthew G. Knepley TRhead = head; 4003221ece2SMatthew G. Knepley head->prev = NULL; 4013221ece2SMatthew G. Knepley head->size = nsize; 4023221ece2SMatthew G. Knepley head->id = TRid; 4033221ece2SMatthew G. Knepley head->lineno = lineno; 4043221ece2SMatthew G. Knepley 4053221ece2SMatthew G. Knepley head->filename = filename; 4063221ece2SMatthew G. Knepley head->functionname = function; 4073221ece2SMatthew G. Knepley head->classid = CLASSID_VALUE; 4083221ece2SMatthew G. Knepley *(PetscClassId*)(inew + nsize) = CLASSID_VALUE; 4093221ece2SMatthew G. Knepley 4103221ece2SMatthew G. Knepley TRallocated += nsize; 4113221ece2SMatthew G. Knepley if (TRallocated > TRMaxMem) TRMaxMem = TRallocated; 4123221ece2SMatthew G. Knepley TRfrags++; 4133221ece2SMatthew G. Knepley 4143221ece2SMatthew G. Knepley #if defined(PETSC_USE_DEBUG) 4153221ece2SMatthew G. Knepley if (PetscStackActive()) { 4163221ece2SMatthew G. Knepley ierr = PetscStackCopy(petscstack,&head->stack);CHKERRQ(ierr); 4173221ece2SMatthew G. Knepley /* fix the line number to where the malloc() was called, not the PetscFunctionBegin; */ 4183221ece2SMatthew G. Knepley head->stack.line[head->stack.currentsize-2] = lineno; 4193221ece2SMatthew G. Knepley } else { 4203221ece2SMatthew G. Knepley head->stack.currentsize = 0; 4213221ece2SMatthew G. Knepley } 4223221ece2SMatthew G. Knepley #endif 4233221ece2SMatthew G. Knepley 4243221ece2SMatthew G. Knepley /* 4253221ece2SMatthew G. Knepley Allow logging of all mallocs made 4263221ece2SMatthew G. Knepley */ 4273221ece2SMatthew G. Knepley if (PetscLogMalloc > -1 && PetscLogMalloc < PetscLogMallocMax && len >= PetscLogMallocThreshold) { 4283221ece2SMatthew G. Knepley if (!PetscLogMalloc) { 4293221ece2SMatthew G. Knepley PetscLogMallocLength = (size_t*)malloc(PetscLogMallocMax*sizeof(size_t)); 4303221ece2SMatthew G. Knepley if (!PetscLogMallocLength) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM," "); 4313221ece2SMatthew G. Knepley 4323221ece2SMatthew G. Knepley PetscLogMallocFile = (const char**)malloc(PetscLogMallocMax*sizeof(char*)); 4333221ece2SMatthew G. Knepley if (!PetscLogMallocFile) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM," "); 4343221ece2SMatthew G. Knepley 4353221ece2SMatthew G. Knepley PetscLogMallocFunction = (const char**)malloc(PetscLogMallocMax*sizeof(char*)); 4363221ece2SMatthew G. Knepley if (!PetscLogMallocFunction) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM," "); 4373221ece2SMatthew G. Knepley } 4383221ece2SMatthew G. Knepley PetscLogMallocLength[PetscLogMalloc] = nsize; 4393221ece2SMatthew G. Knepley PetscLogMallocFile[PetscLogMalloc] = filename; 4403221ece2SMatthew G. Knepley PetscLogMallocFunction[PetscLogMalloc++] = function; 4413221ece2SMatthew G. Knepley } 4423221ece2SMatthew G. Knepley *result = (void*)inew; 4433221ece2SMatthew G. Knepley PetscFunctionReturn(0); 4443221ece2SMatthew G. Knepley } 4453221ece2SMatthew G. Knepley 4463221ece2SMatthew G. Knepley 447fe7fb379SMatthew Knepley /*@C 4480841954dSBarry Smith PetscMemoryView - Shows the amount of memory currently being used 449e5c89e4eSSatish Balay in a communicator. 450e5c89e4eSSatish Balay 451e5c89e4eSSatish Balay Collective on PetscViewer 452e5c89e4eSSatish Balay 453e5c89e4eSSatish Balay Input Parameter: 454e5c89e4eSSatish Balay + viewer - the viewer that defines the communicator 455e5c89e4eSSatish Balay - message - string printed before values 456e5c89e4eSSatish Balay 4570841954dSBarry Smith Options Database: 4580841954dSBarry Smith + -malloc - have PETSc track how much memory it has allocated 4590841954dSBarry Smith - -memory_view - during PetscFinalize() have this routine called 4600841954dSBarry Smith 461e5c89e4eSSatish Balay Level: intermediate 462e5c89e4eSSatish Balay 463e5c89e4eSSatish Balay Concepts: memory usage 464e5c89e4eSSatish Balay 4650841954dSBarry Smith .seealso: PetscMallocDump(), PetscMemoryGetCurrentUsage(), PetscMemorySetGetMaximumUsage() 466e5c89e4eSSatish Balay @*/ 4670841954dSBarry Smith PetscErrorCode PetscMemoryView(PetscViewer viewer,const char message[]) 468e5c89e4eSSatish Balay { 4690841954dSBarry Smith PetscLogDouble allocated,allocatedmax,resident,residentmax,gallocated,gallocatedmax,gresident,gresidentmax,maxgallocated,maxgallocatedmax,maxgresident,maxgresidentmax; 4700841954dSBarry Smith PetscLogDouble mingallocated,mingallocatedmax,mingresident,mingresidentmax; 471e5c89e4eSSatish Balay PetscErrorCode ierr; 472e5c89e4eSSatish Balay MPI_Comm comm; 473e5c89e4eSSatish Balay 474e5c89e4eSSatish Balay PetscFunctionBegin; 475e5c89e4eSSatish Balay if (!viewer) viewer = PETSC_VIEWER_STDOUT_WORLD; 476e5c89e4eSSatish Balay ierr = PetscMallocGetCurrentUsage(&allocated);CHKERRQ(ierr); 4770841954dSBarry Smith ierr = PetscMallocGetMaximumUsage(&allocatedmax);CHKERRQ(ierr); 478e5c89e4eSSatish Balay ierr = PetscMemoryGetCurrentUsage(&resident);CHKERRQ(ierr); 479e5c89e4eSSatish Balay ierr = PetscMemoryGetMaximumUsage(&residentmax);CHKERRQ(ierr); 480e5c89e4eSSatish Balay if (residentmax > 0) residentmax = PetscMax(resident,residentmax); 481e5c89e4eSSatish Balay ierr = PetscObjectGetComm((PetscObject)viewer,&comm);CHKERRQ(ierr); 482e5c89e4eSSatish Balay ierr = PetscViewerASCIIPrintf(viewer,message);CHKERRQ(ierr); 483e5c89e4eSSatish Balay if (resident && residentmax && allocated) { 4840841954dSBarry Smith ierr = MPI_Reduce(&residentmax,&gresidentmax,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);CHKERRQ(ierr); 4850841954dSBarry Smith ierr = MPI_Reduce(&residentmax,&maxgresidentmax,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);CHKERRQ(ierr); 4860841954dSBarry Smith ierr = MPI_Reduce(&residentmax,&mingresidentmax,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);CHKERRQ(ierr); 4870841954dSBarry 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); 4880841954dSBarry Smith ierr = MPI_Reduce(&resident,&gresident,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);CHKERRQ(ierr); 4890841954dSBarry Smith ierr = MPI_Reduce(&resident,&maxgresident,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);CHKERRQ(ierr); 4900841954dSBarry Smith ierr = MPI_Reduce(&resident,&mingresident,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);CHKERRQ(ierr); 4910841954dSBarry Smith ierr = PetscViewerASCIIPrintf(viewer,"Current process memory: total %5.4e max %5.4e min %5.4e\n",gresident,maxgresident,mingresident);CHKERRQ(ierr); 4920841954dSBarry Smith ierr = MPI_Reduce(&allocatedmax,&gallocatedmax,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);CHKERRQ(ierr); 4930841954dSBarry Smith ierr = MPI_Reduce(&allocatedmax,&maxgallocatedmax,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);CHKERRQ(ierr); 4940841954dSBarry Smith ierr = MPI_Reduce(&allocatedmax,&mingallocatedmax,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);CHKERRQ(ierr); 4950841954dSBarry 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); 4960841954dSBarry Smith ierr = MPI_Reduce(&allocated,&gallocated,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);CHKERRQ(ierr); 4970841954dSBarry Smith ierr = MPI_Reduce(&allocated,&maxgallocated,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);CHKERRQ(ierr); 4980841954dSBarry Smith ierr = MPI_Reduce(&allocated,&mingallocated,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);CHKERRQ(ierr); 4990841954dSBarry Smith ierr = PetscViewerASCIIPrintf(viewer,"Current space PetscMalloc()ed: total %5.4e max %5.4e min %5.4e\n",gallocated,maxgallocated,mingallocated);CHKERRQ(ierr); 500e5c89e4eSSatish Balay } else if (resident && residentmax) { 5010841954dSBarry Smith ierr = MPI_Reduce(&residentmax,&gresidentmax,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);CHKERRQ(ierr); 5020841954dSBarry Smith ierr = MPI_Reduce(&residentmax,&maxgresidentmax,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);CHKERRQ(ierr); 5030841954dSBarry Smith ierr = MPI_Reduce(&residentmax,&mingresidentmax,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);CHKERRQ(ierr); 5040841954dSBarry 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); 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); 509e5c89e4eSSatish Balay } else if (resident && allocated) { 5100841954dSBarry Smith ierr = MPI_Reduce(&resident,&gresident,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);CHKERRQ(ierr); 5110841954dSBarry Smith ierr = MPI_Reduce(&resident,&maxgresident,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);CHKERRQ(ierr); 5120841954dSBarry Smith ierr = MPI_Reduce(&resident,&mingresident,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);CHKERRQ(ierr); 5130841954dSBarry Smith ierr = PetscViewerASCIIPrintf(viewer,"Current process memory: total %5.4e max %5.4e min %5.4e\n",gresident,maxgresident,mingresident);CHKERRQ(ierr); 5140841954dSBarry Smith ierr = MPI_Reduce(&allocated,&gallocated,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);CHKERRQ(ierr); 5150841954dSBarry Smith ierr = MPI_Reduce(&allocated,&maxgallocated,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);CHKERRQ(ierr); 5160841954dSBarry Smith ierr = MPI_Reduce(&allocated,&mingallocated,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);CHKERRQ(ierr); 5170841954dSBarry Smith ierr = PetscViewerASCIIPrintf(viewer,"Current space PetscMalloc()ed: total %5.4e max %5.4e min %5.4e\n",gallocated,maxgallocated,mingallocated);CHKERRQ(ierr); 5180841954dSBarry Smith ierr = PetscViewerASCIIPrintf(viewer,"Run with -memory_view to get maximum memory usage\n");CHKERRQ(ierr); 519e5c89e4eSSatish Balay } else if (allocated) { 5200841954dSBarry Smith ierr = MPI_Reduce(&allocated,&gallocated,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);CHKERRQ(ierr); 5210841954dSBarry Smith ierr = MPI_Reduce(&allocated,&maxgallocated,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);CHKERRQ(ierr); 5220841954dSBarry Smith ierr = MPI_Reduce(&allocated,&mingallocated,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);CHKERRQ(ierr); 5230841954dSBarry Smith ierr = PetscViewerASCIIPrintf(viewer,"Current space PetscMalloc()ed: total %5.4e max %5.4e min %5.4e\n",gallocated,maxgallocated,mingallocated);CHKERRQ(ierr); 5240841954dSBarry Smith ierr = PetscViewerASCIIPrintf(viewer,"Run with -memory_view to get maximum memory usage\n");CHKERRQ(ierr); 5250841954dSBarry Smith ierr = PetscViewerASCIIPrintf(viewer,"OS cannot compute process memory\n");CHKERRQ(ierr); 526e5c89e4eSSatish Balay } else { 527e5c89e4eSSatish Balay ierr = PetscViewerASCIIPrintf(viewer,"Run with -malloc to get statistics on PetscMalloc() calls\nOS cannot compute process memory\n");CHKERRQ(ierr); 528e5c89e4eSSatish Balay } 529e5c89e4eSSatish Balay ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 530e5c89e4eSSatish Balay PetscFunctionReturn(0); 531e5c89e4eSSatish Balay } 532e5c89e4eSSatish Balay 53346eb3923SBarry Smith /*@ 534e5c89e4eSSatish Balay PetscMallocGetCurrentUsage - gets the current amount of memory used that was PetscMalloc()ed 535e5c89e4eSSatish Balay 536e5c89e4eSSatish Balay Not Collective 537e5c89e4eSSatish Balay 538e5c89e4eSSatish Balay Output Parameters: 539e5c89e4eSSatish Balay . space - number of bytes currently allocated 540e5c89e4eSSatish Balay 541e5c89e4eSSatish Balay Level: intermediate 542e5c89e4eSSatish Balay 543e5c89e4eSSatish Balay Concepts: memory usage 544e5c89e4eSSatish Balay 545e5c89e4eSSatish Balay .seealso: PetscMallocDump(), PetscMallocDumpLog(), PetscMallocGetMaximumUsage(), PetscMemoryGetCurrentUsage(), 546e5c89e4eSSatish Balay PetscMemoryGetMaximumUsage() 547e5c89e4eSSatish Balay @*/ 5487087cfbeSBarry Smith PetscErrorCode PetscMallocGetCurrentUsage(PetscLogDouble *space) 549e5c89e4eSSatish Balay { 550e5c89e4eSSatish Balay PetscFunctionBegin; 551e5c89e4eSSatish Balay *space = (PetscLogDouble) TRallocated; 552e5c89e4eSSatish Balay PetscFunctionReturn(0); 553e5c89e4eSSatish Balay } 554e5c89e4eSSatish Balay 555dc37d89fSBarry Smith /*@ 556e5c89e4eSSatish Balay PetscMallocGetMaximumUsage - gets the maximum amount of memory used that was PetscMalloc()ed at any time 557e5c89e4eSSatish Balay during this run. 558e5c89e4eSSatish Balay 559e5c89e4eSSatish Balay Not Collective 560e5c89e4eSSatish Balay 561e5c89e4eSSatish Balay Output Parameters: 562e5c89e4eSSatish Balay . space - maximum number of bytes ever allocated at one time 563e5c89e4eSSatish Balay 564e5c89e4eSSatish Balay Level: intermediate 565e5c89e4eSSatish Balay 566e5c89e4eSSatish Balay Concepts: memory usage 567e5c89e4eSSatish Balay 568e5c89e4eSSatish Balay .seealso: PetscMallocDump(), PetscMallocDumpLog(), PetscMallocGetMaximumUsage(), PetscMemoryGetCurrentUsage(), 569e5c89e4eSSatish Balay PetscMemoryGetCurrentUsage() 570e5c89e4eSSatish Balay @*/ 5717087cfbeSBarry Smith PetscErrorCode PetscMallocGetMaximumUsage(PetscLogDouble *space) 572e5c89e4eSSatish Balay { 573e5c89e4eSSatish Balay PetscFunctionBegin; 574e5c89e4eSSatish Balay *space = (PetscLogDouble) TRMaxMem; 575e5c89e4eSSatish Balay PetscFunctionReturn(0); 576e5c89e4eSSatish Balay } 577e5c89e4eSSatish Balay 578a64a8e02SBarry Smith #if defined(PETSC_USE_DEBUG) 579a64a8e02SBarry Smith /*@C 580a64a8e02SBarry Smith PetscMallocGetStack - returns a pointer to the stack for the location in the program a call to PetscMalloc() was used to obtain that memory 581a64a8e02SBarry Smith 582a64a8e02SBarry Smith Collective on PETSC_COMM_WORLD 583a64a8e02SBarry Smith 584a64a8e02SBarry Smith Input Parameter: 585a64a8e02SBarry Smith . ptr - the memory location 586a64a8e02SBarry Smith 587a64a8e02SBarry Smith Output Paramter: 588a64a8e02SBarry Smith . stack - the stack indicating where the program allocated this memory 589a64a8e02SBarry Smith 590a64a8e02SBarry Smith Level: intermediate 591a64a8e02SBarry Smith 592a64a8e02SBarry Smith .seealso: PetscMallocGetCurrentUsage(), PetscMallocDumpLog() 593a64a8e02SBarry Smith @*/ 594a64a8e02SBarry Smith PetscErrorCode PetscMallocGetStack(void *ptr,PetscStack **stack) 595a64a8e02SBarry Smith { 596a64a8e02SBarry Smith TRSPACE *head; 597a64a8e02SBarry Smith 598a64a8e02SBarry Smith PetscFunctionBegin; 599a64a8e02SBarry Smith head = (TRSPACE*) (((char*)ptr) - HEADER_BYTES); 600a64a8e02SBarry Smith *stack = &head->stack; 601a64a8e02SBarry Smith PetscFunctionReturn(0); 602a64a8e02SBarry Smith } 60376386721SLisandro Dalcin #else 60476386721SLisandro Dalcin PetscErrorCode PetscMallocGetStack(void *ptr,void **stack) 60576386721SLisandro Dalcin { 60676386721SLisandro Dalcin PetscFunctionBegin; 607f0ba7cfcSLisandro Dalcin *stack = NULL; 60876386721SLisandro Dalcin PetscFunctionReturn(0); 60976386721SLisandro Dalcin } 610a64a8e02SBarry Smith #endif 611a64a8e02SBarry Smith 612e5c89e4eSSatish Balay /*@C 613e5c89e4eSSatish Balay PetscMallocDump - Dumps the allocated memory blocks to a file. The information 614e5c89e4eSSatish Balay printed is: size of space (in bytes), address of space, id of space, 615e5c89e4eSSatish Balay file in which space was allocated, and line number at which it was 616e5c89e4eSSatish Balay allocated. 617e5c89e4eSSatish Balay 618e5c89e4eSSatish Balay Collective on PETSC_COMM_WORLD 619e5c89e4eSSatish Balay 620e5c89e4eSSatish Balay Input Parameter: 621e5c89e4eSSatish Balay . fp - file pointer. If fp is NULL, stdout is assumed. 622e5c89e4eSSatish Balay 623e5c89e4eSSatish Balay Options Database Key: 624e5c89e4eSSatish Balay . -malloc_dump - Dumps unfreed memory during call to PetscFinalize() 625e5c89e4eSSatish Balay 626e5c89e4eSSatish Balay Level: intermediate 627e5c89e4eSSatish Balay 628e5c89e4eSSatish Balay Fortran Note: 629e5c89e4eSSatish Balay The calling sequence in Fortran is PetscMallocDump(integer ierr) 630e5c89e4eSSatish Balay The fp defaults to stdout. 631e5c89e4eSSatish Balay 63295452b02SPatrick Sanan Notes: 63395452b02SPatrick Sanan uses MPI_COMM_WORLD, because this may be called in PetscFinalize() after PETSC_COMM_WORLD 634e5c89e4eSSatish Balay has been freed. 635e5c89e4eSSatish Balay 636e5c89e4eSSatish Balay Concepts: memory usage 637e5c89e4eSSatish Balay Concepts: memory bleeding 638e5c89e4eSSatish Balay Concepts: bleeding memory 639e5c89e4eSSatish Balay 6409e9a1f8fSvictor .seealso: PetscMallocGetCurrentUsage(), PetscMallocDumpLog() 641e5c89e4eSSatish Balay @*/ 6427087cfbeSBarry Smith PetscErrorCode PetscMallocDump(FILE *fp) 643e5c89e4eSSatish Balay { 644e5c89e4eSSatish Balay TRSPACE *head; 6455486ca60SMatthew G. Knepley PetscInt libAlloc = 0; 646e5c89e4eSSatish Balay PetscErrorCode ierr; 647e5c89e4eSSatish Balay PetscMPIInt rank; 648e5c89e4eSSatish Balay 649e5c89e4eSSatish Balay PetscFunctionBegin; 650e5c89e4eSSatish Balay ierr = MPI_Comm_rank(MPI_COMM_WORLD,&rank);CHKERRQ(ierr); 651da9f1d6bSBarry Smith if (!fp) fp = PETSC_STDOUT; 652e5c89e4eSSatish Balay head = TRhead; 653e5c89e4eSSatish Balay while (head) { 6545486ca60SMatthew G. Knepley PetscBool isLib; 6555486ca60SMatthew G. Knepley 6565486ca60SMatthew G. Knepley ierr = PetscStrcmp(head->functionname, "PetscDLLibraryOpen", &isLib);CHKERRQ(ierr); 6575486ca60SMatthew G. Knepley libAlloc += head->size; 6585486ca60SMatthew G. Knepley head = head->next; 6595486ca60SMatthew G. Knepley } 6605486ca60SMatthew G. Knepley if (TRallocated - libAlloc > 0) fprintf(fp,"[%d]Total space allocated %.0f bytes\n",rank,(PetscLogDouble)TRallocated); 6615486ca60SMatthew G. Knepley head = TRhead; 6625486ca60SMatthew G. Knepley while (head) { 6635486ca60SMatthew G. Knepley PetscBool isLib; 6645486ca60SMatthew G. Knepley 6655486ca60SMatthew G. Knepley ierr = PetscStrcmp(head->functionname, "PetscDLLibraryOpen", &isLib);CHKERRQ(ierr); 6665486ca60SMatthew G. Knepley if (!isLib) { 667efca3c55SSatish Balay fprintf(fp,"[%2d]%.0f bytes %s() line %d in %s\n",rank,(PetscLogDouble)head->size,head->functionname,head->lineno,head->filename); 6688bf1f09cSShri Abhyankar #if defined(PETSC_USE_DEBUG) 669e5c89e4eSSatish Balay ierr = PetscStackPrint(&head->stack,fp);CHKERRQ(ierr); 670e5c89e4eSSatish Balay #endif 6715486ca60SMatthew G. Knepley } 672e5c89e4eSSatish Balay head = head->next; 673e5c89e4eSSatish Balay } 674e5c89e4eSSatish Balay PetscFunctionReturn(0); 675e5c89e4eSSatish Balay } 676e5c89e4eSSatish Balay 677e5c89e4eSSatish Balay /* ---------------------------------------------------------------------------- */ 678e5c89e4eSSatish Balay 679dc37d89fSBarry Smith /*@ 680e5c89e4eSSatish Balay PetscMallocSetDumpLog - Activates logging of all calls to PetscMalloc(). 681e5c89e4eSSatish Balay 682e5c89e4eSSatish Balay Not Collective 683e5c89e4eSSatish Balay 684e5c89e4eSSatish Balay Options Database Key: 685574034a9SJed Brown + -malloc_log <filename> - Activates PetscMallocDumpLog() 686574034a9SJed Brown - -malloc_log_threshold <min> - Activates logging and sets a minimum size 687e5c89e4eSSatish Balay 688e5c89e4eSSatish Balay Level: advanced 689e5c89e4eSSatish Balay 690574034a9SJed Brown .seealso: PetscMallocDump(), PetscMallocDumpLog(), PetscMallocSetDumpLogThreshold() 691e5c89e4eSSatish Balay @*/ 6927087cfbeSBarry Smith PetscErrorCode PetscMallocSetDumpLog(void) 693e5c89e4eSSatish Balay { 69421b680ceSJed Brown PetscErrorCode ierr; 69521b680ceSJed Brown 696e5c89e4eSSatish Balay PetscFunctionBegin; 697e5c89e4eSSatish Balay PetscLogMalloc = 0; 698a297a907SKarl Rupp 69921b680ceSJed Brown ierr = PetscMemorySetGetMaximumUsage();CHKERRQ(ierr); 700e5c89e4eSSatish Balay PetscFunctionReturn(0); 701e5c89e4eSSatish Balay } 702e5c89e4eSSatish Balay 703dc37d89fSBarry Smith /*@ 704574034a9SJed Brown PetscMallocSetDumpLogThreshold - Activates logging of all calls to PetscMalloc(). 705574034a9SJed Brown 706574034a9SJed Brown Not Collective 707574034a9SJed Brown 708574034a9SJed Brown Input Arguments: 709574034a9SJed Brown . logmin - minimum allocation size to log, or PETSC_DEFAULT 710574034a9SJed Brown 711574034a9SJed Brown Options Database Key: 712574034a9SJed Brown + -malloc_log <filename> - Activates PetscMallocDumpLog() 713574034a9SJed Brown - -malloc_log_threshold <min> - Activates logging and sets a minimum size 714574034a9SJed Brown 715574034a9SJed Brown Level: advanced 716574034a9SJed Brown 717574034a9SJed Brown .seealso: PetscMallocDump(), PetscMallocDumpLog(), PetscMallocSetDumpLog() 718574034a9SJed Brown @*/ 719574034a9SJed Brown PetscErrorCode PetscMallocSetDumpLogThreshold(PetscLogDouble logmin) 720574034a9SJed Brown { 721574034a9SJed Brown PetscErrorCode ierr; 722574034a9SJed Brown 723574034a9SJed Brown PetscFunctionBegin; 724574034a9SJed Brown ierr = PetscMallocSetDumpLog();CHKERRQ(ierr); 725574034a9SJed Brown if (logmin < 0) logmin = 0.0; /* PETSC_DEFAULT or PETSC_DECIDE */ 726574034a9SJed Brown PetscLogMallocThreshold = (size_t)logmin; 727574034a9SJed Brown PetscFunctionReturn(0); 728574034a9SJed Brown } 729574034a9SJed Brown 730dc37d89fSBarry Smith /*@ 73118a2528dSJed Brown PetscMallocGetDumpLog - Determine whether all calls to PetscMalloc() are being logged 73218a2528dSJed Brown 73318a2528dSJed Brown Not Collective 73418a2528dSJed Brown 73518a2528dSJed Brown Output Arguments 73618a2528dSJed Brown . logging - PETSC_TRUE if logging is active 73718a2528dSJed Brown 73818a2528dSJed Brown Options Database Key: 73918a2528dSJed Brown . -malloc_log - Activates PetscMallocDumpLog() 74018a2528dSJed Brown 74118a2528dSJed Brown Level: advanced 74218a2528dSJed Brown 74318a2528dSJed Brown .seealso: PetscMallocDump(), PetscMallocDumpLog() 74418a2528dSJed Brown @*/ 74518a2528dSJed Brown PetscErrorCode PetscMallocGetDumpLog(PetscBool *logging) 74618a2528dSJed Brown { 74718a2528dSJed Brown 74818a2528dSJed Brown PetscFunctionBegin; 74918a2528dSJed Brown *logging = (PetscBool)(PetscLogMalloc >= 0); 75018a2528dSJed Brown PetscFunctionReturn(0); 75118a2528dSJed Brown } 75218a2528dSJed Brown 753e5c89e4eSSatish Balay /*@C 754e5c89e4eSSatish Balay PetscMallocDumpLog - Dumps the log of all calls to PetscMalloc(); also calls 75521b680ceSJed Brown PetscMemoryGetMaximumUsage() 756e5c89e4eSSatish Balay 757e5c89e4eSSatish Balay Collective on PETSC_COMM_WORLD 758e5c89e4eSSatish Balay 759e5c89e4eSSatish Balay Input Parameter: 7600298fd71SBarry Smith . fp - file pointer; or NULL 761e5c89e4eSSatish Balay 762e5c89e4eSSatish Balay Options Database Key: 763e5c89e4eSSatish Balay . -malloc_log - Activates PetscMallocDumpLog() 764e5c89e4eSSatish Balay 765e5c89e4eSSatish Balay Level: advanced 766e5c89e4eSSatish Balay 767e5c89e4eSSatish Balay Fortran Note: 768e5c89e4eSSatish Balay The calling sequence in Fortran is PetscMallocDumpLog(integer ierr) 769e5c89e4eSSatish Balay The fp defaults to stdout. 770e5c89e4eSSatish Balay 771e5c89e4eSSatish Balay .seealso: PetscMallocGetCurrentUsage(), PetscMallocDump(), PetscMallocSetDumpLog() 772e5c89e4eSSatish Balay @*/ 7737087cfbeSBarry Smith PetscErrorCode PetscMallocDumpLog(FILE *fp) 774e5c89e4eSSatish Balay { 775e5c89e4eSSatish Balay PetscInt i,j,n,dummy,*perm; 776e5c89e4eSSatish Balay size_t *shortlength; 777f56c2debSBarry Smith int *shortcount,err; 778e5c89e4eSSatish Balay PetscMPIInt rank,size,tag = 1212 /* very bad programming */; 779ace3abfcSBarry Smith PetscBool match; 780e5c89e4eSSatish Balay const char **shortfunction; 781e5c89e4eSSatish Balay PetscLogDouble rss; 782e5c89e4eSSatish Balay MPI_Status status; 783e5c89e4eSSatish Balay PetscErrorCode ierr; 784e5c89e4eSSatish Balay 785e5c89e4eSSatish Balay PetscFunctionBegin; 786e5c89e4eSSatish Balay ierr = MPI_Comm_rank(MPI_COMM_WORLD,&rank);CHKERRQ(ierr); 787e5c89e4eSSatish Balay ierr = MPI_Comm_size(MPI_COMM_WORLD,&size);CHKERRQ(ierr); 788e5c89e4eSSatish Balay /* 789e5c89e4eSSatish Balay Try to get the data printed in order by processor. This will only sometimes work 790e5c89e4eSSatish Balay */ 791f56c2debSBarry Smith err = fflush(fp); 792e32f2f54SBarry Smith if (err) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"fflush() failed on file"); 793f56c2debSBarry Smith 794e5c89e4eSSatish Balay ierr = MPI_Barrier(MPI_COMM_WORLD);CHKERRQ(ierr); 795e5c89e4eSSatish Balay if (rank) { 796e5c89e4eSSatish Balay ierr = MPI_Recv(&dummy,1,MPIU_INT,rank-1,tag,MPI_COMM_WORLD,&status);CHKERRQ(ierr); 797e5c89e4eSSatish Balay } 798e5c89e4eSSatish Balay 799768aa557SSatish 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()"); 800768aa557SSatish Balay 801da9f1d6bSBarry Smith if (!fp) fp = PETSC_STDOUT; 802f3d65365SJed Brown ierr = PetscMemoryGetMaximumUsage(&rss);CHKERRQ(ierr); 803e5c89e4eSSatish Balay if (rss) { 804f3d65365SJed 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); 805e5c89e4eSSatish Balay } else { 806e5c89e4eSSatish 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); 807e5c89e4eSSatish Balay } 808e32f2f54SBarry Smith shortcount = (int*)malloc(PetscLogMalloc*sizeof(int));if (!shortcount) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM,"Out of memory"); 809e32f2f54SBarry Smith shortlength = (size_t*)malloc(PetscLogMalloc*sizeof(size_t));if (!shortlength) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM,"Out of memory"); 810e32f2f54SBarry Smith shortfunction = (const char**)malloc(PetscLogMalloc*sizeof(char*));if (!shortfunction) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM,"Out of memory"); 81197b9d747SJed Brown for (i=0,n=0; i<PetscLogMalloc; i++) { 812e5c89e4eSSatish Balay for (j=0; j<n; j++) { 813e5c89e4eSSatish Balay ierr = PetscStrcmp(shortfunction[j],PetscLogMallocFunction[i],&match);CHKERRQ(ierr); 814e5c89e4eSSatish Balay if (match) { 815e5c89e4eSSatish Balay shortlength[j] += PetscLogMallocLength[i]; 81659ffdab8SBarry Smith shortcount[j]++; 817e5c89e4eSSatish Balay goto foundit; 818e5c89e4eSSatish Balay } 819e5c89e4eSSatish Balay } 820e5c89e4eSSatish Balay shortfunction[n] = PetscLogMallocFunction[i]; 821e5c89e4eSSatish Balay shortlength[n] = PetscLogMallocLength[i]; 82259ffdab8SBarry Smith shortcount[n] = 1; 823e5c89e4eSSatish Balay n++; 824e5c89e4eSSatish Balay foundit:; 825e5c89e4eSSatish Balay } 826e5c89e4eSSatish Balay 827e32f2f54SBarry Smith perm = (PetscInt*)malloc(n*sizeof(PetscInt));if (!perm) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM,"Out of memory"); 828e5c89e4eSSatish Balay for (i=0; i<n; i++) perm[i] = i; 829e5c89e4eSSatish Balay ierr = PetscSortStrWithPermutation(n,(const char**)shortfunction,perm);CHKERRQ(ierr); 830e5c89e4eSSatish Balay 831e5c89e4eSSatish Balay ierr = PetscFPrintf(MPI_COMM_WORLD,fp,"[%d] Memory usage sorted by function\n",rank);CHKERRQ(ierr); 832e5c89e4eSSatish Balay for (i=0; i<n; i++) { 83359ffdab8SBarry 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); 834e5c89e4eSSatish Balay } 835e5c89e4eSSatish Balay free(perm); 836e5c89e4eSSatish Balay free(shortlength); 83759ffdab8SBarry Smith free(shortcount); 838e5c89e4eSSatish Balay free((char**)shortfunction); 839f56c2debSBarry Smith err = fflush(fp); 840e32f2f54SBarry Smith if (err) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"fflush() failed on file"); 841e5c89e4eSSatish Balay if (rank != size-1) { 842e5c89e4eSSatish Balay ierr = MPI_Send(&dummy,1,MPIU_INT,rank+1,tag,MPI_COMM_WORLD);CHKERRQ(ierr); 843e5c89e4eSSatish Balay } 844e5c89e4eSSatish Balay PetscFunctionReturn(0); 845e5c89e4eSSatish Balay } 846e5c89e4eSSatish Balay 847e5c89e4eSSatish Balay /* ---------------------------------------------------------------------------- */ 848e5c89e4eSSatish Balay 849dc37d89fSBarry Smith /*@ 850e5c89e4eSSatish Balay PetscMallocDebug - Turns on/off debugging for the memory management routines. 851e5c89e4eSSatish Balay 852e5c89e4eSSatish Balay Not Collective 853e5c89e4eSSatish Balay 854e5c89e4eSSatish Balay Input Parameter: 855e5c89e4eSSatish Balay . level - PETSC_TRUE or PETSC_FALSE 856e5c89e4eSSatish Balay 857e5c89e4eSSatish Balay Level: intermediate 858e5c89e4eSSatish Balay 859e5c89e4eSSatish Balay .seealso: CHKMEMQ(), PetscMallocValidate() 860e5c89e4eSSatish Balay @*/ 8617087cfbeSBarry Smith PetscErrorCode PetscMallocDebug(PetscBool level) 862e5c89e4eSSatish Balay { 863e5c89e4eSSatish Balay PetscFunctionBegin; 864e5c89e4eSSatish Balay TRdebugLevel = level; 865e5c89e4eSSatish Balay PetscFunctionReturn(0); 866e5c89e4eSSatish Balay } 8670acecf5bSBarry Smith 868dc37d89fSBarry Smith /*@ 8690acecf5bSBarry Smith PetscMallocGetDebug - Indicates if any PETSc is doing ANY memory debugging. 8700acecf5bSBarry Smith 8710acecf5bSBarry Smith Not Collective 8720acecf5bSBarry Smith 8730acecf5bSBarry Smith Output Parameter: 8740acecf5bSBarry Smith . flg - PETSC_TRUE if any debugger 8750acecf5bSBarry Smith 8760acecf5bSBarry Smith Level: intermediate 8770acecf5bSBarry Smith 8780acecf5bSBarry Smith Note that by default, the debug version always does some debugging unless you run with -malloc no 8790acecf5bSBarry Smith 8800acecf5bSBarry Smith 8810acecf5bSBarry Smith .seealso: CHKMEMQ(), PetscMallocValidate() 8820acecf5bSBarry Smith @*/ 8830acecf5bSBarry Smith PetscErrorCode PetscMallocGetDebug(PetscBool *flg) 8840acecf5bSBarry Smith { 8850acecf5bSBarry Smith PetscFunctionBegin; 8860acecf5bSBarry Smith if (PetscTrMalloc == PetscTrMallocDefault) *flg = PETSC_TRUE; 8870acecf5bSBarry Smith else *flg = PETSC_FALSE; 8880acecf5bSBarry Smith PetscFunctionReturn(0); 8890acecf5bSBarry Smith } 890