17d0a6c19SBarry Smith 2e5c89e4eSSatish Balay /* 392f119d6SBarry Smith Interface to malloc() and free(). This code allows for logging of memory usage and some error checking 4e5c89e4eSSatish Balay */ 527104ee2SJacob Faibussowitsch #include <petsc/private/petscimpl.h> /*I "petscsys.h" I*/ 6665c2dedSJed Brown #include <petscviewer.h> 7e5c89e4eSSatish Balay #if defined(PETSC_HAVE_MALLOC_H) 8e5c89e4eSSatish Balay #include <malloc.h> 9e5c89e4eSSatish Balay #endif 10e5c89e4eSSatish Balay 11e5c89e4eSSatish Balay /* 12e5c89e4eSSatish Balay These are defined in mal.c and ensure that malloced space is PetscScalar aligned 13e5c89e4eSSatish Balay */ 14071fcb05SBarry Smith PETSC_EXTERN PetscErrorCode PetscMallocAlign(size_t, PetscBool, int, const char[], const char[], void **); 1595c0884eSLisandro Dalcin PETSC_EXTERN PetscErrorCode PetscFreeAlign(void *, int, const char[], const char[]); 1695c0884eSLisandro Dalcin PETSC_EXTERN PetscErrorCode PetscReallocAlign(size_t, int, const char[], const char[], void **); 17e5c89e4eSSatish Balay 180700a824SBarry Smith #define CLASSID_VALUE ((PetscClassId)0xf0e0d0c9) 190700a824SBarry Smith #define ALREADY_FREED ((PetscClassId)0x0f0e0d9c) 20e5c89e4eSSatish Balay 2192f119d6SBarry Smith /* this is the header put at the beginning of each malloc() using for tracking allocated space and checking of allocated space heap */ 22e5c89e4eSSatish Balay typedef struct _trSPACE { 23608c71bfSMatthew G. Knepley size_t size, rsize; /* Aligned size and requested size */ 24e5c89e4eSSatish Balay int id; 25e5c89e4eSSatish Balay int lineno; 26e5c89e4eSSatish Balay const char *filename; 27e5c89e4eSSatish Balay const char *functionname; 280700a824SBarry Smith PetscClassId classid; 298bf1f09cSShri Abhyankar #if defined(PETSC_USE_DEBUG) 30e5c89e4eSSatish Balay PetscStack stack; 31e5c89e4eSSatish Balay #endif 32e5c89e4eSSatish Balay struct _trSPACE *next, *prev; 33e5c89e4eSSatish Balay } TRSPACE; 34e5c89e4eSSatish Balay 3525b53cc9SJed Brown /* HEADER_BYTES is the number of bytes in a PetscMalloc() header. 3692f119d6SBarry Smith It is sizeof(trSPACE) padded to be a multiple of PETSC_MEMALIGN. 3725b53cc9SJed Brown */ 38a64a8e02SBarry Smith #define HEADER_BYTES ((sizeof(TRSPACE) + (PETSC_MEMALIGN - 1)) & ~(PETSC_MEMALIGN - 1)) 39e5c89e4eSSatish Balay 4025b53cc9SJed Brown /* This union is used to insure that the block passed to the user retains 4125b53cc9SJed Brown a minimum alignment of PETSC_MEMALIGN. 4225b53cc9SJed Brown */ 439371c9d4SSatish Balay typedef union 449371c9d4SSatish Balay { 45e5c89e4eSSatish Balay TRSPACE sp; 4625b53cc9SJed Brown char v[HEADER_BYTES]; 47e5c89e4eSSatish Balay } TrSPACE; 48e5c89e4eSSatish Balay 49e3ed9ee7SBarry Smith #define MAXTRMAXMEMS 50 50e5c89e4eSSatish Balay static size_t TRallocated = 0; 51e5c89e4eSSatish Balay static int TRfrags = 0; 52f0ba7cfcSLisandro Dalcin static TRSPACE *TRhead = NULL; 53e5c89e4eSSatish Balay static int TRid = 0; 54ace3abfcSBarry Smith static PetscBool TRdebugLevel = PETSC_FALSE; 552d4ee042Sprj- static PetscBool TRdebugIinitializenan = PETSC_FALSE; 56608c71bfSMatthew G. Knepley static PetscBool TRrequestedSize = PETSC_FALSE; 57e5c89e4eSSatish Balay static size_t TRMaxMem = 0; 58e3ed9ee7SBarry Smith static int NumTRMaxMems = 0; 59e3ed9ee7SBarry Smith static size_t TRMaxMems[MAXTRMAXMEMS]; 60e3ed9ee7SBarry Smith static int TRMaxMemsEvents[MAXTRMAXMEMS]; 61e5c89e4eSSatish Balay /* 6292f119d6SBarry Smith Arrays to log information on mallocs for PetscMallocView() 63e5c89e4eSSatish Balay */ 64f0ba7cfcSLisandro Dalcin static int PetscLogMallocMax = 10000; 65f0ba7cfcSLisandro Dalcin static int PetscLogMalloc = -1; 66574034a9SJed Brown static size_t PetscLogMallocThreshold = 0; 67e5c89e4eSSatish Balay static size_t *PetscLogMallocLength; 68efca3c55SSatish Balay static const char **PetscLogMallocFile, **PetscLogMallocFunction; 69608c71bfSMatthew G. Knepley static int PetscLogMallocTrace = -1; 70608c71bfSMatthew G. Knepley static size_t PetscLogMallocTraceThreshold = 0; 71608c71bfSMatthew G. Knepley static PetscViewer PetscLogMallocTraceViewer = NULL; 72b022a5c1SBarry Smith 73e5c89e4eSSatish Balay /*@C 7492f119d6SBarry Smith PetscMallocValidate - Test the memory for corruption. This can be called at any time between PetscInitialize() and PetscFinalize() 75e5c89e4eSSatish Balay 7692f119d6SBarry Smith Input Parameters: 77e5c89e4eSSatish Balay + line - line number where call originated. 78e5c89e4eSSatish Balay . function - name of function calling 79efca3c55SSatish Balay - file - file where function is 80e5c89e4eSSatish Balay 81e5c89e4eSSatish Balay Return value: 82e5c89e4eSSatish Balay The number of errors detected. 83e5c89e4eSSatish Balay 8492f119d6SBarry Smith Options Database:. 8592f119d6SBarry Smith + -malloc_test - turns this feature on when PETSc was not configured with --with-debugging=0 8692f119d6SBarry Smith - -malloc_debug - turns this feature on anytime 8792f119d6SBarry Smith 88e5c89e4eSSatish Balay Output Effect: 89e5c89e4eSSatish Balay Error messages are written to stdout. 90e5c89e4eSSatish Balay 91e5c89e4eSSatish Balay Level: advanced 92e5c89e4eSSatish Balay 93e5c89e4eSSatish Balay Notes: 9479dccf82SBarry Smith This is only run if PetscMallocSetDebug() has been called which is set by -malloc_test (if debugging is turned on) or -malloc_debug (any time) 9538548759SBarry Smith 9692f119d6SBarry Smith You should generally use CHKMEMQ as a short cut for calling this routine. 97e5c89e4eSSatish Balay 98e5c89e4eSSatish Balay The Fortran calling sequence is simply PetscMallocValidate(ierr) 99e5c89e4eSSatish Balay 100e5c89e4eSSatish Balay No output is generated if there are no problems detected. 101e5c89e4eSSatish Balay 10292f119d6SBarry Smith Developers Note: 10392f119d6SBarry Smith Uses the flg TRdebugLevel (set as the first argument to PetscMallocSetDebug()) to determine if it should run 10492f119d6SBarry Smith 105db781477SPatrick Sanan .seealso: `CHKMEMQ` 106e5c89e4eSSatish Balay 107e5c89e4eSSatish Balay @*/ 1089371c9d4SSatish Balay PetscErrorCode PetscMallocValidate(int line, const char function[], const char file[]) { 1096c093d5bSvictor TRSPACE *head, *lasthead; 110e5c89e4eSSatish Balay char *a; 1110700a824SBarry Smith PetscClassId *nend; 112e5c89e4eSSatish Balay 11338548759SBarry Smith if (!TRdebugLevel) return 0; 1149371c9d4SSatish Balay head = TRhead; 1159371c9d4SSatish Balay lasthead = NULL; 1162cba8197SMatthew G. Knepley if (head && head->prev) { 117ccd65f63SJunchao Zhang (*PetscErrorPrintf)("PetscMallocValidate: error detected in %s() at %s:%d\n", function, file, line); 1182cba8197SMatthew G. Knepley (*PetscErrorPrintf)("Root memory header %p has invalid back pointer %p\n", head, head->prev); 1194ed0ab5bSBarry Smith return PETSC_ERR_MEMC; 1202cba8197SMatthew G. Knepley } 121e5c89e4eSSatish Balay while (head) { 1220700a824SBarry Smith if (head->classid != CLASSID_VALUE) { 123ccd65f63SJunchao Zhang (*PetscErrorPrintf)("PetscMallocValidate: error detected in %s() at %s:%d\n", function, file, line); 124e5c89e4eSSatish Balay (*PetscErrorPrintf)("Memory at address %p is corrupted\n", head); 1254ed0ab5bSBarry Smith (*PetscErrorPrintf)("Probably write before beginning of or past end of array\n"); 126e269983cSBarry Smith if (lasthead) { 127e269983cSBarry Smith a = (char *)(((TrSPACE *)head) + 1); 128ccd65f63SJunchao Zhang (*PetscErrorPrintf)("Last intact block [id=%d(%.0f)] at address %p allocated in %s() at %s:%d\n", lasthead->id, (PetscLogDouble)lasthead->size, a, lasthead->functionname, lasthead->filename, lasthead->lineno); 129e269983cSBarry Smith } 130e269983cSBarry Smith abort(); 1314ed0ab5bSBarry Smith return PETSC_ERR_MEMC; 132e5c89e4eSSatish Balay } 133e5c89e4eSSatish Balay a = (char *)(((TrSPACE *)head) + 1); 1340700a824SBarry Smith nend = (PetscClassId *)(a + head->size); 1350700a824SBarry Smith if (*nend != CLASSID_VALUE) { 136ccd65f63SJunchao Zhang (*PetscErrorPrintf)("PetscMallocValidate: error detected in %s() at %s:%d\n", function, file, line); 137e5c89e4eSSatish Balay if (*nend == ALREADY_FREED) { 138e5c89e4eSSatish Balay (*PetscErrorPrintf)("Memory [id=%d(%.0f)] at address %p already freed\n", head->id, (PetscLogDouble)head->size, a); 1394ed0ab5bSBarry Smith return PETSC_ERR_MEMC; 140e5c89e4eSSatish Balay } else { 141e5c89e4eSSatish Balay (*PetscErrorPrintf)("Memory [id=%d(%.0f)] at address %p is corrupted (probably write past end of array)\n", head->id, (PetscLogDouble)head->size, a); 142ccd65f63SJunchao Zhang (*PetscErrorPrintf)("Memory originally allocated in %s() at %s:%d\n", head->functionname, head->filename, head->lineno); 1434ed0ab5bSBarry Smith return PETSC_ERR_MEMC; 144e5c89e4eSSatish Balay } 145e5c89e4eSSatish Balay } 1462cba8197SMatthew G. Knepley if (head->prev && head->prev != lasthead) { 147ccd65f63SJunchao Zhang (*PetscErrorPrintf)("PetscMallocValidate: error detected in %s() at %s:%d\n", function, file, line); 1482cba8197SMatthew G. Knepley (*PetscErrorPrintf)("Backpointer %p is invalid, should be %p\n", head->prev, lasthead); 149ccd65f63SJunchao Zhang (*PetscErrorPrintf)("Previous memory originally allocated in %s() at %s:%d\n", lasthead->functionname, lasthead->filename, lasthead->lineno); 150ccd65f63SJunchao Zhang (*PetscErrorPrintf)("Memory originally allocated in %s() at %s:%d\n", head->functionname, head->filename, head->lineno); 1514ed0ab5bSBarry Smith return PETSC_ERR_MEMC; 1522cba8197SMatthew G. Knepley } 1536c093d5bSvictor lasthead = head; 154e5c89e4eSSatish Balay head = head->next; 155e5c89e4eSSatish Balay } 1564ed0ab5bSBarry Smith return 0; 157e5c89e4eSSatish Balay } 158e5c89e4eSSatish Balay 159e5c89e4eSSatish Balay /* 160e5c89e4eSSatish Balay PetscTrMallocDefault - Malloc with tracing. 161e5c89e4eSSatish Balay 162e5c89e4eSSatish Balay Input Parameters: 163e5c89e4eSSatish Balay + a - number of bytes to allocate 164e5c89e4eSSatish Balay . lineno - line number where used. Use __LINE__ for this 165efca3c55SSatish Balay - filename - file name where used. Use __FILE__ for this 166e5c89e4eSSatish Balay 167e5c89e4eSSatish Balay Returns: 16892f119d6SBarry Smith double aligned pointer to requested storage, or null if not available. 169e5c89e4eSSatish Balay */ 1709371c9d4SSatish Balay PetscErrorCode PetscTrMallocDefault(size_t a, PetscBool clear, int lineno, const char function[], const char filename[], void **result) { 171e5c89e4eSSatish Balay TRSPACE *head; 172e5c89e4eSSatish Balay char *inew; 173e5c89e4eSSatish Balay size_t nsize; 174e5c89e4eSSatish Balay PetscErrorCode ierr; 175e5c89e4eSSatish Balay 176e5c89e4eSSatish Balay PetscFunctionBegin; 177f0ba7cfcSLisandro Dalcin /* Do not try to handle empty blocks */ 1789371c9d4SSatish Balay if (!a) { 1799371c9d4SSatish Balay *result = NULL; 1809371c9d4SSatish Balay PetscFunctionReturn(0); 1819371c9d4SSatish Balay } 182f0ba7cfcSLisandro Dalcin 1839371c9d4SSatish Balay ierr = PetscMallocValidate(lineno, function, filename); 1849371c9d4SSatish Balay if (ierr) PetscFunctionReturn(ierr); 185e5c89e4eSSatish Balay 18625b53cc9SJed Brown nsize = (a + (PETSC_MEMALIGN - 1)) & ~(PETSC_MEMALIGN - 1); 1879566063dSJacob Faibussowitsch PetscCall(PetscMallocAlign(nsize + sizeof(TrSPACE) + sizeof(PetscClassId), clear, lineno, function, filename, (void **)&inew)); 188e3ed9ee7SBarry Smith 189e5c89e4eSSatish Balay head = (TRSPACE *)inew; 190e5c89e4eSSatish Balay inew += sizeof(TrSPACE); 191e5c89e4eSSatish Balay 192e5c89e4eSSatish Balay if (TRhead) TRhead->prev = head; 193e5c89e4eSSatish Balay head->next = TRhead; 194e5c89e4eSSatish Balay TRhead = head; 195f0ba7cfcSLisandro Dalcin head->prev = NULL; 196e5c89e4eSSatish Balay head->size = nsize; 197608c71bfSMatthew G. Knepley head->rsize = a; 198e269983cSBarry Smith head->id = TRid++; 199e5c89e4eSSatish Balay head->lineno = lineno; 200e5c89e4eSSatish Balay 201e5c89e4eSSatish Balay head->filename = filename; 202e5c89e4eSSatish Balay head->functionname = function; 2030700a824SBarry Smith head->classid = CLASSID_VALUE; 2040700a824SBarry Smith *(PetscClassId *)(inew + nsize) = CLASSID_VALUE; 205e5c89e4eSSatish Balay 206608c71bfSMatthew G. Knepley TRallocated += TRrequestedSize ? head->rsize : head->size; 207a297a907SKarl Rupp if (TRallocated > TRMaxMem) TRMaxMem = TRallocated; 208e3ed9ee7SBarry Smith if (PetscLogMemory) { 209e3ed9ee7SBarry Smith PetscInt i; 210e3ed9ee7SBarry Smith for (i = 0; i < NumTRMaxMems; i++) { 211e3ed9ee7SBarry Smith if (TRallocated > TRMaxMems[i]) TRMaxMems[i] = TRallocated; 212e3ed9ee7SBarry Smith } 213e3ed9ee7SBarry Smith } 214e5c89e4eSSatish Balay TRfrags++; 215e5c89e4eSSatish Balay 2168bf1f09cSShri Abhyankar #if defined(PETSC_USE_DEBUG) 2179566063dSJacob Faibussowitsch PetscCall(PetscStackCopy(&petscstack, &head->stack)); 2182c9581d2SBarry Smith /* fix the line number to where the malloc() was called, not the PetscFunctionBegin; */ 2192c9581d2SBarry Smith head->stack.line[head->stack.currentsize - 2] = lineno; 22092f119d6SBarry Smith #if defined(PETSC_USE_REAL_SINGLE) || defined(PETSC_USE_REAL_DOUBLE) 2212d4ee042Sprj- if (!clear && TRdebugIinitializenan) { 22292f119d6SBarry Smith size_t i, n = a / sizeof(PetscReal); 22392f119d6SBarry Smith PetscReal *s = (PetscReal *)inew; 22492f119d6SBarry Smith /* from https://www.doc.ic.ac.uk/~eedwards/compsys/float/nan.html */ 22592f119d6SBarry Smith #if defined(PETSC_USE_REAL_SINGLE) 226df282883SBarry Smith int nas = 0x7F800002; 22792f119d6SBarry Smith #else 22892f119d6SBarry Smith PetscInt64 nas = 0x7FF0000000000002; 22992f119d6SBarry Smith #endif 2309371c9d4SSatish Balay for (i = 0; i < n; i++) { memcpy(s + i, &nas, sizeof(PetscReal)); } 23192f119d6SBarry Smith } 23292f119d6SBarry Smith #endif 233e5c89e4eSSatish Balay #endif 234e5c89e4eSSatish Balay 235e5c89e4eSSatish Balay /* 23692f119d6SBarry Smith Allow logging of all mallocs made. 23792f119d6SBarry Smith TODO: Currently this memory is never freed, it should be freed during PetscFinalize() 238e5c89e4eSSatish Balay */ 239574034a9SJed Brown if (PetscLogMalloc > -1 && PetscLogMalloc < PetscLogMallocMax && a >= PetscLogMallocThreshold) { 240e5c89e4eSSatish Balay if (!PetscLogMalloc) { 241e5c89e4eSSatish Balay PetscLogMallocLength = (size_t *)malloc(PetscLogMallocMax * sizeof(size_t)); 24228b400f6SJacob Faibussowitsch PetscCheck(PetscLogMallocLength, PETSC_COMM_SELF, PETSC_ERR_MEM, " "); 243a297a907SKarl Rupp 244a2ea699eSBarry Smith PetscLogMallocFile = (const char **)malloc(PetscLogMallocMax * sizeof(char *)); 24528b400f6SJacob Faibussowitsch PetscCheck(PetscLogMallocFile, PETSC_COMM_SELF, PETSC_ERR_MEM, " "); 246a297a907SKarl Rupp 247a2ea699eSBarry Smith PetscLogMallocFunction = (const char **)malloc(PetscLogMallocMax * sizeof(char *)); 24828b400f6SJacob Faibussowitsch PetscCheck(PetscLogMallocFunction, PETSC_COMM_SELF, PETSC_ERR_MEM, " "); 249e5c89e4eSSatish Balay } 250e5c89e4eSSatish Balay PetscLogMallocLength[PetscLogMalloc] = nsize; 251e5c89e4eSSatish Balay PetscLogMallocFile[PetscLogMalloc] = filename; 252e5c89e4eSSatish Balay PetscLogMallocFunction[PetscLogMalloc++] = function; 253e5c89e4eSSatish Balay } 254*48a46eb9SPierre Jolivet if (PetscLogMallocTrace > -1 && a >= PetscLogMallocTraceThreshold) PetscCall(PetscViewerASCIIPrintf(PetscLogMallocTraceViewer, "Alloc %zu %s:%d (%s)\n", a, filename ? filename : "null", lineno, function ? function : "null")); 255e5c89e4eSSatish Balay *result = (void *)inew; 256e5c89e4eSSatish Balay PetscFunctionReturn(0); 257e5c89e4eSSatish Balay } 258e5c89e4eSSatish Balay 259e5c89e4eSSatish Balay /* 260e5c89e4eSSatish Balay PetscTrFreeDefault - Free with tracing. 261e5c89e4eSSatish Balay 262e5c89e4eSSatish Balay Input Parameters: 263e5c89e4eSSatish Balay . a - pointer to a block allocated with PetscTrMalloc 264e5c89e4eSSatish Balay . lineno - line number where used. Use __LINE__ for this 265608c71bfSMatthew G. Knepley . filename - file name where used. Use __FILE__ for this 266e5c89e4eSSatish Balay */ 2679371c9d4SSatish Balay PetscErrorCode PetscTrFreeDefault(void *aa, int lineno, const char function[], const char filename[]) { 268e5c89e4eSSatish Balay char *a = (char *)aa; 269e5c89e4eSSatish Balay TRSPACE *head; 270e5c89e4eSSatish Balay char *ahead; 271608c71bfSMatthew G. Knepley size_t asize; 2720700a824SBarry Smith PetscClassId *nend; 273e5c89e4eSSatish Balay 274e5c89e4eSSatish Balay PetscFunctionBegin; 275e5c89e4eSSatish Balay /* Do not try to handle empty blocks */ 27649d7da52SJed Brown if (!a) PetscFunctionReturn(0); 277e5c89e4eSSatish Balay 2789566063dSJacob Faibussowitsch PetscCall(PetscMallocValidate(lineno, function, filename)); 279e5c89e4eSSatish Balay 280e5c89e4eSSatish Balay ahead = a; 281e5c89e4eSSatish Balay a = a - sizeof(TrSPACE); 282e5c89e4eSSatish Balay head = (TRSPACE *)a; 283e5c89e4eSSatish Balay 2840700a824SBarry Smith if (head->classid != CLASSID_VALUE) { 285ccd65f63SJunchao Zhang (*PetscErrorPrintf)("PetscTrFreeDefault() called from %s() at %s:%d\n", function, filename, lineno); 286e5c89e4eSSatish Balay (*PetscErrorPrintf)("Block at address %p is corrupted; cannot free;\nmay be block not allocated with PetscMalloc()\n", a); 287e32f2f54SBarry Smith SETERRQ(PETSC_COMM_SELF, PETSC_ERR_MEMC, "Bad location or corrupted memory"); 288e5c89e4eSSatish Balay } 2890700a824SBarry Smith nend = (PetscClassId *)(ahead + head->size); 2900700a824SBarry Smith if (*nend != CLASSID_VALUE) { 291e5c89e4eSSatish Balay if (*nend == ALREADY_FREED) { 292ccd65f63SJunchao Zhang (*PetscErrorPrintf)("PetscTrFreeDefault() called from %s() at %s:%d\n", function, filename, lineno); 293e5c89e4eSSatish Balay (*PetscErrorPrintf)("Block [id=%d(%.0f)] at address %p was already freed\n", head->id, (PetscLogDouble)head->size, a + sizeof(TrSPACE)); 294e5c89e4eSSatish Balay if (head->lineno > 0 && head->lineno < 50000 /* sanity check */) { 295ccd65f63SJunchao Zhang (*PetscErrorPrintf)("Block freed in %s() at %s:%d\n", head->functionname, head->filename, head->lineno); 296e5c89e4eSSatish Balay } else { 297ccd65f63SJunchao Zhang (*PetscErrorPrintf)("Block allocated in %s() at %s:%d\n", head->functionname, head->filename, -head->lineno); 298e5c89e4eSSatish Balay } 299e32f2f54SBarry Smith SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Memory already freed"); 300e5c89e4eSSatish Balay } else { 301e5c89e4eSSatish Balay /* Damaged tail */ 302ccd65f63SJunchao Zhang (*PetscErrorPrintf)("PetscTrFreeDefault() called from %s() at %s:%d\n", function, filename, lineno); 303e5c89e4eSSatish Balay (*PetscErrorPrintf)("Block [id=%d(%.0f)] at address %p is corrupted (probably write past end of array)\n", head->id, (PetscLogDouble)head->size, a); 304ccd65f63SJunchao Zhang (*PetscErrorPrintf)("Block allocated in %s() at %s:%d\n", head->functionname, head->filename, head->lineno); 305e32f2f54SBarry Smith SETERRQ(PETSC_COMM_SELF, PETSC_ERR_MEMC, "Corrupted memory"); 306e5c89e4eSSatish Balay } 307e5c89e4eSSatish Balay } 308608c71bfSMatthew G. Knepley if (PetscLogMallocTrace > -1 && head->rsize >= PetscLogMallocTraceThreshold) { 3099566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(PetscLogMallocTraceViewer, "Free %zu %s:%d (%s)\n", head->rsize, filename ? filename : "null", lineno, function ? function : "null")); 310608c71bfSMatthew G. Knepley } 311e5c89e4eSSatish Balay /* Mark the location freed */ 312e5c89e4eSSatish Balay *nend = ALREADY_FREED; 313e5c89e4eSSatish Balay /* Save location where freed. If we suspect the line number, mark as allocated location */ 314608c71bfSMatthew G. Knepley if (lineno > 0 && lineno < 50000) { 315608c71bfSMatthew G. Knepley head->lineno = lineno; 316608c71bfSMatthew G. Knepley head->filename = filename; 317e5c89e4eSSatish Balay head->functionname = function; 318e5c89e4eSSatish Balay } else { 319e5c89e4eSSatish Balay head->lineno = -head->lineno; 320e5c89e4eSSatish Balay } 321608c71bfSMatthew G. Knepley asize = TRrequestedSize ? head->rsize : head->size; 32208401ef6SPierre Jolivet PetscCheck(TRallocated >= asize, PETSC_COMM_SELF, PETSC_ERR_MEMC, "TRallocate is smaller than memory just freed"); 323608c71bfSMatthew G. Knepley TRallocated -= asize; 324e5c89e4eSSatish Balay TRfrags--; 325e5c89e4eSSatish Balay if (head->prev) head->prev->next = head->next; 326e5c89e4eSSatish Balay else TRhead = head->next; 327e5c89e4eSSatish Balay 328e5c89e4eSSatish Balay if (head->next) head->next->prev = head->prev; 3299566063dSJacob Faibussowitsch PetscCall(PetscFreeAlign(a, lineno, function, filename)); 330e5c89e4eSSatish Balay PetscFunctionReturn(0); 331e5c89e4eSSatish Balay } 332e5c89e4eSSatish Balay 3333221ece2SMatthew G. Knepley /* 3343221ece2SMatthew G. Knepley PetscTrReallocDefault - Realloc with tracing. 3353221ece2SMatthew G. Knepley 3363221ece2SMatthew G. Knepley Input Parameters: 3373221ece2SMatthew G. Knepley + len - number of bytes to allocate 3383221ece2SMatthew G. Knepley . lineno - line number where used. Use __LINE__ for this 3393221ece2SMatthew G. Knepley . filename - file name where used. Use __FILE__ for this 34092f119d6SBarry Smith - result - original memory 3413221ece2SMatthew G. Knepley 3423221ece2SMatthew G. Knepley Output Parameter: 3433221ece2SMatthew G. Knepley . result - double aligned pointer to requested storage, or null if not available. 3443221ece2SMatthew G. Knepley 3453221ece2SMatthew G. Knepley Level: developer 3463221ece2SMatthew G. Knepley 347db781477SPatrick Sanan .seealso: `PetscTrMallocDefault()`, `PetscTrFreeDefault()` 3483221ece2SMatthew G. Knepley */ 3499371c9d4SSatish Balay PetscErrorCode PetscTrReallocDefault(size_t len, int lineno, const char function[], const char filename[], void **result) { 3503221ece2SMatthew G. Knepley char *a = (char *)*result; 3513221ece2SMatthew G. Knepley TRSPACE *head; 3523221ece2SMatthew G. Knepley char *ahead, *inew; 3533221ece2SMatthew G. Knepley PetscClassId *nend; 3543221ece2SMatthew G. Knepley size_t nsize; 3553221ece2SMatthew G. Knepley PetscErrorCode ierr; 3563221ece2SMatthew G. Knepley 3573221ece2SMatthew G. Knepley PetscFunctionBegin; 35892f119d6SBarry Smith /* Realloc requests zero space so just free the current space */ 359c22f1541SToby Isaac if (!len) { 3609566063dSJacob Faibussowitsch PetscCall(PetscTrFreeDefault(*result, lineno, function, filename)); 361c22f1541SToby Isaac *result = NULL; 362c22f1541SToby Isaac PetscFunctionReturn(0); 363c22f1541SToby Isaac } 36492f119d6SBarry Smith /* If the orginal space was NULL just use the regular malloc() */ 365f590eff4SLisandro Dalcin if (!*result) { 3669566063dSJacob Faibussowitsch PetscCall(PetscTrMallocDefault(len, PETSC_FALSE, lineno, function, filename, result)); 367f590eff4SLisandro Dalcin PetscFunctionReturn(0); 368f590eff4SLisandro Dalcin } 3693221ece2SMatthew G. Knepley 3709371c9d4SSatish Balay ierr = PetscMallocValidate(lineno, function, filename); 3719371c9d4SSatish Balay if (ierr) PetscFunctionReturn(ierr); 3723221ece2SMatthew G. Knepley 3733221ece2SMatthew G. Knepley ahead = a; 3743221ece2SMatthew G. Knepley a = a - sizeof(TrSPACE); 3753221ece2SMatthew G. Knepley head = (TRSPACE *)a; 3763221ece2SMatthew G. Knepley inew = a; 3773221ece2SMatthew G. Knepley 3783221ece2SMatthew G. Knepley if (head->classid != CLASSID_VALUE) { 379ccd65f63SJunchao Zhang (*PetscErrorPrintf)("PetscTrReallocDefault() called from %s() at %s:%d\n", function, filename, lineno); 3803221ece2SMatthew G. Knepley (*PetscErrorPrintf)("Block at address %p is corrupted; cannot free;\nmay be block not allocated with PetscMalloc()\n", a); 3813221ece2SMatthew G. Knepley SETERRQ(PETSC_COMM_SELF, PETSC_ERR_MEMC, "Bad location or corrupted memory"); 3823221ece2SMatthew G. Knepley } 3833221ece2SMatthew G. Knepley nend = (PetscClassId *)(ahead + head->size); 3843221ece2SMatthew G. Knepley if (*nend != CLASSID_VALUE) { 3853221ece2SMatthew G. Knepley if (*nend == ALREADY_FREED) { 386ccd65f63SJunchao Zhang (*PetscErrorPrintf)("PetscTrReallocDefault() called from %s() at %s:%d\n", function, filename, lineno); 3873221ece2SMatthew G. Knepley (*PetscErrorPrintf)("Block [id=%d(%.0f)] at address %p was already freed\n", head->id, (PetscLogDouble)head->size, a + sizeof(TrSPACE)); 3883221ece2SMatthew G. Knepley if (head->lineno > 0 && head->lineno < 50000 /* sanity check */) { 389ccd65f63SJunchao Zhang (*PetscErrorPrintf)("Block freed in %s() at %s:%d\n", head->functionname, head->filename, head->lineno); 3903221ece2SMatthew G. Knepley } else { 391ccd65f63SJunchao Zhang (*PetscErrorPrintf)("Block allocated in %s() at %s:%d\n", head->functionname, head->filename, -head->lineno); 3923221ece2SMatthew G. Knepley } 3933221ece2SMatthew G. Knepley SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Memory already freed"); 3943221ece2SMatthew G. Knepley } else { 3953221ece2SMatthew G. Knepley /* Damaged tail */ 396ccd65f63SJunchao Zhang (*PetscErrorPrintf)("PetscTrReallocDefault() called from %s() at %s:%d\n", function, filename, lineno); 3973221ece2SMatthew 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); 398ccd65f63SJunchao Zhang (*PetscErrorPrintf)("Block allocated in %s() at %s:%d\n", head->functionname, head->filename, head->lineno); 3993221ece2SMatthew G. Knepley SETERRQ(PETSC_COMM_SELF, PETSC_ERR_MEMC, "Corrupted memory"); 4003221ece2SMatthew G. Knepley } 4013221ece2SMatthew G. Knepley } 4023221ece2SMatthew G. Knepley 40392f119d6SBarry Smith /* remove original reference to the memory allocated from the PETSc debugging heap */ 404608c71bfSMatthew G. Knepley TRallocated -= TRrequestedSize ? head->rsize : head->size; 4053221ece2SMatthew G. Knepley TRfrags--; 4063221ece2SMatthew G. Knepley if (head->prev) head->prev->next = head->next; 4073221ece2SMatthew G. Knepley else TRhead = head->next; 4083221ece2SMatthew G. Knepley if (head->next) head->next->prev = head->prev; 4093221ece2SMatthew G. Knepley 4103221ece2SMatthew G. Knepley nsize = (len + (PETSC_MEMALIGN - 1)) & ~(PETSC_MEMALIGN - 1); 4119566063dSJacob Faibussowitsch PetscCall(PetscReallocAlign(nsize + sizeof(TrSPACE) + sizeof(PetscClassId), lineno, function, filename, (void **)&inew)); 4123221ece2SMatthew G. Knepley 4133221ece2SMatthew G. Knepley head = (TRSPACE *)inew; 4143221ece2SMatthew G. Knepley inew += sizeof(TrSPACE); 4153221ece2SMatthew G. Knepley 4163221ece2SMatthew G. Knepley if (TRhead) TRhead->prev = head; 4173221ece2SMatthew G. Knepley head->next = TRhead; 4183221ece2SMatthew G. Knepley TRhead = head; 4193221ece2SMatthew G. Knepley head->prev = NULL; 4203221ece2SMatthew G. Knepley head->size = nsize; 421608c71bfSMatthew G. Knepley head->rsize = len; 422e269983cSBarry Smith head->id = TRid++; 4233221ece2SMatthew G. Knepley head->lineno = lineno; 4243221ece2SMatthew G. Knepley 4253221ece2SMatthew G. Knepley head->filename = filename; 4263221ece2SMatthew G. Knepley head->functionname = function; 4273221ece2SMatthew G. Knepley head->classid = CLASSID_VALUE; 4283221ece2SMatthew G. Knepley *(PetscClassId *)(inew + nsize) = CLASSID_VALUE; 4293221ece2SMatthew G. Knepley 430608c71bfSMatthew G. Knepley TRallocated += TRrequestedSize ? head->rsize : head->size; 4313221ece2SMatthew G. Knepley if (TRallocated > TRMaxMem) TRMaxMem = TRallocated; 432e3ed9ee7SBarry Smith if (PetscLogMemory) { 433e3ed9ee7SBarry Smith PetscInt i; 434e3ed9ee7SBarry Smith for (i = 0; i < NumTRMaxMems; i++) { 435e3ed9ee7SBarry Smith if (TRallocated > TRMaxMems[i]) TRMaxMems[i] = TRallocated; 436e3ed9ee7SBarry Smith } 437e3ed9ee7SBarry Smith } 4383221ece2SMatthew G. Knepley TRfrags++; 4393221ece2SMatthew G. Knepley 4403221ece2SMatthew G. Knepley #if defined(PETSC_USE_DEBUG) 4419566063dSJacob Faibussowitsch PetscCall(PetscStackCopy(&petscstack, &head->stack)); 4423221ece2SMatthew G. Knepley /* fix the line number to where the malloc() was called, not the PetscFunctionBegin; */ 4433221ece2SMatthew G. Knepley head->stack.line[head->stack.currentsize - 2] = lineno; 4443221ece2SMatthew G. Knepley #endif 4453221ece2SMatthew G. Knepley 4463221ece2SMatthew G. Knepley /* 44792f119d6SBarry Smith Allow logging of all mallocs made. This adds a new entry to the list of allocated memory 44892f119d6SBarry Smith and does not remove the previous entry to the list hence this memory is "double counted" in PetscMallocView() 4493221ece2SMatthew G. Knepley */ 4503221ece2SMatthew G. Knepley if (PetscLogMalloc > -1 && PetscLogMalloc < PetscLogMallocMax && len >= PetscLogMallocThreshold) { 4513221ece2SMatthew G. Knepley if (!PetscLogMalloc) { 4523221ece2SMatthew G. Knepley PetscLogMallocLength = (size_t *)malloc(PetscLogMallocMax * sizeof(size_t)); 45328b400f6SJacob Faibussowitsch PetscCheck(PetscLogMallocLength, PETSC_COMM_SELF, PETSC_ERR_MEM, " "); 4543221ece2SMatthew G. Knepley 4553221ece2SMatthew G. Knepley PetscLogMallocFile = (const char **)malloc(PetscLogMallocMax * sizeof(char *)); 45628b400f6SJacob Faibussowitsch PetscCheck(PetscLogMallocFile, PETSC_COMM_SELF, PETSC_ERR_MEM, " "); 4573221ece2SMatthew G. Knepley 4583221ece2SMatthew G. Knepley PetscLogMallocFunction = (const char **)malloc(PetscLogMallocMax * sizeof(char *)); 45928b400f6SJacob Faibussowitsch PetscCheck(PetscLogMallocFunction, PETSC_COMM_SELF, PETSC_ERR_MEM, " "); 4603221ece2SMatthew G. Knepley } 4613221ece2SMatthew G. Knepley PetscLogMallocLength[PetscLogMalloc] = nsize; 4623221ece2SMatthew G. Knepley PetscLogMallocFile[PetscLogMalloc] = filename; 4633221ece2SMatthew G. Knepley PetscLogMallocFunction[PetscLogMalloc++] = function; 4643221ece2SMatthew G. Knepley } 4653221ece2SMatthew G. Knepley *result = (void *)inew; 4663221ece2SMatthew G. Knepley PetscFunctionReturn(0); 4673221ece2SMatthew G. Knepley } 4683221ece2SMatthew G. Knepley 469fe7fb379SMatthew Knepley /*@C 47092f119d6SBarry Smith PetscMemoryView - Shows the amount of memory currently being used in a communicator. 471e5c89e4eSSatish Balay 472e5c89e4eSSatish Balay Collective on PetscViewer 473e5c89e4eSSatish Balay 474d8d19677SJose E. Roman Input Parameters: 475e5c89e4eSSatish Balay + viewer - the viewer that defines the communicator 476e5c89e4eSSatish Balay - message - string printed before values 477e5c89e4eSSatish Balay 4780841954dSBarry Smith Options Database: 47992f119d6SBarry Smith + -malloc_debug - have PETSc track how much memory it has allocated 4800841954dSBarry Smith - -memory_view - during PetscFinalize() have this routine called 4810841954dSBarry Smith 482e5c89e4eSSatish Balay Level: intermediate 483e5c89e4eSSatish Balay 484db781477SPatrick Sanan .seealso: `PetscMallocDump()`, `PetscMemoryGetCurrentUsage()`, `PetscMemorySetGetMaximumUsage()`, `PetscMallocView()` 485e5c89e4eSSatish Balay @*/ 4869371c9d4SSatish Balay PetscErrorCode PetscMemoryView(PetscViewer viewer, const char message[]) { 4870841954dSBarry Smith PetscLogDouble allocated, allocatedmax, resident, residentmax, gallocated, gallocatedmax, gresident, gresidentmax, maxgallocated, maxgallocatedmax, maxgresident, maxgresidentmax; 4880841954dSBarry Smith PetscLogDouble mingallocated, mingallocatedmax, mingresident, mingresidentmax; 489e5c89e4eSSatish Balay MPI_Comm comm; 490e5c89e4eSSatish Balay 491e5c89e4eSSatish Balay PetscFunctionBegin; 492e5c89e4eSSatish Balay if (!viewer) viewer = PETSC_VIEWER_STDOUT_WORLD; 4939566063dSJacob Faibussowitsch PetscCall(PetscMallocGetCurrentUsage(&allocated)); 4949566063dSJacob Faibussowitsch PetscCall(PetscMallocGetMaximumUsage(&allocatedmax)); 4959566063dSJacob Faibussowitsch PetscCall(PetscMemoryGetCurrentUsage(&resident)); 4969566063dSJacob Faibussowitsch PetscCall(PetscMemoryGetMaximumUsage(&residentmax)); 497e5c89e4eSSatish Balay if (residentmax > 0) residentmax = PetscMax(resident, residentmax); 4989566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)viewer, &comm)); 4999566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "%s", message)); 500e5c89e4eSSatish Balay if (resident && residentmax && allocated) { 5019566063dSJacob Faibussowitsch PetscCallMPI(MPI_Reduce(&residentmax, &gresidentmax, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm)); 5029566063dSJacob Faibussowitsch PetscCallMPI(MPI_Reduce(&residentmax, &maxgresidentmax, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm)); 5039566063dSJacob Faibussowitsch PetscCallMPI(MPI_Reduce(&residentmax, &mingresidentmax, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm)); 5049566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Maximum (over computational time) process memory: total %5.4e max %5.4e min %5.4e\n", gresidentmax, maxgresidentmax, mingresidentmax)); 5059566063dSJacob Faibussowitsch PetscCallMPI(MPI_Reduce(&resident, &gresident, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm)); 5069566063dSJacob Faibussowitsch PetscCallMPI(MPI_Reduce(&resident, &maxgresident, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm)); 5079566063dSJacob Faibussowitsch PetscCallMPI(MPI_Reduce(&resident, &mingresident, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm)); 5089566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Current process memory: total %5.4e max %5.4e min %5.4e\n", gresident, maxgresident, mingresident)); 5099566063dSJacob Faibussowitsch PetscCallMPI(MPI_Reduce(&allocatedmax, &gallocatedmax, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm)); 5109566063dSJacob Faibussowitsch PetscCallMPI(MPI_Reduce(&allocatedmax, &maxgallocatedmax, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm)); 5119566063dSJacob Faibussowitsch PetscCallMPI(MPI_Reduce(&allocatedmax, &mingallocatedmax, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm)); 5129566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Maximum (over computational time) space PetscMalloc()ed: total %5.4e max %5.4e min %5.4e\n", gallocatedmax, maxgallocatedmax, mingallocatedmax)); 5139566063dSJacob Faibussowitsch PetscCallMPI(MPI_Reduce(&allocated, &gallocated, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm)); 5149566063dSJacob Faibussowitsch PetscCallMPI(MPI_Reduce(&allocated, &maxgallocated, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm)); 5159566063dSJacob Faibussowitsch PetscCallMPI(MPI_Reduce(&allocated, &mingallocated, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm)); 5169566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Current space PetscMalloc()ed: total %5.4e max %5.4e min %5.4e\n", gallocated, maxgallocated, mingallocated)); 517e5c89e4eSSatish Balay } else if (resident && residentmax) { 5189566063dSJacob Faibussowitsch PetscCallMPI(MPI_Reduce(&residentmax, &gresidentmax, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm)); 5199566063dSJacob Faibussowitsch PetscCallMPI(MPI_Reduce(&residentmax, &maxgresidentmax, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm)); 5209566063dSJacob Faibussowitsch PetscCallMPI(MPI_Reduce(&residentmax, &mingresidentmax, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm)); 5219566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Maximum (over computational time) process memory: total %5.4e max %5.4e min %5.4e\n", gresidentmax, maxgresidentmax, mingresidentmax)); 5229566063dSJacob Faibussowitsch PetscCallMPI(MPI_Reduce(&resident, &gresident, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm)); 5239566063dSJacob Faibussowitsch PetscCallMPI(MPI_Reduce(&resident, &maxgresident, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm)); 5249566063dSJacob Faibussowitsch PetscCallMPI(MPI_Reduce(&resident, &mingresident, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm)); 5259566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Current process memory: total %5.4e max %5.4e min %5.4e\n", gresident, maxgresident, mingresident)); 526e5c89e4eSSatish Balay } else if (resident && allocated) { 5279566063dSJacob Faibussowitsch PetscCallMPI(MPI_Reduce(&resident, &gresident, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm)); 5289566063dSJacob Faibussowitsch PetscCallMPI(MPI_Reduce(&resident, &maxgresident, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm)); 5299566063dSJacob Faibussowitsch PetscCallMPI(MPI_Reduce(&resident, &mingresident, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm)); 5309566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Current process memory: total %5.4e max %5.4e min %5.4e\n", gresident, maxgresident, mingresident)); 5319566063dSJacob Faibussowitsch PetscCallMPI(MPI_Reduce(&allocated, &gallocated, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm)); 5329566063dSJacob Faibussowitsch PetscCallMPI(MPI_Reduce(&allocated, &maxgallocated, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm)); 5339566063dSJacob Faibussowitsch PetscCallMPI(MPI_Reduce(&allocated, &mingallocated, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm)); 5349566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Current space PetscMalloc()ed: total %5.4e max %5.4e min %5.4e\n", gallocated, maxgallocated, mingallocated)); 5359566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Run with -memory_view to get maximum memory usage\n")); 536e5c89e4eSSatish Balay } else if (allocated) { 5379566063dSJacob Faibussowitsch PetscCallMPI(MPI_Reduce(&allocated, &gallocated, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm)); 5389566063dSJacob Faibussowitsch PetscCallMPI(MPI_Reduce(&allocated, &maxgallocated, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm)); 5399566063dSJacob Faibussowitsch PetscCallMPI(MPI_Reduce(&allocated, &mingallocated, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm)); 5409566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Current space PetscMalloc()ed: total %5.4e max %5.4e min %5.4e\n", gallocated, maxgallocated, mingallocated)); 5419566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Run with -memory_view to get maximum memory usage\n")); 5429566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "OS cannot compute process memory\n")); 543e5c89e4eSSatish Balay } else { 5449566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Run with -malloc_debug to get statistics on PetscMalloc() calls\nOS cannot compute process memory\n")); 545e5c89e4eSSatish Balay } 5469566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(viewer)); 547e5c89e4eSSatish Balay PetscFunctionReturn(0); 548e5c89e4eSSatish Balay } 549e5c89e4eSSatish Balay 55046eb3923SBarry Smith /*@ 551e5c89e4eSSatish Balay PetscMallocGetCurrentUsage - gets the current amount of memory used that was PetscMalloc()ed 552e5c89e4eSSatish Balay 553e5c89e4eSSatish Balay Not Collective 554e5c89e4eSSatish Balay 555e5c89e4eSSatish Balay Output Parameters: 556e5c89e4eSSatish Balay . space - number of bytes currently allocated 557e5c89e4eSSatish Balay 558e5c89e4eSSatish Balay Level: intermediate 559e5c89e4eSSatish Balay 560db781477SPatrick Sanan .seealso: `PetscMallocDump()`, `PetscMallocGetMaximumUsage()`, `PetscMemoryGetCurrentUsage()`, 561db781477SPatrick Sanan `PetscMemoryGetMaximumUsage()` 562e5c89e4eSSatish Balay @*/ 5639371c9d4SSatish Balay PetscErrorCode PetscMallocGetCurrentUsage(PetscLogDouble *space) { 564e5c89e4eSSatish Balay PetscFunctionBegin; 565e5c89e4eSSatish Balay *space = (PetscLogDouble)TRallocated; 566e5c89e4eSSatish Balay PetscFunctionReturn(0); 567e5c89e4eSSatish Balay } 568e5c89e4eSSatish Balay 569dc37d89fSBarry Smith /*@ 570e5c89e4eSSatish Balay PetscMallocGetMaximumUsage - gets the maximum amount of memory used that was PetscMalloc()ed at any time 571e5c89e4eSSatish Balay during this run. 572e5c89e4eSSatish Balay 573e5c89e4eSSatish Balay Not Collective 574e5c89e4eSSatish Balay 575e5c89e4eSSatish Balay Output Parameters: 576e5c89e4eSSatish Balay . space - maximum number of bytes ever allocated at one time 577e5c89e4eSSatish Balay 578e5c89e4eSSatish Balay Level: intermediate 579e5c89e4eSSatish Balay 580db781477SPatrick Sanan .seealso: `PetscMallocDump()`, `PetscMallocView()`, `PetscMallocGetMaximumUsage()`, `PetscMemoryGetCurrentUsage()`, 581db781477SPatrick Sanan `PetscMallocPushMaximumUsage()` 582e5c89e4eSSatish Balay @*/ 5839371c9d4SSatish Balay PetscErrorCode PetscMallocGetMaximumUsage(PetscLogDouble *space) { 584e5c89e4eSSatish Balay PetscFunctionBegin; 585e5c89e4eSSatish Balay *space = (PetscLogDouble)TRMaxMem; 586e5c89e4eSSatish Balay PetscFunctionReturn(0); 587e5c89e4eSSatish Balay } 588e5c89e4eSSatish Balay 589e3ed9ee7SBarry Smith /*@ 590e3ed9ee7SBarry Smith PetscMallocPushMaximumUsage - Adds another event to collect the maximum memory usage over an event 591e3ed9ee7SBarry Smith 592e3ed9ee7SBarry Smith Not Collective 593e3ed9ee7SBarry Smith 594e3ed9ee7SBarry Smith Input Parameter: 595e3ed9ee7SBarry Smith . event - an event id; this is just for error checking 596e3ed9ee7SBarry Smith 597e3ed9ee7SBarry Smith Level: developer 598e3ed9ee7SBarry Smith 599db781477SPatrick Sanan .seealso: `PetscMallocDump()`, `PetscMallocView()`, `PetscMallocGetMaximumUsage()`, `PetscMemoryGetCurrentUsage()`, 600db781477SPatrick Sanan `PetscMallocPopMaximumUsage()` 601e3ed9ee7SBarry Smith @*/ 6029371c9d4SSatish Balay PetscErrorCode PetscMallocPushMaximumUsage(int event) { 603e3ed9ee7SBarry Smith PetscFunctionBegin; 604e3ed9ee7SBarry Smith if (++NumTRMaxMems > MAXTRMAXMEMS) PetscFunctionReturn(0); 605e3ed9ee7SBarry Smith TRMaxMems[NumTRMaxMems - 1] = TRallocated; 606e3ed9ee7SBarry Smith TRMaxMemsEvents[NumTRMaxMems - 1] = event; 607e3ed9ee7SBarry Smith PetscFunctionReturn(0); 608e3ed9ee7SBarry Smith } 609e3ed9ee7SBarry Smith 610e3ed9ee7SBarry Smith /*@ 611e3ed9ee7SBarry Smith PetscMallocPopMaximumUsage - collect the maximum memory usage over an event 612e3ed9ee7SBarry Smith 613e3ed9ee7SBarry Smith Not Collective 614e3ed9ee7SBarry Smith 615e3ed9ee7SBarry Smith Input Parameter: 616e3ed9ee7SBarry Smith . event - an event id; this is just for error checking 617e3ed9ee7SBarry Smith 618e3ed9ee7SBarry Smith Output Parameter: 619e3ed9ee7SBarry Smith . mu - maximum amount of memory malloced during this event; high water mark relative to the beginning of the event 620e3ed9ee7SBarry Smith 621e3ed9ee7SBarry Smith Level: developer 622e3ed9ee7SBarry Smith 623db781477SPatrick Sanan .seealso: `PetscMallocDump()`, `PetscMallocView()`, `PetscMallocGetMaximumUsage()`, `PetscMemoryGetCurrentUsage()`, 624db781477SPatrick Sanan `PetscMallocPushMaximumUsage()` 625e3ed9ee7SBarry Smith @*/ 6269371c9d4SSatish Balay PetscErrorCode PetscMallocPopMaximumUsage(int event, PetscLogDouble *mu) { 627e3ed9ee7SBarry Smith PetscFunctionBegin; 628e3ed9ee7SBarry Smith *mu = 0; 629e3ed9ee7SBarry Smith if (NumTRMaxMems-- > MAXTRMAXMEMS) PetscFunctionReturn(0); 63008401ef6SPierre Jolivet PetscCheck(TRMaxMemsEvents[NumTRMaxMems] == event, PETSC_COMM_SELF, PETSC_ERR_MEMC, "PetscMallocPush/PopMaximumUsage() are not nested"); 631e3ed9ee7SBarry Smith *mu = TRMaxMems[NumTRMaxMems]; 632e3ed9ee7SBarry Smith PetscFunctionReturn(0); 633e3ed9ee7SBarry Smith } 634e3ed9ee7SBarry Smith 635a64a8e02SBarry Smith #if defined(PETSC_USE_DEBUG) 636a64a8e02SBarry Smith /*@C 637a64a8e02SBarry Smith PetscMallocGetStack - returns a pointer to the stack for the location in the program a call to PetscMalloc() was used to obtain that memory 638a64a8e02SBarry Smith 639a64a8e02SBarry Smith Collective on PETSC_COMM_WORLD 640a64a8e02SBarry Smith 641a64a8e02SBarry Smith Input Parameter: 642a64a8e02SBarry Smith . ptr - the memory location 643a64a8e02SBarry Smith 644fd292e60Sprj- Output Parameter: 645a64a8e02SBarry Smith . stack - the stack indicating where the program allocated this memory 646a64a8e02SBarry Smith 647a64a8e02SBarry Smith Level: intermediate 648a64a8e02SBarry Smith 649db781477SPatrick Sanan .seealso: `PetscMallocGetCurrentUsage()`, `PetscMallocView()` 650a64a8e02SBarry Smith @*/ 6519371c9d4SSatish Balay PetscErrorCode PetscMallocGetStack(void *ptr, PetscStack **stack) { 652a64a8e02SBarry Smith TRSPACE *head; 653a64a8e02SBarry Smith 654a64a8e02SBarry Smith PetscFunctionBegin; 655a64a8e02SBarry Smith head = (TRSPACE *)(((char *)ptr) - HEADER_BYTES); 656a64a8e02SBarry Smith *stack = &head->stack; 657a64a8e02SBarry Smith PetscFunctionReturn(0); 658a64a8e02SBarry Smith } 65976386721SLisandro Dalcin #else 6609371c9d4SSatish Balay PetscErrorCode PetscMallocGetStack(void *ptr, void **stack) { 66176386721SLisandro Dalcin PetscFunctionBegin; 662f0ba7cfcSLisandro Dalcin *stack = NULL; 66376386721SLisandro Dalcin PetscFunctionReturn(0); 66476386721SLisandro Dalcin } 665a64a8e02SBarry Smith #endif 666a64a8e02SBarry Smith 667e5c89e4eSSatish Balay /*@C 66892f119d6SBarry Smith PetscMallocDump - Dumps the currently allocated memory blocks to a file. The information 669e5c89e4eSSatish Balay printed is: size of space (in bytes), address of space, id of space, 670e5c89e4eSSatish Balay file in which space was allocated, and line number at which it was 671e5c89e4eSSatish Balay allocated. 672e5c89e4eSSatish Balay 67392f119d6SBarry Smith Not Collective 674e5c89e4eSSatish Balay 675e5c89e4eSSatish Balay Input Parameter: 676e5c89e4eSSatish Balay . fp - file pointer. If fp is NULL, stdout is assumed. 677e5c89e4eSSatish Balay 678e5c89e4eSSatish Balay Options Database Key: 67992f119d6SBarry Smith . -malloc_dump <optional filename> - Dumps unfreed memory during call to PetscFinalize() 680e5c89e4eSSatish Balay 681e5c89e4eSSatish Balay Level: intermediate 682e5c89e4eSSatish Balay 683e5c89e4eSSatish Balay Fortran Note: 684e5c89e4eSSatish Balay The calling sequence in Fortran is PetscMallocDump(integer ierr) 685e5c89e4eSSatish Balay The fp defaults to stdout. 686e5c89e4eSSatish Balay 68795452b02SPatrick Sanan Notes: 68892f119d6SBarry Smith Uses MPI_COMM_WORLD to display rank, because this may be called in PetscFinalize() after PETSC_COMM_WORLD has been freed. 689e5c89e4eSSatish Balay 69092f119d6SBarry Smith When called in PetscFinalize() dumps only the allocations that have not been properly freed 69192f119d6SBarry Smith 69292f119d6SBarry Smith PetscMallocView() prints a list of all memory ever allocated 69392f119d6SBarry Smith 694db781477SPatrick Sanan .seealso: `PetscMallocGetCurrentUsage()`, `PetscMallocView()`, `PetscMallocViewSet()`, `PetscMallocValidate()` 695e5c89e4eSSatish Balay @*/ 6969371c9d4SSatish Balay PetscErrorCode PetscMallocDump(FILE *fp) { 697e5c89e4eSSatish Balay TRSPACE *head; 698e3ed9ee7SBarry Smith size_t libAlloc = 0; 699e5c89e4eSSatish Balay PetscMPIInt rank; 700e5c89e4eSSatish Balay 701e5c89e4eSSatish Balay PetscFunctionBegin; 7029566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(MPI_COMM_WORLD, &rank)); 703da9f1d6bSBarry Smith if (!fp) fp = PETSC_STDOUT; 704e5c89e4eSSatish Balay head = TRhead; 705e5c89e4eSSatish Balay while (head) { 706608c71bfSMatthew G. Knepley libAlloc += TRrequestedSize ? head->rsize : head->size; 7075486ca60SMatthew G. Knepley head = head->next; 7085486ca60SMatthew G. Knepley } 7095486ca60SMatthew G. Knepley if (TRallocated - libAlloc > 0) fprintf(fp, "[%d]Total space allocated %.0f bytes\n", rank, (PetscLogDouble)TRallocated); 7105486ca60SMatthew G. Knepley head = TRhead; 7115486ca60SMatthew G. Knepley while (head) { 7125486ca60SMatthew G. Knepley PetscBool isLib; 7135486ca60SMatthew G. Knepley 7149566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(head->functionname, "PetscDLLibraryOpen", &isLib)); 7155486ca60SMatthew G. Knepley if (!isLib) { 716ccd65f63SJunchao Zhang fprintf(fp, "[%2d] %.0f bytes %s() at %s:%d\n", rank, (PetscLogDouble)(TRrequestedSize ? head->rsize : head->size), head->functionname, head->filename, head->lineno); 7178bf1f09cSShri Abhyankar #if defined(PETSC_USE_DEBUG) 7189566063dSJacob Faibussowitsch PetscCall(PetscStackPrint(&head->stack, fp)); 719e5c89e4eSSatish Balay #endif 7205486ca60SMatthew G. Knepley } 721e5c89e4eSSatish Balay head = head->next; 722e5c89e4eSSatish Balay } 723e5c89e4eSSatish Balay PetscFunctionReturn(0); 724e5c89e4eSSatish Balay } 725e5c89e4eSSatish Balay 726dc37d89fSBarry Smith /*@ 72792f119d6SBarry Smith PetscMallocViewSet - Activates logging of all calls to PetscMalloc() with a minimum size to view 728574034a9SJed Brown 729574034a9SJed Brown Not Collective 730574034a9SJed Brown 7314165533cSJose E. Roman Input Parameter: 732574034a9SJed Brown . logmin - minimum allocation size to log, or PETSC_DEFAULT 733574034a9SJed Brown 734574034a9SJed Brown Options Database Key: 73592f119d6SBarry Smith + -malloc_view <optional filename> - Activates PetscMallocView() in PetscFinalize() 7368b254c29SBarry Smith . -malloc_view_threshold <min> - Sets a minimum size if -malloc_view is used 7378b254c29SBarry Smith - -log_view_memory - view the memory usage also with the -log_view option 738574034a9SJed Brown 739574034a9SJed Brown Level: advanced 740574034a9SJed Brown 74192f119d6SBarry Smith Notes: Must be called after PetscMallocSetDebug() 74292f119d6SBarry Smith 74392f119d6SBarry Smith Uses MPI_COMM_WORLD to determine rank because PETSc communicators may not be available 74492f119d6SBarry Smith 745db781477SPatrick Sanan .seealso: `PetscMallocDump()`, `PetscMallocView()`, `PetscMallocViewSet()`, `PetscMallocTraceSet()`, `PetscMallocValidate()` 746574034a9SJed Brown @*/ 7479371c9d4SSatish Balay PetscErrorCode PetscMallocViewSet(PetscLogDouble logmin) { 748574034a9SJed Brown PetscFunctionBegin; 74992f119d6SBarry Smith PetscLogMalloc = 0; 7509566063dSJacob Faibussowitsch PetscCall(PetscMemorySetGetMaximumUsage()); 751574034a9SJed Brown if (logmin < 0) logmin = 0.0; /* PETSC_DEFAULT or PETSC_DECIDE */ 752574034a9SJed Brown PetscLogMallocThreshold = (size_t)logmin; 753574034a9SJed Brown PetscFunctionReturn(0); 754574034a9SJed Brown } 755574034a9SJed Brown 756dc37d89fSBarry Smith /*@ 75792f119d6SBarry Smith PetscMallocViewGet - Determine whether all calls to PetscMalloc() are being logged 75818a2528dSJed Brown 75918a2528dSJed Brown Not Collective 76018a2528dSJed Brown 7614165533cSJose E. Roman Output Parameter 76218a2528dSJed Brown . logging - PETSC_TRUE if logging is active 76318a2528dSJed Brown 76418a2528dSJed Brown Options Database Key: 76592f119d6SBarry Smith . -malloc_view <optional filename> - Activates PetscMallocView() 76618a2528dSJed Brown 76718a2528dSJed Brown Level: advanced 76818a2528dSJed Brown 769db781477SPatrick Sanan .seealso: `PetscMallocDump()`, `PetscMallocView()`, `PetscMallocTraceGet()` 77018a2528dSJed Brown @*/ 7719371c9d4SSatish Balay PetscErrorCode PetscMallocViewGet(PetscBool *logging) { 77218a2528dSJed Brown PetscFunctionBegin; 77318a2528dSJed Brown *logging = (PetscBool)(PetscLogMalloc >= 0); 77418a2528dSJed Brown PetscFunctionReturn(0); 77518a2528dSJed Brown } 77618a2528dSJed Brown 777608c71bfSMatthew G. Knepley /*@ 778608c71bfSMatthew G. Knepley PetscMallocTraceSet - Trace all calls to PetscMalloc() 779608c71bfSMatthew G. Knepley 780608c71bfSMatthew G. Knepley Not Collective 781608c71bfSMatthew G. Knepley 7824165533cSJose E. Roman Input Parameters: 783608c71bfSMatthew G. Knepley + viewer - The viewer to use for tracing, or NULL to use stdout 784608c71bfSMatthew G. Knepley . active - Flag to activate or deactivate tracing 785608c71bfSMatthew G. Knepley - logmin - The smallest memory size that will be logged 786608c71bfSMatthew G. Knepley 787608c71bfSMatthew G. Knepley Note: 788608c71bfSMatthew G. Knepley The viewer should not be collective. 789608c71bfSMatthew G. Knepley 790608c71bfSMatthew G. Knepley Level: advanced 791608c71bfSMatthew G. Knepley 792db781477SPatrick Sanan .seealso: `PetscMallocTraceGet()`, `PetscMallocViewGet()`, `PetscMallocDump()`, `PetscMallocView()` 793608c71bfSMatthew G. Knepley @*/ 7949371c9d4SSatish Balay PetscErrorCode PetscMallocTraceSet(PetscViewer viewer, PetscBool active, PetscLogDouble logmin) { 795608c71bfSMatthew G. Knepley PetscFunctionBegin; 7969371c9d4SSatish Balay if (!active) { 7979371c9d4SSatish Balay PetscLogMallocTrace = -1; 7989371c9d4SSatish Balay PetscFunctionReturn(0); 7999371c9d4SSatish Balay } 800608c71bfSMatthew G. Knepley PetscLogMallocTraceViewer = !viewer ? PETSC_VIEWER_STDOUT_SELF : viewer; 801608c71bfSMatthew G. Knepley PetscLogMallocTrace = 0; 8029566063dSJacob Faibussowitsch PetscCall(PetscMemorySetGetMaximumUsage()); 803608c71bfSMatthew G. Knepley if (logmin < 0) logmin = 0.0; /* PETSC_DEFAULT or PETSC_DECIDE */ 804608c71bfSMatthew G. Knepley PetscLogMallocTraceThreshold = (size_t)logmin; 805608c71bfSMatthew G. Knepley PetscFunctionReturn(0); 806608c71bfSMatthew G. Knepley } 807608c71bfSMatthew G. Knepley 808608c71bfSMatthew G. Knepley /*@ 809608c71bfSMatthew G. Knepley PetscMallocTraceGet - Determine whether all calls to PetscMalloc() are being traced 810608c71bfSMatthew G. Knepley 811608c71bfSMatthew G. Knepley Not Collective 812608c71bfSMatthew G. Knepley 8134165533cSJose E. Roman Output Parameter: 814608c71bfSMatthew G. Knepley . logging - PETSC_TRUE if logging is active 815608c71bfSMatthew G. Knepley 816608c71bfSMatthew G. Knepley Options Database Key: 817608c71bfSMatthew G. Knepley . -malloc_view <optional filename> - Activates PetscMallocView() 818608c71bfSMatthew G. Knepley 819608c71bfSMatthew G. Knepley Level: advanced 820608c71bfSMatthew G. Knepley 821db781477SPatrick Sanan .seealso: `PetscMallocTraceSet()`, `PetscMallocViewGet()`, `PetscMallocDump()`, `PetscMallocView()` 822608c71bfSMatthew G. Knepley @*/ 8239371c9d4SSatish Balay PetscErrorCode PetscMallocTraceGet(PetscBool *logging) { 824608c71bfSMatthew G. Knepley PetscFunctionBegin; 825608c71bfSMatthew G. Knepley *logging = (PetscBool)(PetscLogMallocTrace >= 0); 826608c71bfSMatthew G. Knepley PetscFunctionReturn(0); 827608c71bfSMatthew G. Knepley } 828608c71bfSMatthew G. Knepley 829e5c89e4eSSatish Balay /*@C 83092f119d6SBarry Smith PetscMallocView - Saves the log of all calls to PetscMalloc(); also calls 83121b680ceSJed Brown PetscMemoryGetMaximumUsage() 832e5c89e4eSSatish Balay 83392f119d6SBarry Smith Not Collective 834e5c89e4eSSatish Balay 835e5c89e4eSSatish Balay Input Parameter: 8360298fd71SBarry Smith . fp - file pointer; or NULL 837e5c89e4eSSatish Balay 838e5c89e4eSSatish Balay Options Database Key: 83992f119d6SBarry Smith . -malloc_view <optional filename> - Activates PetscMallocView() in PetscFinalize() 840e5c89e4eSSatish Balay 841e5c89e4eSSatish Balay Level: advanced 842e5c89e4eSSatish Balay 843e5c89e4eSSatish Balay Fortran Note: 84492f119d6SBarry Smith The calling sequence in Fortran is PetscMallocView(integer ierr) 845e5c89e4eSSatish Balay The fp defaults to stdout. 846e5c89e4eSSatish Balay 84792f119d6SBarry Smith Notes: 84892f119d6SBarry Smith PetscMallocDump() dumps only the currently unfreed memory, this dumps all memory ever allocated 84992f119d6SBarry Smith 85092f119d6SBarry Smith PetscMemoryView() gives a brief summary of current memory usage 85192f119d6SBarry Smith 852db781477SPatrick Sanan .seealso: `PetscMallocGetCurrentUsage()`, `PetscMallocDump()`, `PetscMallocViewSet()`, `PetscMemoryView()` 853e5c89e4eSSatish Balay @*/ 8549371c9d4SSatish Balay PetscErrorCode PetscMallocView(FILE *fp) { 85592f119d6SBarry Smith PetscInt i, j, n, *perm; 856e5c89e4eSSatish Balay size_t *shortlength; 857f56c2debSBarry Smith int *shortcount, err; 85892f119d6SBarry Smith PetscMPIInt rank; 859ace3abfcSBarry Smith PetscBool match; 860e5c89e4eSSatish Balay const char **shortfunction; 861e5c89e4eSSatish Balay PetscLogDouble rss; 862e5c89e4eSSatish Balay 863e5c89e4eSSatish Balay PetscFunctionBegin; 8649566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(MPI_COMM_WORLD, &rank)); 865f56c2debSBarry Smith err = fflush(fp); 86628b400f6SJacob Faibussowitsch PetscCheck(!err, PETSC_COMM_SELF, PETSC_ERR_SYS, "fflush() failed on file"); 867f56c2debSBarry Smith 86808401ef6SPierre Jolivet PetscCheck(PetscLogMalloc >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "PetscMallocView() called without call to PetscMallocViewSet() this is often due to\n setting the option -malloc_view AFTER PetscInitialize() with PetscOptionsInsert() or PetscOptionsInsertFile()"); 869768aa557SSatish Balay 870da9f1d6bSBarry Smith if (!fp) fp = PETSC_STDOUT; 8719566063dSJacob Faibussowitsch PetscCall(PetscMemoryGetMaximumUsage(&rss)); 872e5c89e4eSSatish Balay if (rss) { 87392f119d6SBarry Smith (void)fprintf(fp, "[%d] Maximum memory PetscMalloc()ed %.0f maximum size of entire process %.0f\n", rank, (PetscLogDouble)TRMaxMem, rss); 874e5c89e4eSSatish Balay } else { 87592f119d6SBarry Smith (void)fprintf(fp, "[%d] Maximum memory PetscMalloc()ed %.0f OS cannot compute size of entire process\n", rank, (PetscLogDouble)TRMaxMem); 876e5c89e4eSSatish Balay } 8779371c9d4SSatish Balay shortcount = (int *)malloc(PetscLogMalloc * sizeof(int)); 8789371c9d4SSatish Balay PetscCheck(shortcount, PETSC_COMM_SELF, PETSC_ERR_MEM, "Out of memory"); 8799371c9d4SSatish Balay shortlength = (size_t *)malloc(PetscLogMalloc * sizeof(size_t)); 8809371c9d4SSatish Balay PetscCheck(shortlength, PETSC_COMM_SELF, PETSC_ERR_MEM, "Out of memory"); 8819371c9d4SSatish Balay shortfunction = (const char **)malloc(PetscLogMalloc * sizeof(char *)); 8829371c9d4SSatish Balay PetscCheck(shortfunction, PETSC_COMM_SELF, PETSC_ERR_MEM, "Out of memory"); 88397b9d747SJed Brown for (i = 0, n = 0; i < PetscLogMalloc; i++) { 884e5c89e4eSSatish Balay for (j = 0; j < n; j++) { 8859566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(shortfunction[j], PetscLogMallocFunction[i], &match)); 886e5c89e4eSSatish Balay if (match) { 887e5c89e4eSSatish Balay shortlength[j] += PetscLogMallocLength[i]; 88859ffdab8SBarry Smith shortcount[j]++; 889e5c89e4eSSatish Balay goto foundit; 890e5c89e4eSSatish Balay } 891e5c89e4eSSatish Balay } 892e5c89e4eSSatish Balay shortfunction[n] = PetscLogMallocFunction[i]; 893e5c89e4eSSatish Balay shortlength[n] = PetscLogMallocLength[i]; 89459ffdab8SBarry Smith shortcount[n] = 1; 895e5c89e4eSSatish Balay n++; 896e5c89e4eSSatish Balay foundit:; 897e5c89e4eSSatish Balay } 898e5c89e4eSSatish Balay 8999371c9d4SSatish Balay perm = (PetscInt *)malloc(n * sizeof(PetscInt)); 9009371c9d4SSatish Balay PetscCheck(perm, PETSC_COMM_SELF, PETSC_ERR_MEM, "Out of memory"); 901e5c89e4eSSatish Balay for (i = 0; i < n; i++) perm[i] = i; 9029566063dSJacob Faibussowitsch PetscCall(PetscSortStrWithPermutation(n, (const char **)shortfunction, perm)); 903e5c89e4eSSatish Balay 90492f119d6SBarry Smith (void)fprintf(fp, "[%d] Memory usage sorted by function\n", rank); 9059371c9d4SSatish Balay for (i = 0; i < n; i++) { (void)fprintf(fp, "[%d] %d %.0f %s()\n", rank, shortcount[perm[i]], (PetscLogDouble)shortlength[perm[i]], shortfunction[perm[i]]); } 906e5c89e4eSSatish Balay free(perm); 907e5c89e4eSSatish Balay free(shortlength); 90859ffdab8SBarry Smith free(shortcount); 909e5c89e4eSSatish Balay free((char **)shortfunction); 910f56c2debSBarry Smith err = fflush(fp); 91128b400f6SJacob Faibussowitsch PetscCheck(!err, PETSC_COMM_SELF, PETSC_ERR_SYS, "fflush() failed on file"); 912e5c89e4eSSatish Balay PetscFunctionReturn(0); 913e5c89e4eSSatish Balay } 914e5c89e4eSSatish Balay 915e5c89e4eSSatish Balay /* ---------------------------------------------------------------------------- */ 916e5c89e4eSSatish Balay 917dc37d89fSBarry Smith /*@ 91892f119d6SBarry Smith PetscMallocSetDebug - Set's PETSc memory debugging 919e5c89e4eSSatish Balay 920e5c89e4eSSatish Balay Not Collective 921e5c89e4eSSatish Balay 922d8d19677SJose E. Roman Input Parameters: 92392f119d6SBarry Smith + eachcall - checks the entire heap of allocated memory for issues on each call to PetscMalloc() and PetscFree() 9242d4ee042Sprj- - initializenan - initializes all memory with NaN to catch use of uninitialized floating point arrays 925e5c89e4eSSatish Balay 92692f119d6SBarry Smith Options Database: 92779dccf82SBarry Smith + -malloc_debug <true or false> - turns on or off debugging 92892f119d6SBarry Smith . -malloc_test - turns on all debugging if PETSc was configured with debugging including -malloc_dump, otherwise ignored 92979dccf82SBarry Smith . -malloc_view_threshold t - log only allocations larger than t 93092f119d6SBarry Smith . -malloc_dump <filename> - print a list of all memory that has not been freed 93179dccf82SBarry Smith . -malloc no - (deprecated) same as -malloc_debug no 93279dccf82SBarry Smith - -malloc_log - (deprecated) same as -malloc_view 933e5c89e4eSSatish Balay 93492f119d6SBarry Smith Level: developer 93592f119d6SBarry Smith 93692f119d6SBarry Smith Notes: This is called in PetscInitialize() and should not be called elsewhere 93792f119d6SBarry Smith 938db781477SPatrick Sanan .seealso: `CHKMEMQ()`, `PetscMallocValidate()`, `PetscMallocGetDebug()` 939e5c89e4eSSatish Balay @*/ 9409371c9d4SSatish Balay PetscErrorCode PetscMallocSetDebug(PetscBool eachcall, PetscBool initializenan) { 941e5c89e4eSSatish Balay PetscFunctionBegin; 94208401ef6SPierre Jolivet PetscCheck(PetscTrMalloc != PetscTrMallocDefault, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot call this routine more than once, it can only be called in PetscInitialize()"); 9439566063dSJacob Faibussowitsch PetscCall(PetscMallocSet(PetscTrMallocDefault, PetscTrFreeDefault, PetscTrReallocDefault)); 94492f119d6SBarry Smith 94592f119d6SBarry Smith TRallocated = 0; 94692f119d6SBarry Smith TRfrags = 0; 94792f119d6SBarry Smith TRhead = NULL; 94892f119d6SBarry Smith TRid = 0; 94992f119d6SBarry Smith TRdebugLevel = eachcall; 95092f119d6SBarry Smith TRMaxMem = 0; 95192f119d6SBarry Smith PetscLogMallocMax = 10000; 95292f119d6SBarry Smith PetscLogMalloc = -1; 9532d4ee042Sprj- TRdebugIinitializenan = initializenan; 954e5c89e4eSSatish Balay PetscFunctionReturn(0); 955e5c89e4eSSatish Balay } 9560acecf5bSBarry Smith 957dc37d89fSBarry Smith /*@ 95892f119d6SBarry Smith PetscMallocGetDebug - Indicates what PETSc memory debugging it is doing. 9590acecf5bSBarry Smith 9600acecf5bSBarry Smith Not Collective 9610acecf5bSBarry Smith 96292f119d6SBarry Smith Output Parameters: 96392f119d6SBarry Smith + basic - doing basic debugging 96492f119d6SBarry Smith . eachcall - checks the entire memory heap at each PetscMalloc()/PetscFree() 96579dccf82SBarry Smith - initializenan - initializes memory with NaN 9660acecf5bSBarry Smith 9670acecf5bSBarry Smith Level: intermediate 9680acecf5bSBarry Smith 96992f119d6SBarry Smith Notes: 97079dccf82SBarry Smith By default, the debug version always does some debugging unless you run with -malloc_debug no 9710acecf5bSBarry Smith 972db781477SPatrick Sanan .seealso: `CHKMEMQ()`, `PetscMallocValidate()`, `PetscMallocSetDebug()` 9730acecf5bSBarry Smith @*/ 9749371c9d4SSatish Balay PetscErrorCode PetscMallocGetDebug(PetscBool *basic, PetscBool *eachcall, PetscBool *initializenan) { 9750acecf5bSBarry Smith PetscFunctionBegin; 97679dccf82SBarry Smith if (basic) *basic = (PetscTrMalloc == PetscTrMallocDefault) ? PETSC_TRUE : PETSC_FALSE; 97779dccf82SBarry Smith if (eachcall) *eachcall = TRdebugLevel; 9782d4ee042Sprj- if (initializenan) *initializenan = TRdebugIinitializenan; 9790acecf5bSBarry Smith PetscFunctionReturn(0); 9800acecf5bSBarry Smith } 981608c71bfSMatthew G. Knepley 982608c71bfSMatthew G. Knepley /*@ 983608c71bfSMatthew G. Knepley PetscMallocLogRequestedSizeSet - Whether to log the requested or aligned memory size 984608c71bfSMatthew G. Knepley 985608c71bfSMatthew G. Knepley Not Collective 986608c71bfSMatthew G. Knepley 987608c71bfSMatthew G. Knepley Input Parameter: 988608c71bfSMatthew G. Knepley . flg - PETSC_TRUE to log the requested memory size 989608c71bfSMatthew G. Knepley 990608c71bfSMatthew G. Knepley Options Database: 991608c71bfSMatthew G. Knepley . -malloc_requested_size <bool> - Sets this flag 992608c71bfSMatthew G. Knepley 993608c71bfSMatthew G. Knepley Level: developer 994608c71bfSMatthew G. Knepley 995db781477SPatrick Sanan .seealso: `PetscMallocLogRequestedSizeGet()`, `PetscMallocViewSet()` 996608c71bfSMatthew G. Knepley @*/ 9979371c9d4SSatish Balay PetscErrorCode PetscMallocLogRequestedSizeSet(PetscBool flg) { 998608c71bfSMatthew G. Knepley PetscFunctionBegin; 999608c71bfSMatthew G. Knepley TRrequestedSize = flg; 1000608c71bfSMatthew G. Knepley PetscFunctionReturn(0); 1001608c71bfSMatthew G. Knepley } 1002608c71bfSMatthew G. Knepley 1003608c71bfSMatthew G. Knepley /*@ 1004608c71bfSMatthew G. Knepley PetscMallocLogRequestedSizeGet - Whether to log the requested or aligned memory size 1005608c71bfSMatthew G. Knepley 1006608c71bfSMatthew G. Knepley Not Collective 1007608c71bfSMatthew G. Knepley 1008608c71bfSMatthew G. Knepley Output Parameter: 1009608c71bfSMatthew G. Knepley . flg - PETSC_TRUE if we log the requested memory size 1010608c71bfSMatthew G. Knepley 1011608c71bfSMatthew G. Knepley Level: developer 1012608c71bfSMatthew G. Knepley 1013db781477SPatrick Sanan .seealso: `PetscMallocLogRequestedSizeSetinalSizeSet()`, `PetscMallocViewSet()` 1014608c71bfSMatthew G. Knepley @*/ 10159371c9d4SSatish Balay PetscErrorCode PetscMallocLogRequestedSizeGet(PetscBool *flg) { 1016608c71bfSMatthew G. Knepley PetscFunctionBegin; 1017608c71bfSMatthew G. Knepley *flg = TRrequestedSize; 1018608c71bfSMatthew G. Knepley PetscFunctionReturn(0); 1019608c71bfSMatthew G. Knepley } 1020