xref: /petsc/src/sys/memory/mtr.c (revision 53dcd878f9679251981793a4bf9ec6afefcf7ddd)
1e5c89e4eSSatish Balay /*
22d853995SBarry Smith      Logging of memory usage and some error checking
3e5c89e4eSSatish Balay */
427104ee2SJacob Faibussowitsch #include <petsc/private/petscimpl.h> /*I "petscsys.h" I*/
5665c2dedSJed Brown #include <petscviewer.h>
6e5c89e4eSSatish Balay #if defined(PETSC_HAVE_MALLOC_H)
7e5c89e4eSSatish Balay   #include <malloc.h>
8e5c89e4eSSatish Balay #endif
9e5c89e4eSSatish Balay 
10e5c89e4eSSatish Balay /*
11e5c89e4eSSatish Balay      These are defined in mal.c and ensure that malloced space is PetscScalar aligned
12e5c89e4eSSatish Balay */
13071fcb05SBarry Smith PETSC_EXTERN PetscErrorCode PetscMallocAlign(size_t, PetscBool, int, const char[], const char[], void **);
1495c0884eSLisandro Dalcin PETSC_EXTERN PetscErrorCode PetscFreeAlign(void *, int, const char[], const char[]);
1595c0884eSLisandro Dalcin PETSC_EXTERN PetscErrorCode PetscReallocAlign(size_t, int, const char[], const char[], void **);
16e5c89e4eSSatish Balay 
170700a824SBarry Smith #define CLASSID_VALUE ((PetscClassId)0xf0e0d0c9)
180700a824SBarry Smith #define ALREADY_FREED ((PetscClassId)0x0f0e0d9c)
19e5c89e4eSSatish Balay 
202d853995SBarry Smith /*  this is the header put at the beginning of each PetscTrMallocDefault() for tracking allocated space and checking of allocated space heap */
21e5c89e4eSSatish Balay typedef struct _trSPACE {
22608c71bfSMatthew G. Knepley   size_t       size, rsize; /* Aligned size and requested size */
23e5c89e4eSSatish Balay   int          id;
24e5c89e4eSSatish Balay   int          lineno;
25e5c89e4eSSatish Balay   const char  *filename;
26e5c89e4eSSatish Balay   const char  *functionname;
270700a824SBarry Smith   PetscClassId classid;
28dfb7d7afSStefano Zampini #if defined(PETSC_USE_DEBUG) && !defined(PETSC_HAVE_THREADSAFETY)
29e5c89e4eSSatish Balay   PetscStack stack;
30e5c89e4eSSatish Balay #endif
31e5c89e4eSSatish Balay   struct _trSPACE *next, *prev;
32e5c89e4eSSatish Balay } TRSPACE;
33e5c89e4eSSatish Balay 
342d853995SBarry Smith /* HEADER_BYTES is the number of bytes in a PetscTrMallocDefault() header.
3592f119d6SBarry Smith    It is sizeof(trSPACE) padded to be a multiple of PETSC_MEMALIGN.
3625b53cc9SJed Brown */
37a64a8e02SBarry Smith #define HEADER_BYTES ((sizeof(TRSPACE) + (PETSC_MEMALIGN - 1)) & ~(PETSC_MEMALIGN - 1))
38e5c89e4eSSatish Balay 
3925b53cc9SJed Brown /* This union is used to insure that the block passed to the user retains
4025b53cc9SJed Brown    a minimum alignment of PETSC_MEMALIGN.
4125b53cc9SJed Brown */
429371c9d4SSatish Balay typedef union
439371c9d4SSatish Balay {
44e5c89e4eSSatish Balay   TRSPACE sp;
4525b53cc9SJed Brown   char    v[HEADER_BYTES];
46e5c89e4eSSatish Balay } TrSPACE;
47e5c89e4eSSatish Balay 
48e3ed9ee7SBarry Smith #define MAXTRMAXMEMS 50
49e5c89e4eSSatish Balay static size_t    TRallocated           = 0;
50e5c89e4eSSatish Balay static int       TRfrags               = 0;
51f0ba7cfcSLisandro Dalcin static TRSPACE  *TRhead                = NULL;
52e5c89e4eSSatish Balay static int       TRid                  = 0;
532d853995SBarry Smith static PetscBool TRdebug               = PETSC_FALSE;
542d4ee042Sprj- static PetscBool TRdebugIinitializenan = PETSC_FALSE;
55608c71bfSMatthew G. Knepley static PetscBool TRrequestedSize       = PETSC_FALSE;
56e5c89e4eSSatish Balay static size_t    TRMaxMem              = 0;
57e3ed9ee7SBarry Smith static int       NumTRMaxMems          = 0;
58e3ed9ee7SBarry Smith static size_t    TRMaxMems[MAXTRMAXMEMS];
59e3ed9ee7SBarry Smith static int       TRMaxMemsEvents[MAXTRMAXMEMS];
60e5c89e4eSSatish Balay /*
6192f119d6SBarry Smith       Arrays to log information on mallocs for PetscMallocView()
62e5c89e4eSSatish Balay */
63f0ba7cfcSLisandro Dalcin static int          PetscLogMallocMax       = 10000;
64f0ba7cfcSLisandro Dalcin static int          PetscLogMalloc          = -1;
65574034a9SJed Brown static size_t       PetscLogMallocThreshold = 0;
66e5c89e4eSSatish Balay static size_t      *PetscLogMallocLength;
67efca3c55SSatish Balay static const char **PetscLogMallocFile, **PetscLogMallocFunction;
68608c71bfSMatthew G. Knepley static int          PetscLogMallocTrace          = -1;
69608c71bfSMatthew G. Knepley static size_t       PetscLogMallocTraceThreshold = 0;
70608c71bfSMatthew G. Knepley static PetscViewer  PetscLogMallocTraceViewer    = NULL;
71b022a5c1SBarry Smith 
72e5c89e4eSSatish Balay /*@C
73811af0c4SBarry Smith   PetscMallocValidate - Test the memory for corruption.  This can be called at any time between `PetscInitialize()` and `PetscFinalize()`
74e5c89e4eSSatish Balay 
7592f119d6SBarry Smith   Input Parameters:
76e5c89e4eSSatish Balay + line     - line number where call originated.
77e5c89e4eSSatish Balay . function - name of function calling
78efca3c55SSatish Balay - file     - file where function is
79e5c89e4eSSatish Balay 
8010450e9eSJacob Faibussowitsch   Options Database Keys:
810ed210f4SBarry Smith + -malloc_test  - turns this feature on when PETSc was not configured with `--with-debugging=0`
8292f119d6SBarry Smith - -malloc_debug - turns this feature on anytime
8392f119d6SBarry Smith 
84e5c89e4eSSatish Balay   Level: advanced
85e5c89e4eSSatish Balay 
86e5c89e4eSSatish Balay   Notes:
872d853995SBarry Smith   You should generally use `CHKMEMQ` as a short cut for calling this routine.
882d853995SBarry Smith 
890ed210f4SBarry Smith   Error messages are written to `stdout`.
900ed210f4SBarry Smith 
910ed210f4SBarry 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)
9238548759SBarry Smith 
93e5c89e4eSSatish Balay   No output is generated if there are no problems detected.
94e5c89e4eSSatish Balay 
95aec76313SJacob Faibussowitsch   Fortran Notes:
9620f4b53cSBarry Smith   The Fortran calling sequence is simply `PetscMallocValidate(ierr)`
9720f4b53cSBarry Smith 
980ed210f4SBarry Smith .seealso: `CHKMEMQ`, `PetscMalloc()`, `PetscFree()`, `PetscMallocSetDebug()`
99e5c89e4eSSatish Balay @*/
100d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscMallocValidate(int line, const char function[], const char file[])
101d71ae5a4SJacob Faibussowitsch {
1026c093d5bSvictor   TRSPACE      *head, *lasthead;
103e5c89e4eSSatish Balay   char         *a;
1040700a824SBarry Smith   PetscClassId *nend;
105e5c89e4eSSatish Balay 
1062d853995SBarry Smith   if (!TRdebug) return PETSC_SUCCESS;
1079371c9d4SSatish Balay   head     = TRhead;
1089371c9d4SSatish Balay   lasthead = NULL;
1092cba8197SMatthew G. Knepley   if (head && head->prev) {
1102d853995SBarry Smith     TRdebug = PETSC_FALSE;
1113ba16761SJacob Faibussowitsch     PetscCall((*PetscErrorPrintf)("PetscMallocValidate: error detected in %s() at %s:%d\n", function, file, line));
1123ba16761SJacob Faibussowitsch     PetscCall((*PetscErrorPrintf)("Root memory header %p has invalid back pointer %p\n", (void *)head, (void *)head->prev));
1134ed0ab5bSBarry Smith     return PETSC_ERR_MEMC;
1142cba8197SMatthew G. Knepley   }
115e5c89e4eSSatish Balay   while (head) {
1160700a824SBarry Smith     if (head->classid != CLASSID_VALUE) {
1172d853995SBarry Smith       TRdebug = PETSC_FALSE;
1183ba16761SJacob Faibussowitsch       PetscCall((*PetscErrorPrintf)("PetscMallocValidate: error detected in %s() at %s:%d\n", function, file, line));
1193ba16761SJacob Faibussowitsch       PetscCall((*PetscErrorPrintf)("Memory at address %p is corrupted\n", (void *)head));
1203ba16761SJacob Faibussowitsch       PetscCall((*PetscErrorPrintf)("Probably write before beginning of or past end of array\n"));
121e269983cSBarry Smith       if (lasthead) {
122e269983cSBarry Smith         a = (char *)(((TrSPACE *)head) + 1);
1233ba16761SJacob Faibussowitsch         PetscCall((*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));
124e269983cSBarry Smith       }
125e269983cSBarry Smith       abort();
1264ed0ab5bSBarry Smith       return PETSC_ERR_MEMC;
127e5c89e4eSSatish Balay     }
128e5c89e4eSSatish Balay     a    = (char *)(((TrSPACE *)head) + 1);
1290700a824SBarry Smith     nend = (PetscClassId *)(a + head->size);
1300700a824SBarry Smith     if (*nend != CLASSID_VALUE) {
1312d853995SBarry Smith       TRdebug = PETSC_FALSE;
1323ba16761SJacob Faibussowitsch       PetscCall((*PetscErrorPrintf)("PetscMallocValidate: error detected in %s() at %s:%d\n", function, file, line));
133e5c89e4eSSatish Balay       if (*nend == ALREADY_FREED) {
1343ba16761SJacob Faibussowitsch         PetscCall((*PetscErrorPrintf)("Memory [id=%d(%.0f)] at address %p already freed\n", head->id, (PetscLogDouble)head->size, a));
1354ed0ab5bSBarry Smith         return PETSC_ERR_MEMC;
136e5c89e4eSSatish Balay       } else {
1373ba16761SJacob Faibussowitsch         PetscCall((*PetscErrorPrintf)("Memory [id=%d(%.0f)] at address %p is corrupted (probably write past end of array)\n", head->id, (PetscLogDouble)head->size, a));
1383ba16761SJacob Faibussowitsch         PetscCall((*PetscErrorPrintf)("Memory originally allocated in %s() at %s:%d\n", head->functionname, head->filename, head->lineno));
1394ed0ab5bSBarry Smith         return PETSC_ERR_MEMC;
140e5c89e4eSSatish Balay       }
141e5c89e4eSSatish Balay     }
1422cba8197SMatthew G. Knepley     if (head->prev && head->prev != lasthead) {
1432d853995SBarry Smith       TRdebug = PETSC_FALSE;
1443ba16761SJacob Faibussowitsch       PetscCall((*PetscErrorPrintf)("PetscMallocValidate: error detected in %s() at %s:%d\n", function, file, line));
1453ba16761SJacob Faibussowitsch       PetscCall((*PetscErrorPrintf)("Backpointer %p is invalid, should be %p\n", (void *)head->prev, (void *)lasthead));
1463ba16761SJacob Faibussowitsch       PetscCall((*PetscErrorPrintf)("Previous memory originally allocated in %s() at %s:%d\n", lasthead->functionname, lasthead->filename, lasthead->lineno));
1473ba16761SJacob Faibussowitsch       PetscCall((*PetscErrorPrintf)("Memory originally allocated in %s() at %s:%d\n", head->functionname, head->filename, head->lineno));
1484ed0ab5bSBarry Smith       return PETSC_ERR_MEMC;
1492cba8197SMatthew G. Knepley     }
1506c093d5bSvictor     lasthead = head;
151e5c89e4eSSatish Balay     head     = head->next;
152e5c89e4eSSatish Balay   }
1533ba16761SJacob Faibussowitsch   return PETSC_SUCCESS;
154e5c89e4eSSatish Balay }
155e5c89e4eSSatish Balay 
156e5c89e4eSSatish Balay /*
1572d853995SBarry Smith     PetscTrMallocDefault - Malloc with logging and error checking
158e5c89e4eSSatish Balay 
159e5c89e4eSSatish Balay */
16066976f2fSJacob Faibussowitsch static PetscErrorCode PetscTrMallocDefault(size_t a, PetscBool clear, int lineno, const char function[], const char filename[], void **result)
161d71ae5a4SJacob Faibussowitsch {
162e5c89e4eSSatish Balay   TRSPACE *head;
163e5c89e4eSSatish Balay   char    *inew;
164e5c89e4eSSatish Balay   size_t   nsize;
165e5c89e4eSSatish Balay 
166e5c89e4eSSatish Balay   PetscFunctionBegin;
1679371c9d4SSatish Balay   if (!a) {
1689371c9d4SSatish Balay     *result = NULL;
1693ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
1709371c9d4SSatish Balay   }
171f0ba7cfcSLisandro Dalcin 
17211cc89d2SBarry Smith   PetscCall(PetscMallocValidate(lineno, function, filename));
173e5c89e4eSSatish Balay 
17425b53cc9SJed Brown   nsize = (a + (PETSC_MEMALIGN - 1)) & ~(PETSC_MEMALIGN - 1);
1759566063dSJacob Faibussowitsch   PetscCall(PetscMallocAlign(nsize + sizeof(TrSPACE) + sizeof(PetscClassId), clear, lineno, function, filename, (void **)&inew));
176e3ed9ee7SBarry Smith 
177e5c89e4eSSatish Balay   head = (TRSPACE *)inew;
178e5c89e4eSSatish Balay   inew += sizeof(TrSPACE);
179e5c89e4eSSatish Balay 
180e5c89e4eSSatish Balay   if (TRhead) TRhead->prev = head;
181e5c89e4eSSatish Balay   head->next   = TRhead;
182e5c89e4eSSatish Balay   TRhead       = head;
183f0ba7cfcSLisandro Dalcin   head->prev   = NULL;
184e5c89e4eSSatish Balay   head->size   = nsize;
185608c71bfSMatthew G. Knepley   head->rsize  = a;
186e269983cSBarry Smith   head->id     = TRid++;
187e5c89e4eSSatish Balay   head->lineno = lineno;
188e5c89e4eSSatish Balay 
189e5c89e4eSSatish Balay   head->filename                  = filename;
190e5c89e4eSSatish Balay   head->functionname              = function;
1910700a824SBarry Smith   head->classid                   = CLASSID_VALUE;
1920700a824SBarry Smith   *(PetscClassId *)(inew + nsize) = CLASSID_VALUE;
193e5c89e4eSSatish Balay 
194608c71bfSMatthew G. Knepley   TRallocated += TRrequestedSize ? head->rsize : head->size;
195a297a907SKarl Rupp   if (TRallocated > TRMaxMem) TRMaxMem = TRallocated;
196e3ed9ee7SBarry Smith   if (PetscLogMemory) {
1972d853995SBarry Smith     for (PetscInt i = 0; i < NumTRMaxMems; i++) {
198e3ed9ee7SBarry Smith       if (TRallocated > TRMaxMems[i]) TRMaxMems[i] = TRallocated;
199e3ed9ee7SBarry Smith     }
200e3ed9ee7SBarry Smith   }
201e5c89e4eSSatish Balay   TRfrags++;
202e5c89e4eSSatish Balay 
203dfb7d7afSStefano Zampini #if defined(PETSC_USE_DEBUG) && !defined(PETSC_HAVE_THREADSAFETY)
2049566063dSJacob Faibussowitsch   PetscCall(PetscStackCopy(&petscstack, &head->stack));
2052d853995SBarry Smith   /* fix the line number to where PetscTrMallocDefault() was called, not the PetscFunctionBegin; */
206*53dcd878SStefano Zampini   head->stack.line[PetscMax(head->stack.currentsize - 2, 0)] = lineno;
2072d853995SBarry Smith   head->stack.currentsize--;
20892f119d6SBarry Smith   #if defined(PETSC_USE_REAL_SINGLE) || defined(PETSC_USE_REAL_DOUBLE)
2092d4ee042Sprj-   if (!clear && TRdebugIinitializenan) {
2102d853995SBarry Smith     size_t     n = a / sizeof(PetscReal);
21192f119d6SBarry Smith     PetscReal *s = (PetscReal *)inew;
21292f119d6SBarry Smith       /* from https://www.doc.ic.ac.uk/~eedwards/compsys/float/nan.html */
21392f119d6SBarry Smith     #if defined(PETSC_USE_REAL_SINGLE)
214df282883SBarry Smith     int nas = 0x7F800002;
21592f119d6SBarry Smith     #else
21692f119d6SBarry Smith     PetscInt64 nas = 0x7FF0000000000002;
21792f119d6SBarry Smith     #endif
2182d853995SBarry Smith     for (size_t i = 0; i < n; i++) memcpy(s + i, &nas, sizeof(PetscReal));
21992f119d6SBarry Smith   }
22092f119d6SBarry Smith   #endif
221e5c89e4eSSatish Balay #endif
222e5c89e4eSSatish Balay 
223e5c89e4eSSatish Balay   /*
22492f119d6SBarry Smith          Allow logging of all mallocs made.
22592f119d6SBarry Smith          TODO: Currently this memory is never freed, it should be freed during PetscFinalize()
226e5c89e4eSSatish Balay   */
227574034a9SJed Brown   if (PetscLogMalloc > -1 && PetscLogMalloc < PetscLogMallocMax && a >= PetscLogMallocThreshold) {
228e5c89e4eSSatish Balay     if (!PetscLogMalloc) {
229e5c89e4eSSatish Balay       PetscLogMallocLength = (size_t *)malloc(PetscLogMallocMax * sizeof(size_t));
23028b400f6SJacob Faibussowitsch       PetscCheck(PetscLogMallocLength, PETSC_COMM_SELF, PETSC_ERR_MEM, " ");
231a297a907SKarl Rupp 
232a2ea699eSBarry Smith       PetscLogMallocFile = (const char **)malloc(PetscLogMallocMax * sizeof(char *));
23328b400f6SJacob Faibussowitsch       PetscCheck(PetscLogMallocFile, PETSC_COMM_SELF, PETSC_ERR_MEM, " ");
234a297a907SKarl Rupp 
235a2ea699eSBarry Smith       PetscLogMallocFunction = (const char **)malloc(PetscLogMallocMax * sizeof(char *));
23628b400f6SJacob Faibussowitsch       PetscCheck(PetscLogMallocFunction, PETSC_COMM_SELF, PETSC_ERR_MEM, " ");
237e5c89e4eSSatish Balay     }
238e5c89e4eSSatish Balay     PetscLogMallocLength[PetscLogMalloc]     = nsize;
239e5c89e4eSSatish Balay     PetscLogMallocFile[PetscLogMalloc]       = filename;
240e5c89e4eSSatish Balay     PetscLogMallocFunction[PetscLogMalloc++] = function;
241e5c89e4eSSatish Balay   }
24248a46eb9SPierre Jolivet   if (PetscLogMallocTrace > -1 && a >= PetscLogMallocTraceThreshold) PetscCall(PetscViewerASCIIPrintf(PetscLogMallocTraceViewer, "Alloc %zu %s:%d (%s)\n", a, filename ? filename : "null", lineno, function ? function : "null"));
243e5c89e4eSSatish Balay   *result = (void *)inew;
2443ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
245e5c89e4eSSatish Balay }
246e5c89e4eSSatish Balay 
247e5c89e4eSSatish Balay /*
2482d853995SBarry Smith    PetscTrFreeDefault - Free with logging and error checking
249e5c89e4eSSatish Balay 
250e5c89e4eSSatish Balay */
25166976f2fSJacob Faibussowitsch static PetscErrorCode PetscTrFreeDefault(void *aa, int lineno, const char function[], const char filename[])
252d71ae5a4SJacob Faibussowitsch {
253e5c89e4eSSatish Balay   char         *a = (char *)aa;
254e5c89e4eSSatish Balay   TRSPACE      *head;
255e5c89e4eSSatish Balay   char         *ahead;
256608c71bfSMatthew G. Knepley   size_t        asize;
2570700a824SBarry Smith   PetscClassId *nend;
258e5c89e4eSSatish Balay 
259e5c89e4eSSatish Balay   PetscFunctionBegin;
2603ba16761SJacob Faibussowitsch   if (!a) PetscFunctionReturn(PETSC_SUCCESS);
261e5c89e4eSSatish Balay 
2629566063dSJacob Faibussowitsch   PetscCall(PetscMallocValidate(lineno, function, filename));
263e5c89e4eSSatish Balay 
264e5c89e4eSSatish Balay   ahead = a;
265e5c89e4eSSatish Balay   a     = a - sizeof(TrSPACE);
266e5c89e4eSSatish Balay   head  = (TRSPACE *)a;
267e5c89e4eSSatish Balay 
2680700a824SBarry Smith   if (head->classid != CLASSID_VALUE) {
2692d853995SBarry Smith     TRdebug = PETSC_FALSE;
2703ba16761SJacob Faibussowitsch     PetscCall((*PetscErrorPrintf)("PetscTrFreeDefault() called from %s() at %s:%d\n", function, filename, lineno));
2713ba16761SJacob Faibussowitsch     PetscCall((*PetscErrorPrintf)("Block at address %p is corrupted; cannot free;\nmay be block not allocated with PetscMalloc()\n", a));
272e32f2f54SBarry Smith     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_MEMC, "Bad location or corrupted memory");
273e5c89e4eSSatish Balay   }
2740700a824SBarry Smith   nend = (PetscClassId *)(ahead + head->size);
2750700a824SBarry Smith   if (*nend != CLASSID_VALUE) {
2762d853995SBarry Smith     TRdebug = PETSC_FALSE;
277e5c89e4eSSatish Balay     if (*nend == ALREADY_FREED) {
2783ba16761SJacob Faibussowitsch       PetscCall((*PetscErrorPrintf)("PetscTrFreeDefault() called from %s() at %s:%d\n", function, filename, lineno));
2793ba16761SJacob Faibussowitsch       PetscCall((*PetscErrorPrintf)("Block [id=%d(%.0f)] at address %p was already freed\n", head->id, (PetscLogDouble)head->size, a + sizeof(TrSPACE)));
280e5c89e4eSSatish Balay       if (head->lineno > 0 && head->lineno < 50000 /* sanity check */) {
2813ba16761SJacob Faibussowitsch         PetscCall((*PetscErrorPrintf)("Block freed in %s() at %s:%d\n", head->functionname, head->filename, head->lineno));
282e5c89e4eSSatish Balay       } else {
2833ba16761SJacob Faibussowitsch         PetscCall((*PetscErrorPrintf)("Block allocated in %s() at %s:%d\n", head->functionname, head->filename, -head->lineno));
284e5c89e4eSSatish Balay       }
285e32f2f54SBarry Smith       SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Memory already freed");
286e5c89e4eSSatish Balay     } else {
287e5c89e4eSSatish Balay       /* Damaged tail */
2883ba16761SJacob Faibussowitsch       PetscCall((*PetscErrorPrintf)("PetscTrFreeDefault() called from %s() at %s:%d\n", function, filename, lineno));
2893ba16761SJacob Faibussowitsch       PetscCall((*PetscErrorPrintf)("Block [id=%d(%.0f)] at address %p is corrupted (probably write past end of array)\n", head->id, (PetscLogDouble)head->size, a));
2903ba16761SJacob Faibussowitsch       PetscCall((*PetscErrorPrintf)("Block allocated in %s() at %s:%d\n", head->functionname, head->filename, head->lineno));
291e32f2f54SBarry Smith       SETERRQ(PETSC_COMM_SELF, PETSC_ERR_MEMC, "Corrupted memory");
292e5c89e4eSSatish Balay     }
293e5c89e4eSSatish Balay   }
294608c71bfSMatthew G. Knepley   if (PetscLogMallocTrace > -1 && head->rsize >= PetscLogMallocTraceThreshold) {
2959566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(PetscLogMallocTraceViewer, "Free  %zu %s:%d (%s)\n", head->rsize, filename ? filename : "null", lineno, function ? function : "null"));
296608c71bfSMatthew G. Knepley   }
297e5c89e4eSSatish Balay   *nend = ALREADY_FREED;
298e5c89e4eSSatish Balay   /* Save location where freed.  If we suspect the line number, mark as allocated location */
299608c71bfSMatthew G. Knepley   if (lineno > 0 && lineno < 50000) {
300608c71bfSMatthew G. Knepley     head->lineno       = lineno;
301608c71bfSMatthew G. Knepley     head->filename     = filename;
302e5c89e4eSSatish Balay     head->functionname = function;
303e5c89e4eSSatish Balay   } else {
304e5c89e4eSSatish Balay     head->lineno = -head->lineno;
305e5c89e4eSSatish Balay   }
306608c71bfSMatthew G. Knepley   asize = TRrequestedSize ? head->rsize : head->size;
30708401ef6SPierre Jolivet   PetscCheck(TRallocated >= asize, PETSC_COMM_SELF, PETSC_ERR_MEMC, "TRallocate is smaller than memory just freed");
308608c71bfSMatthew G. Knepley   TRallocated -= asize;
309e5c89e4eSSatish Balay   TRfrags--;
310e5c89e4eSSatish Balay   if (head->prev) head->prev->next = head->next;
311e5c89e4eSSatish Balay   else TRhead = head->next;
312e5c89e4eSSatish Balay 
313e5c89e4eSSatish Balay   if (head->next) head->next->prev = head->prev;
3149566063dSJacob Faibussowitsch   PetscCall(PetscFreeAlign(a, lineno, function, filename));
3153ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
316e5c89e4eSSatish Balay }
317e5c89e4eSSatish Balay 
3183221ece2SMatthew G. Knepley /*
3192d853995SBarry Smith   PetscTrReallocDefault - Realloc with logging and error checking
3203221ece2SMatthew G. Knepley 
3213221ece2SMatthew G. Knepley */
32266976f2fSJacob Faibussowitsch static PetscErrorCode PetscTrReallocDefault(size_t len, int lineno, const char function[], const char filename[], void **result)
323d71ae5a4SJacob Faibussowitsch {
3243221ece2SMatthew G. Knepley   char         *a = (char *)*result;
3253221ece2SMatthew G. Knepley   TRSPACE      *head;
3263221ece2SMatthew G. Knepley   char         *ahead, *inew;
3273221ece2SMatthew G. Knepley   PetscClassId *nend;
3283221ece2SMatthew G. Knepley   size_t        nsize;
3293221ece2SMatthew G. Knepley 
3303221ece2SMatthew G. Knepley   PetscFunctionBegin;
33192f119d6SBarry Smith   /* Realloc requests zero space so just free the current space */
332c22f1541SToby Isaac   if (!len) {
3339566063dSJacob Faibussowitsch     PetscCall(PetscTrFreeDefault(*result, lineno, function, filename));
334c22f1541SToby Isaac     *result = NULL;
3353ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
336c22f1541SToby Isaac   }
337da81f932SPierre Jolivet   /* If the original space was NULL just use the regular malloc() */
338f590eff4SLisandro Dalcin   if (!*result) {
3399566063dSJacob Faibussowitsch     PetscCall(PetscTrMallocDefault(len, PETSC_FALSE, lineno, function, filename, result));
3403ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
341f590eff4SLisandro Dalcin   }
3423221ece2SMatthew G. Knepley 
34311cc89d2SBarry Smith   PetscCall(PetscMallocValidate(lineno, function, filename));
3443221ece2SMatthew G. Knepley 
3453221ece2SMatthew G. Knepley   ahead = a;
3463221ece2SMatthew G. Knepley   a     = a - sizeof(TrSPACE);
3473221ece2SMatthew G. Knepley   head  = (TRSPACE *)a;
3483221ece2SMatthew G. Knepley   inew  = a;
3493221ece2SMatthew G. Knepley 
3503221ece2SMatthew G. Knepley   if (head->classid != CLASSID_VALUE) {
3512d853995SBarry Smith     TRdebug = PETSC_FALSE;
3523ba16761SJacob Faibussowitsch     PetscCall((*PetscErrorPrintf)("PetscTrReallocDefault() called from %s() at %s:%d\n", function, filename, lineno));
3533ba16761SJacob Faibussowitsch     PetscCall((*PetscErrorPrintf)("Block at address %p is corrupted; cannot free;\nmay be block not allocated with PetscMalloc()\n", a));
3543221ece2SMatthew G. Knepley     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_MEMC, "Bad location or corrupted memory");
3553221ece2SMatthew G. Knepley   }
3563221ece2SMatthew G. Knepley   nend = (PetscClassId *)(ahead + head->size);
3573221ece2SMatthew G. Knepley   if (*nend != CLASSID_VALUE) {
3582d853995SBarry Smith     TRdebug = PETSC_FALSE;
3593221ece2SMatthew G. Knepley     if (*nend == ALREADY_FREED) {
3603ba16761SJacob Faibussowitsch       PetscCall((*PetscErrorPrintf)("PetscTrReallocDefault() called from %s() at %s:%d\n", function, filename, lineno));
3613ba16761SJacob Faibussowitsch       PetscCall((*PetscErrorPrintf)("Block [id=%d(%.0f)] at address %p was already freed\n", head->id, (PetscLogDouble)head->size, a + sizeof(TrSPACE)));
3623221ece2SMatthew G. Knepley       if (head->lineno > 0 && head->lineno < 50000 /* sanity check */) {
3633ba16761SJacob Faibussowitsch         PetscCall((*PetscErrorPrintf)("Block freed in %s() at %s:%d\n", head->functionname, head->filename, head->lineno));
3643221ece2SMatthew G. Knepley       } else {
3653ba16761SJacob Faibussowitsch         PetscCall((*PetscErrorPrintf)("Block allocated in %s() at %s:%d\n", head->functionname, head->filename, -head->lineno));
3663221ece2SMatthew G. Knepley       }
3673221ece2SMatthew G. Knepley       SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Memory already freed");
3683221ece2SMatthew G. Knepley     } else {
3693221ece2SMatthew G. Knepley       /* Damaged tail */
3703ba16761SJacob Faibussowitsch       PetscCall((*PetscErrorPrintf)("PetscTrReallocDefault() called from %s() at %s:%d\n", function, filename, lineno));
3713ba16761SJacob Faibussowitsch       PetscCall((*PetscErrorPrintf)("Block [id=%d(%.0f)] at address %p is corrupted (probably write past end of array)\n", head->id, (PetscLogDouble)head->size, a));
3723ba16761SJacob Faibussowitsch       PetscCall((*PetscErrorPrintf)("Block allocated in %s() at %s:%d\n", head->functionname, head->filename, head->lineno));
3733221ece2SMatthew G. Knepley       SETERRQ(PETSC_COMM_SELF, PETSC_ERR_MEMC, "Corrupted memory");
3743221ece2SMatthew G. Knepley     }
3753221ece2SMatthew G. Knepley   }
3763221ece2SMatthew G. Knepley 
37792f119d6SBarry Smith   /* remove original reference to the memory allocated from the PETSc debugging heap */
378608c71bfSMatthew G. Knepley   TRallocated -= TRrequestedSize ? head->rsize : head->size;
3793221ece2SMatthew G. Knepley   TRfrags--;
3803221ece2SMatthew G. Knepley   if (head->prev) head->prev->next = head->next;
3813221ece2SMatthew G. Knepley   else TRhead = head->next;
3823221ece2SMatthew G. Knepley   if (head->next) head->next->prev = head->prev;
3833221ece2SMatthew G. Knepley 
3843221ece2SMatthew G. Knepley   nsize = (len + (PETSC_MEMALIGN - 1)) & ~(PETSC_MEMALIGN - 1);
3859566063dSJacob Faibussowitsch   PetscCall(PetscReallocAlign(nsize + sizeof(TrSPACE) + sizeof(PetscClassId), lineno, function, filename, (void **)&inew));
3863221ece2SMatthew G. Knepley 
3873221ece2SMatthew G. Knepley   head = (TRSPACE *)inew;
3883221ece2SMatthew G. Knepley   inew += sizeof(TrSPACE);
3893221ece2SMatthew G. Knepley 
3903221ece2SMatthew G. Knepley   if (TRhead) TRhead->prev = head;
3913221ece2SMatthew G. Knepley   head->next   = TRhead;
3923221ece2SMatthew G. Knepley   TRhead       = head;
3933221ece2SMatthew G. Knepley   head->prev   = NULL;
3943221ece2SMatthew G. Knepley   head->size   = nsize;
395608c71bfSMatthew G. Knepley   head->rsize  = len;
396e269983cSBarry Smith   head->id     = TRid++;
3973221ece2SMatthew G. Knepley   head->lineno = lineno;
3983221ece2SMatthew G. Knepley 
3993221ece2SMatthew G. Knepley   head->filename                  = filename;
4003221ece2SMatthew G. Knepley   head->functionname              = function;
4013221ece2SMatthew G. Knepley   head->classid                   = CLASSID_VALUE;
4023221ece2SMatthew G. Knepley   *(PetscClassId *)(inew + nsize) = CLASSID_VALUE;
4033221ece2SMatthew G. Knepley 
404608c71bfSMatthew G. Knepley   TRallocated += TRrequestedSize ? head->rsize : head->size;
4053221ece2SMatthew G. Knepley   if (TRallocated > TRMaxMem) TRMaxMem = TRallocated;
406e3ed9ee7SBarry Smith   if (PetscLogMemory) {
4072d853995SBarry Smith     for (PetscInt i = 0; i < NumTRMaxMems; i++) {
408e3ed9ee7SBarry Smith       if (TRallocated > TRMaxMems[i]) TRMaxMems[i] = TRallocated;
409e3ed9ee7SBarry Smith     }
410e3ed9ee7SBarry Smith   }
4113221ece2SMatthew G. Knepley   TRfrags++;
4123221ece2SMatthew G. Knepley 
413dfb7d7afSStefano Zampini #if defined(PETSC_USE_DEBUG) && !defined(PETSC_HAVE_THREADSAFETY)
4149566063dSJacob Faibussowitsch   PetscCall(PetscStackCopy(&petscstack, &head->stack));
4153221ece2SMatthew G. Knepley   /* fix the line number to where the malloc() was called, not the PetscFunctionBegin; */
416*53dcd878SStefano Zampini   head->stack.line[PetscMax(head->stack.currentsize - 2, 0)] = lineno;
4173221ece2SMatthew G. Knepley #endif
4183221ece2SMatthew G. Knepley 
4193221ece2SMatthew G. Knepley   /*
42092f119d6SBarry Smith          Allow logging of all mallocs made. This adds a new entry to the list of allocated memory
42192f119d6SBarry Smith          and does not remove the previous entry to the list hence this memory is "double counted" in PetscMallocView()
4223221ece2SMatthew G. Knepley   */
4233221ece2SMatthew G. Knepley   if (PetscLogMalloc > -1 && PetscLogMalloc < PetscLogMallocMax && len >= PetscLogMallocThreshold) {
4243221ece2SMatthew G. Knepley     if (!PetscLogMalloc) {
4253221ece2SMatthew G. Knepley       PetscLogMallocLength = (size_t *)malloc(PetscLogMallocMax * sizeof(size_t));
42628b400f6SJacob Faibussowitsch       PetscCheck(PetscLogMallocLength, PETSC_COMM_SELF, PETSC_ERR_MEM, " ");
4273221ece2SMatthew G. Knepley 
4283221ece2SMatthew G. Knepley       PetscLogMallocFile = (const char **)malloc(PetscLogMallocMax * sizeof(char *));
42928b400f6SJacob Faibussowitsch       PetscCheck(PetscLogMallocFile, PETSC_COMM_SELF, PETSC_ERR_MEM, " ");
4303221ece2SMatthew G. Knepley 
4313221ece2SMatthew G. Knepley       PetscLogMallocFunction = (const char **)malloc(PetscLogMallocMax * sizeof(char *));
43228b400f6SJacob Faibussowitsch       PetscCheck(PetscLogMallocFunction, PETSC_COMM_SELF, PETSC_ERR_MEM, " ");
4333221ece2SMatthew G. Knepley     }
4343221ece2SMatthew G. Knepley     PetscLogMallocLength[PetscLogMalloc]     = nsize;
4353221ece2SMatthew G. Knepley     PetscLogMallocFile[PetscLogMalloc]       = filename;
4363221ece2SMatthew G. Knepley     PetscLogMallocFunction[PetscLogMalloc++] = function;
4373221ece2SMatthew G. Knepley   }
4383221ece2SMatthew G. Knepley   *result = (void *)inew;
4393ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4403221ece2SMatthew G. Knepley }
4413221ece2SMatthew G. Knepley 
442fe7fb379SMatthew Knepley /*@C
44392f119d6SBarry Smith   PetscMemoryView - Shows the amount of memory currently being used in a communicator.
444e5c89e4eSSatish Balay 
445c3339decSBarry Smith   Collective
446e5c89e4eSSatish Balay 
447d8d19677SJose E. Roman   Input Parameters:
4480ed210f4SBarry Smith + viewer  - the viewer to output the information on
449e5c89e4eSSatish Balay - message - string printed before values
450e5c89e4eSSatish Balay 
451811af0c4SBarry Smith   Options Database Keys:
45292f119d6SBarry Smith + -malloc_debug    - have PETSc track how much memory it has allocated
4530ed210f4SBarry Smith . -log_view_memory - print memory usage per event when `-log_view` is used
4540ed210f4SBarry Smith - -memory_view     - during `PetscFinalize()` have this routine called
4550841954dSBarry Smith 
456e5c89e4eSSatish Balay   Level: intermediate
457e5c89e4eSSatish Balay 
4580ed210f4SBarry Smith .seealso: `PetscMallocDump()`, `PetscMemoryGetCurrentUsage()`, `PetscMemorySetGetMaximumUsage()`, `PetscMallocView()`, `PetscMalloc()`, `PetscFree()`
459e5c89e4eSSatish Balay  @*/
460d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscMemoryView(PetscViewer viewer, const char message[])
461d71ae5a4SJacob Faibussowitsch {
4622d853995SBarry Smith   PetscLogDouble allocated, allocatedmax, resident, residentmax, gallocated, gallocatedmax, gresident, gresidentmax, maxgallocated, maxgallocatedmax;
4632d853995SBarry Smith   PetscLogDouble mingallocated, mingallocatedmax, mingresident, mingresidentmax, maxgresident, maxgresidentmax;
464e5c89e4eSSatish Balay   MPI_Comm       comm;
465e5c89e4eSSatish Balay 
466e5c89e4eSSatish Balay   PetscFunctionBegin;
467e5c89e4eSSatish Balay   if (!viewer) viewer = PETSC_VIEWER_STDOUT_WORLD;
4689566063dSJacob Faibussowitsch   PetscCall(PetscMallocGetCurrentUsage(&allocated));
4699566063dSJacob Faibussowitsch   PetscCall(PetscMallocGetMaximumUsage(&allocatedmax));
4709566063dSJacob Faibussowitsch   PetscCall(PetscMemoryGetCurrentUsage(&resident));
4719566063dSJacob Faibussowitsch   PetscCall(PetscMemoryGetMaximumUsage(&residentmax));
472e5c89e4eSSatish Balay   if (residentmax > 0) residentmax = PetscMax(resident, residentmax);
4739566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)viewer, &comm));
4749566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPrintf(viewer, "%s", message));
475e5c89e4eSSatish Balay   if (resident && residentmax && allocated) {
4769566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&residentmax, &gresidentmax, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm));
4779566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&residentmax, &maxgresidentmax, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm));
4789566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&residentmax, &mingresidentmax, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm));
4799566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "Maximum (over computational time) process memory:        total %5.4e max %5.4e min %5.4e\n", gresidentmax, maxgresidentmax, mingresidentmax));
4809566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&resident, &gresident, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm));
4819566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&resident, &maxgresident, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm));
4829566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&resident, &mingresident, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm));
4839566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "Current process memory:                                  total %5.4e max %5.4e min %5.4e\n", gresident, maxgresident, mingresident));
4849566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&allocatedmax, &gallocatedmax, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm));
4859566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&allocatedmax, &maxgallocatedmax, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm));
4869566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&allocatedmax, &mingallocatedmax, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm));
4879566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "Maximum (over computational time) space PetscMalloc()ed: total %5.4e max %5.4e min %5.4e\n", gallocatedmax, maxgallocatedmax, mingallocatedmax));
4889566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&allocated, &gallocated, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm));
4899566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&allocated, &maxgallocated, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm));
4909566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&allocated, &mingallocated, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm));
4919566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "Current space PetscMalloc()ed:                           total %5.4e max %5.4e min %5.4e\n", gallocated, maxgallocated, mingallocated));
492e5c89e4eSSatish Balay   } else if (resident && residentmax) {
4939566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&residentmax, &gresidentmax, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm));
4949566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&residentmax, &maxgresidentmax, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm));
4959566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&residentmax, &mingresidentmax, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm));
4969566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "Maximum (over computational time) process memory:        total %5.4e max %5.4e min %5.4e\n", gresidentmax, maxgresidentmax, mingresidentmax));
4979566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&resident, &gresident, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm));
4989566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&resident, &maxgresident, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm));
4999566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&resident, &mingresident, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm));
5009566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "Current process memory:                                  total %5.4e max %5.4e min %5.4e\n", gresident, maxgresident, mingresident));
501e5c89e4eSSatish Balay   } else if (resident && allocated) {
5029566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&resident, &gresident, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm));
5039566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&resident, &maxgresident, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm));
5049566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&resident, &mingresident, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm));
5059566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "Current process memory:                                  total %5.4e max %5.4e min %5.4e\n", gresident, maxgresident, mingresident));
5069566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&allocated, &gallocated, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm));
5079566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&allocated, &maxgallocated, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm));
5089566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&allocated, &mingallocated, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm));
5099566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "Current space PetscMalloc()ed:                           total %5.4e max %5.4e min %5.4e\n", gallocated, maxgallocated, mingallocated));
5109566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "Run with -memory_view to get maximum memory usage\n"));
511e5c89e4eSSatish Balay   } else if (allocated) {
5129566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&allocated, &gallocated, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm));
5139566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&allocated, &maxgallocated, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm));
5149566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&allocated, &mingallocated, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm));
5159566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "Current space PetscMalloc()ed:                           total %5.4e max %5.4e min %5.4e\n", gallocated, maxgallocated, mingallocated));
5169566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "Run with -memory_view to get maximum memory usage\n"));
5179566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "OS cannot compute process memory\n"));
518e5c89e4eSSatish Balay   } else {
5199566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "Run with -malloc_debug to get statistics on PetscMalloc() calls\nOS cannot compute process memory\n"));
520e5c89e4eSSatish Balay   }
5219566063dSJacob Faibussowitsch   PetscCall(PetscViewerFlush(viewer));
5223ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
523e5c89e4eSSatish Balay }
524e5c89e4eSSatish Balay 
52546eb3923SBarry Smith /*@
526811af0c4SBarry Smith   PetscMallocGetCurrentUsage - gets the current amount of memory used that was allocated with `PetscMalloc()`
527e5c89e4eSSatish Balay 
528e5c89e4eSSatish Balay   Not Collective
529e5c89e4eSSatish Balay 
5302fe279fdSBarry Smith   Output Parameter:
531e5c89e4eSSatish Balay . space - number of bytes currently allocated
532e5c89e4eSSatish Balay 
533e5c89e4eSSatish Balay   Level: intermediate
534e5c89e4eSSatish Balay 
5352d853995SBarry Smith   Note:
5362d853995SBarry Smith   This only works if `-memory_view` or `-log_view_memory` have been used
5372d853995SBarry Smith 
5380ed210f4SBarry Smith .seealso: `PetscMallocDump()`, `PetscMallocGetMaximumUsage()`, `PetscMemoryGetCurrentUsage()`, `PetscMalloc()`, `PetscFree()`,
539db781477SPatrick Sanan           `PetscMemoryGetMaximumUsage()`
540e5c89e4eSSatish Balay  @*/
541d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscMallocGetCurrentUsage(PetscLogDouble *space)
542d71ae5a4SJacob Faibussowitsch {
543e5c89e4eSSatish Balay   PetscFunctionBegin;
544e5c89e4eSSatish Balay   *space = (PetscLogDouble)TRallocated;
5453ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
546e5c89e4eSSatish Balay }
547e5c89e4eSSatish Balay 
548dc37d89fSBarry Smith /*@
549811af0c4SBarry Smith   PetscMallocGetMaximumUsage - gets the maximum amount of memory used that was obtained with `PetscMalloc()` at any time
550811af0c4SBarry Smith   during this run, the high water mark.
551e5c89e4eSSatish Balay 
552e5c89e4eSSatish Balay   Not Collective
553e5c89e4eSSatish Balay 
5542fe279fdSBarry Smith   Output Parameter:
555e5c89e4eSSatish Balay . space - maximum number of bytes ever allocated at one time
556e5c89e4eSSatish Balay 
557e5c89e4eSSatish Balay   Level: intermediate
558e5c89e4eSSatish Balay 
5592d853995SBarry Smith   Note:
5602d853995SBarry Smith   This only works if `PetscMemorySetGetMaximumUsage()`, `-memory_view`, or `-log_view_memory` have been used
5612d853995SBarry Smith 
5620ed210f4SBarry Smith .seealso: `PetscMallocDump()`, `PetscMallocView()`, `PetscMemoryGetCurrentUsage()`, `PetscMalloc()`, `PetscFree()`,
563db781477SPatrick Sanan           `PetscMallocPushMaximumUsage()`
564e5c89e4eSSatish Balay  @*/
565d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscMallocGetMaximumUsage(PetscLogDouble *space)
566d71ae5a4SJacob Faibussowitsch {
567e5c89e4eSSatish Balay   PetscFunctionBegin;
568e5c89e4eSSatish Balay   *space = (PetscLogDouble)TRMaxMem;
5693ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
570e5c89e4eSSatish Balay }
571e5c89e4eSSatish Balay 
572e3ed9ee7SBarry Smith /*@
573e3ed9ee7SBarry Smith   PetscMallocPushMaximumUsage - Adds another event to collect the maximum memory usage over an event
574e3ed9ee7SBarry Smith 
575e3ed9ee7SBarry Smith   Not Collective
576e3ed9ee7SBarry Smith 
577e3ed9ee7SBarry Smith   Input Parameter:
578e3ed9ee7SBarry Smith . event - an event id; this is just for error checking
579e3ed9ee7SBarry Smith 
580e3ed9ee7SBarry Smith   Level: developer
581e3ed9ee7SBarry Smith 
5822d853995SBarry Smith   Note:
5832d853995SBarry Smith   This only does anything if `PetscMemorySetGetMaximumUsage()`, `-memory_view`, or `-log_view_memory` have been used
5842d853995SBarry Smith 
5850ed210f4SBarry Smith .seealso: `PetscMallocDump()`, `PetscMallocView()`, `PetscMallocGetMaximumUsage()`, `PetscMemoryGetCurrentUsage()`, `PetscMalloc()`, `PetscFree()`,
586db781477SPatrick Sanan           `PetscMallocPopMaximumUsage()`
587e3ed9ee7SBarry Smith  @*/
588d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscMallocPushMaximumUsage(int event)
589d71ae5a4SJacob Faibussowitsch {
590e3ed9ee7SBarry Smith   PetscFunctionBegin;
5912611ad71SToby Isaac   if (event < 0 || ++NumTRMaxMems > MAXTRMAXMEMS) PetscFunctionReturn(PETSC_SUCCESS);
592e3ed9ee7SBarry Smith   TRMaxMems[NumTRMaxMems - 1]       = TRallocated;
593e3ed9ee7SBarry Smith   TRMaxMemsEvents[NumTRMaxMems - 1] = event;
5943ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
595e3ed9ee7SBarry Smith }
596e3ed9ee7SBarry Smith 
597e3ed9ee7SBarry Smith /*@
598e3ed9ee7SBarry Smith   PetscMallocPopMaximumUsage - collect the maximum memory usage over an event
599e3ed9ee7SBarry Smith 
600e3ed9ee7SBarry Smith   Not Collective
601e3ed9ee7SBarry Smith 
602e3ed9ee7SBarry Smith   Input Parameter:
603e3ed9ee7SBarry Smith . event - an event id; this is just for error checking
604e3ed9ee7SBarry Smith 
605e3ed9ee7SBarry Smith   Output Parameter:
606e3ed9ee7SBarry Smith . mu - maximum amount of memory malloced during this event; high water mark relative to the beginning of the event
607e3ed9ee7SBarry Smith 
608e3ed9ee7SBarry Smith   Level: developer
609e3ed9ee7SBarry Smith 
6102d853995SBarry Smith   Note:
6112d853995SBarry Smith   This only does anything if `PetscMemorySetGetMaximumUsage()`, `-memory_view`, or `-log_view_memory` have been used
6122d853995SBarry Smith 
6130ed210f4SBarry Smith .seealso: `PetscMallocDump()`, `PetscMallocView()`, `PetscMallocGetMaximumUsage()`, `PetscMemoryGetCurrentUsage()`, `PetscMalloc()`, `PetscFree()`,
614db781477SPatrick Sanan           `PetscMallocPushMaximumUsage()`
615e3ed9ee7SBarry Smith  @*/
616d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscMallocPopMaximumUsage(int event, PetscLogDouble *mu)
617d71ae5a4SJacob Faibussowitsch {
618e3ed9ee7SBarry Smith   PetscFunctionBegin;
619e3ed9ee7SBarry Smith   *mu = 0;
6202611ad71SToby Isaac   if (event < 0 || NumTRMaxMems-- > MAXTRMAXMEMS) PetscFunctionReturn(PETSC_SUCCESS);
62108401ef6SPierre Jolivet   PetscCheck(TRMaxMemsEvents[NumTRMaxMems] == event, PETSC_COMM_SELF, PETSC_ERR_MEMC, "PetscMallocPush/PopMaximumUsage() are not nested");
622e3ed9ee7SBarry Smith   *mu = TRMaxMems[NumTRMaxMems];
6233ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
624e3ed9ee7SBarry Smith }
625e3ed9ee7SBarry Smith 
626a64a8e02SBarry Smith /*@C
627811af0c4SBarry Smith   PetscMallocGetStack - returns a pointer to the stack for the location in the program a call to `PetscMalloc()` was used to obtain that memory
628a64a8e02SBarry Smith 
6290ed210f4SBarry Smith   Not Collective
630a64a8e02SBarry Smith 
631a64a8e02SBarry Smith   Input Parameter:
632a64a8e02SBarry Smith . ptr - the memory location
633a64a8e02SBarry Smith 
634fd292e60Sprj-   Output Parameter:
635a64a8e02SBarry Smith . stack - the stack indicating where the program allocated this memory
636a64a8e02SBarry Smith 
637a64a8e02SBarry Smith   Level: intermediate
638a64a8e02SBarry Smith 
6392d853995SBarry Smith   Note:
6402d853995SBarry Smith   This only does anything if `-malloc_debug` (or `-malloc_test` if PETSc was configured with debugging) has been used
6412d853995SBarry Smith 
6420ed210f4SBarry Smith .seealso: `PetscMallocGetCurrentUsage()`, `PetscMallocView()`, `PetscMalloc()`, `PetscFree()`
643a64a8e02SBarry Smith @*/
644d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscMallocGetStack(void *ptr, PetscStack **stack)
645d71ae5a4SJacob Faibussowitsch {
646dfb7d7afSStefano Zampini #if defined(PETSC_USE_DEBUG) && !defined(PETSC_HAVE_THREADSAFETY)
647a64a8e02SBarry Smith   TRSPACE *head;
648a64a8e02SBarry Smith 
649a64a8e02SBarry Smith   PetscFunctionBegin;
650a64a8e02SBarry Smith   head   = (TRSPACE *)(((char *)ptr) - HEADER_BYTES);
651a64a8e02SBarry Smith   *stack = &head->stack;
6523ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
65376386721SLisandro Dalcin #else
654f0ba7cfcSLisandro Dalcin   *stack = NULL;
6553ba16761SJacob Faibussowitsch   return PETSC_SUCCESS;
656a64a8e02SBarry Smith #endif
657dfb7d7afSStefano Zampini }
658a64a8e02SBarry Smith 
659e5c89e4eSSatish Balay /*@C
66092f119d6SBarry Smith   PetscMallocDump - Dumps the currently allocated memory blocks to a file. The information
661e5c89e4eSSatish Balay   printed is: size of space (in bytes), address of space, id of space,
662e5c89e4eSSatish Balay   file in which space was allocated, and line number at which it was
663e5c89e4eSSatish Balay   allocated.
664e5c89e4eSSatish Balay 
66592f119d6SBarry Smith   Not Collective
666e5c89e4eSSatish Balay 
667e5c89e4eSSatish Balay   Input Parameter:
6680ed210f4SBarry Smith . fp - file pointer.  If `fp` is `NULL`, `stdout` is assumed.
669e5c89e4eSSatish Balay 
670e5c89e4eSSatish Balay   Options Database Key:
6710ed210f4SBarry Smith . -malloc_dump <optional filename> - Print summary of unfreed memory during call to `PetscFinalize()`, writing to filename if given
672e5c89e4eSSatish Balay 
673e5c89e4eSSatish Balay   Level: intermediate
674e5c89e4eSSatish Balay 
67595452b02SPatrick Sanan   Notes:
676811af0c4SBarry Smith   Uses `MPI_COMM_WORLD` to display rank, because this may be called in `PetscFinalize()` after `PETSC_COMM_WORLD` has been freed.
677e5c89e4eSSatish Balay 
678811af0c4SBarry Smith   When called in `PetscFinalize()` dumps only the allocations that have not been properly freed
67992f119d6SBarry Smith 
680811af0c4SBarry Smith   `PetscMallocView()` prints a list of all memory ever allocated
68192f119d6SBarry Smith 
6822d853995SBarry Smith   This only does anything if `-malloc_debug` (or `-malloc_test` if PETSc was configured with debugging) has been used
6832d853995SBarry Smith 
684aec76313SJacob Faibussowitsch   Fortran Notes:
6850ed210f4SBarry Smith   The calling sequence is `PetscMallocDump`(PetscErrorCode ierr). A `fp` parameter is not supported.
68620f4b53cSBarry Smith 
687aec76313SJacob Faibussowitsch   Developer Notes:
6882d853995SBarry Smith   This should be absorbed into `PetscMallocView()`
6892d853995SBarry Smith 
6900ed210f4SBarry Smith .seealso: `PetscMallocGetCurrentUsage()`, `PetscMallocView()`, `PetscMallocViewSet()`, `PetscMallocValidate()`, `PetscMalloc()`, `PetscFree()`
691e5c89e4eSSatish Balay @*/
692d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscMallocDump(FILE *fp)
693d71ae5a4SJacob Faibussowitsch {
694e5c89e4eSSatish Balay   TRSPACE    *head;
695e3ed9ee7SBarry Smith   size_t      libAlloc = 0;
696e5c89e4eSSatish Balay   PetscMPIInt rank;
697e5c89e4eSSatish Balay 
698e5c89e4eSSatish Balay   PetscFunctionBegin;
6999566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(MPI_COMM_WORLD, &rank));
700da9f1d6bSBarry Smith   if (!fp) fp = PETSC_STDOUT;
701e5c89e4eSSatish Balay   head = TRhead;
702e5c89e4eSSatish Balay   while (head) {
703608c71bfSMatthew G. Knepley     libAlloc += TRrequestedSize ? head->rsize : head->size;
7045486ca60SMatthew G. Knepley     head = head->next;
7055486ca60SMatthew G. Knepley   }
7065486ca60SMatthew G. Knepley   if (TRallocated - libAlloc > 0) fprintf(fp, "[%d]Total space allocated %.0f bytes\n", rank, (PetscLogDouble)TRallocated);
7075486ca60SMatthew G. Knepley   head = TRhead;
7085486ca60SMatthew G. Knepley   while (head) {
7095486ca60SMatthew G. Knepley     PetscBool isLib;
7105486ca60SMatthew G. Knepley 
7119566063dSJacob Faibussowitsch     PetscCall(PetscStrcmp(head->functionname, "PetscDLLibraryOpen", &isLib));
7125486ca60SMatthew G. Knepley     if (!isLib) {
713dfb7d7afSStefano Zampini #if defined(PETSC_USE_DEBUG) && !defined(PETSC_HAVE_THREADSAFETY)
7142d853995SBarry Smith       fprintf(fp, "[%2d] %.0f bytes\n", rank, (PetscLogDouble)(TRrequestedSize ? head->rsize : head->size));
7159566063dSJacob Faibussowitsch       PetscCall(PetscStackPrint(&head->stack, fp));
7162d853995SBarry Smith #else
7172d853995SBarry Smith       fprintf(fp, "[%2d] %.0f bytes %s() at %s:%d\n", rank, (PetscLogDouble)(TRrequestedSize ? head->rsize : head->size), head->functionname, head->filename, head->lineno);
718e5c89e4eSSatish Balay #endif
7195486ca60SMatthew G. Knepley     }
720e5c89e4eSSatish Balay     head = head->next;
721e5c89e4eSSatish Balay   }
7223ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
723e5c89e4eSSatish Balay }
724e5c89e4eSSatish Balay 
725dc37d89fSBarry Smith /*@
726811af0c4SBarry Smith   PetscMallocViewSet - Activates logging of all calls to `PetscMalloc()` with a minimum size to view
727574034a9SJed Brown 
728574034a9SJed Brown   Not Collective
729574034a9SJed Brown 
7304165533cSJose E. Roman   Input Parameter:
7310ed210f4SBarry Smith . logmin - minimum allocation size to log, or `PETSC_DEFAULT` to log all memory allocations
732574034a9SJed Brown 
7330ed210f4SBarry Smith   Options Database Keys:
734811af0c4SBarry Smith + -malloc_view <optional filename> - Activates `PetscMallocView()` in `PetscFinalize()`
7352d853995SBarry Smith . -malloc_view_threshold <min>     - Sets a minimum size if `-malloc_view` is used
7368b254c29SBarry Smith - -log_view_memory                 - view the memory usage also with the -log_view option
737574034a9SJed Brown 
738574034a9SJed Brown   Level: advanced
739574034a9SJed Brown 
7400ed210f4SBarry Smith   Note:
741811af0c4SBarry Smith   Must be called after `PetscMallocSetDebug()`
74292f119d6SBarry Smith 
743aec76313SJacob Faibussowitsch   Developer Notes:
744811af0c4SBarry Smith   Uses `MPI_COMM_WORLD` to determine rank because PETSc communicators may not be available
74592f119d6SBarry Smith 
7460ed210f4SBarry Smith .seealso: `PetscMallocViewGet()`, `PetscMallocDump()`, `PetscMallocView()`, `PetscMallocTraceSet()`, `PetscMallocValidate()`, `PetscMalloc()`, `PetscFree()`
747574034a9SJed Brown @*/
748d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscMallocViewSet(PetscLogDouble logmin)
749d71ae5a4SJacob Faibussowitsch {
750574034a9SJed Brown   PetscFunctionBegin;
75192f119d6SBarry Smith   PetscLogMalloc = 0;
7529566063dSJacob Faibussowitsch   PetscCall(PetscMemorySetGetMaximumUsage());
753574034a9SJed Brown   if (logmin < 0) logmin = 0.0; /* PETSC_DEFAULT or PETSC_DECIDE */
754574034a9SJed Brown   PetscLogMallocThreshold = (size_t)logmin;
7553ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
756574034a9SJed Brown }
757574034a9SJed Brown 
758dc37d89fSBarry Smith /*@
759811af0c4SBarry Smith   PetscMallocViewGet - Determine whether calls to `PetscMalloc()` are being logged
76018a2528dSJed Brown 
76118a2528dSJed Brown   Not Collective
76218a2528dSJed Brown 
76310450e9eSJacob Faibussowitsch   Output Parameter:
764811af0c4SBarry Smith . logging - `PETSC_TRUE` if logging is active
76518a2528dSJed Brown 
76618a2528dSJed Brown   Options Database Key:
767811af0c4SBarry Smith . -malloc_view <optional filename> - Activates `PetscMallocView()`
76818a2528dSJed Brown 
76918a2528dSJed Brown   Level: advanced
77018a2528dSJed Brown 
7710ed210f4SBarry Smith .seealso: `PetscMallocViewSet()`, `PetscMallocDump()`, `PetscMallocView()`, `PetscMallocTraceGet()`, `PetscMalloc()`, `PetscFree()`
77218a2528dSJed Brown @*/
773d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscMallocViewGet(PetscBool *logging)
774d71ae5a4SJacob Faibussowitsch {
77518a2528dSJed Brown   PetscFunctionBegin;
77618a2528dSJed Brown   *logging = (PetscBool)(PetscLogMalloc >= 0);
7773ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
77818a2528dSJed Brown }
77918a2528dSJed Brown 
780608c71bfSMatthew G. Knepley /*@
7812d853995SBarry Smith   PetscMallocTraceSet - Trace all calls to `PetscMalloc()`. That is print each `PetscMalloc()` and `PetscFree()` call to a viewer.
782608c71bfSMatthew G. Knepley 
783608c71bfSMatthew G. Knepley   Not Collective
784608c71bfSMatthew G. Knepley 
7854165533cSJose E. Roman   Input Parameters:
7860ed210f4SBarry Smith + viewer - The viewer to use for tracing, or `NULL` to use `PETSC_VIEWER_STDOUT_SELF`
787608c71bfSMatthew G. Knepley . active - Flag to activate or deactivate tracing
788608c71bfSMatthew G. Knepley - logmin - The smallest memory size that will be logged
789608c71bfSMatthew G. Knepley 
7900ed210f4SBarry Smith   Level: advanced
7910ed210f4SBarry Smith 
792608c71bfSMatthew G. Knepley   Note:
793608c71bfSMatthew G. Knepley   The viewer should not be collective.
794608c71bfSMatthew G. Knepley 
7952d853995SBarry Smith   This only does anything if `-malloc_debug` (or `-malloc_test` if PETSc was configured with debugging) has been used
7962d853995SBarry Smith 
7970ed210f4SBarry Smith .seealso: `PetscMallocTraceGet()`, `PetscMallocViewGet()`, `PetscMallocDump()`, `PetscMallocView()`, `PetscMalloc()`, `PetscFree()`
798608c71bfSMatthew G. Knepley @*/
799d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscMallocTraceSet(PetscViewer viewer, PetscBool active, PetscLogDouble logmin)
800d71ae5a4SJacob Faibussowitsch {
801608c71bfSMatthew G. Knepley   PetscFunctionBegin;
8029371c9d4SSatish Balay   if (!active) {
8039371c9d4SSatish Balay     PetscLogMallocTrace = -1;
8043ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
8059371c9d4SSatish Balay   }
8060ed210f4SBarry Smith   if (!viewer) viewer = PETSC_VIEWER_STDOUT_SELF;
8070ed210f4SBarry Smith   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
8080ed210f4SBarry Smith   PetscLogMallocTraceViewer = viewer;
809608c71bfSMatthew G. Knepley   PetscLogMallocTrace       = 0;
8109566063dSJacob Faibussowitsch   PetscCall(PetscMemorySetGetMaximumUsage());
811608c71bfSMatthew G. Knepley   if (logmin < 0) logmin = 0.0; /* PETSC_DEFAULT or PETSC_DECIDE */
812608c71bfSMatthew G. Knepley   PetscLogMallocTraceThreshold = (size_t)logmin;
8133ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
814608c71bfSMatthew G. Knepley }
815608c71bfSMatthew G. Knepley 
816608c71bfSMatthew G. Knepley /*@
817811af0c4SBarry Smith   PetscMallocTraceGet - Determine whether all calls to `PetscMalloc()` are being traced
818608c71bfSMatthew G. Knepley 
819608c71bfSMatthew G. Knepley   Not Collective
820608c71bfSMatthew G. Knepley 
8214165533cSJose E. Roman   Output Parameter:
822811af0c4SBarry Smith . logging - `PETSC_TRUE` if logging is active
823608c71bfSMatthew G. Knepley 
824608c71bfSMatthew G. Knepley   Options Database Key:
8250ed210f4SBarry Smith . -malloc_view <optional filename> - Activates `PetscMallocView()`
826608c71bfSMatthew G. Knepley 
827608c71bfSMatthew G. Knepley   Level: advanced
828608c71bfSMatthew G. Knepley 
8292d853995SBarry Smith   This only does anything if `-malloc_debug` (or `-malloc_test` if PETSc was configured with debugging) has been used
8302d853995SBarry Smith 
8310ed210f4SBarry Smith .seealso: `PetscMallocTraceSet()`, `PetscMallocViewGet()`, `PetscMallocDump()`, `PetscMallocView()`, `PetscMalloc()`, `PetscFree()`
832608c71bfSMatthew G. Knepley @*/
833d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscMallocTraceGet(PetscBool *logging)
834d71ae5a4SJacob Faibussowitsch {
835608c71bfSMatthew G. Knepley   PetscFunctionBegin;
836608c71bfSMatthew G. Knepley   *logging = (PetscBool)(PetscLogMallocTrace >= 0);
8373ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
838608c71bfSMatthew G. Knepley }
839608c71bfSMatthew G. Knepley 
840e5c89e4eSSatish Balay /*@C
8412d853995SBarry Smith   PetscMallocView - Saves the log of all calls to `PetscMalloc()`; also calls `PetscMemoryGetMaximumUsage()`
842e5c89e4eSSatish Balay 
84392f119d6SBarry Smith   Not Collective
844e5c89e4eSSatish Balay 
845e5c89e4eSSatish Balay   Input Parameter:
8460ed210f4SBarry Smith . fp - file pointer; or `NULL`
847e5c89e4eSSatish Balay 
848e5c89e4eSSatish Balay   Options Database Key:
849811af0c4SBarry Smith . -malloc_view <optional filename> - Activates `PetscMallocView()` in `PetscFinalize()`
850e5c89e4eSSatish Balay 
851e5c89e4eSSatish Balay   Level: advanced
852e5c89e4eSSatish Balay 
85392f119d6SBarry Smith   Notes:
854811af0c4SBarry Smith   `PetscMallocDump()` dumps only the currently unfreed memory, this dumps all memory ever allocated
85592f119d6SBarry Smith 
856811af0c4SBarry Smith   `PetscMemoryView()` gives a brief summary of current memory usage
85792f119d6SBarry Smith 
85820f4b53cSBarry Smith   Fortran Notes:
8590ed210f4SBarry Smith   The calling sequence in Fortran is `PetscMallocView`(integer ierr)
86020f4b53cSBarry Smith 
8610ed210f4SBarry Smith .seealso: `PetscMallocGetCurrentUsage()`, `PetscMallocDump()`, `PetscMallocViewSet()`, `PetscMemoryView()`, `PetscMalloc()`, `PetscFree()`
862e5c89e4eSSatish Balay @*/
863d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscMallocView(FILE *fp)
864d71ae5a4SJacob Faibussowitsch {
8652d853995SBarry Smith   PetscInt       n, *perm;
866e5c89e4eSSatish Balay   size_t        *shortlength;
867c69effb2SJacob Faibussowitsch   int           *shortcount;
86892f119d6SBarry Smith   PetscMPIInt    rank;
869ace3abfcSBarry Smith   PetscBool      match;
870e5c89e4eSSatish Balay   const char   **shortfunction;
871e5c89e4eSSatish Balay   PetscLogDouble rss;
872e5c89e4eSSatish Balay 
873e5c89e4eSSatish Balay   PetscFunctionBegin;
8749566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(MPI_COMM_WORLD, &rank));
875c69effb2SJacob Faibussowitsch   PetscCall(PetscFFlush(fp));
876f56c2debSBarry Smith 
87700045ab3SPierre Jolivet   PetscCheck(PetscLogMalloc >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "PetscMallocView() called without call to PetscMallocViewSet() this is often due to setting the option -malloc_view AFTER PetscInitialize() with PetscOptionsInsert() or PetscOptionsInsertFile()");
878768aa557SSatish Balay 
879da9f1d6bSBarry Smith   if (!fp) fp = PETSC_STDOUT;
8809566063dSJacob Faibussowitsch   PetscCall(PetscMemoryGetMaximumUsage(&rss));
881e5c89e4eSSatish Balay   if (rss) {
88292f119d6SBarry Smith     (void)fprintf(fp, "[%d] Maximum memory PetscMalloc()ed %.0f maximum size of entire process %.0f\n", rank, (PetscLogDouble)TRMaxMem, rss);
883e5c89e4eSSatish Balay   } else {
88492f119d6SBarry Smith     (void)fprintf(fp, "[%d] Maximum memory PetscMalloc()ed %.0f OS cannot compute size of entire process\n", rank, (PetscLogDouble)TRMaxMem);
885e5c89e4eSSatish Balay   }
886b13f2904SStefano Zampini   if (PetscLogMalloc > 0) {
8879371c9d4SSatish Balay     shortcount = (int *)malloc(PetscLogMalloc * sizeof(int));
8889371c9d4SSatish Balay     PetscCheck(shortcount, PETSC_COMM_SELF, PETSC_ERR_MEM, "Out of memory");
8899371c9d4SSatish Balay     shortlength = (size_t *)malloc(PetscLogMalloc * sizeof(size_t));
8909371c9d4SSatish Balay     PetscCheck(shortlength, PETSC_COMM_SELF, PETSC_ERR_MEM, "Out of memory");
8919371c9d4SSatish Balay     shortfunction = (const char **)malloc(PetscLogMalloc * sizeof(char *));
8929371c9d4SSatish Balay     PetscCheck(shortfunction, PETSC_COMM_SELF, PETSC_ERR_MEM, "Out of memory");
8932d853995SBarry Smith     n = 0;
8942d853995SBarry Smith     for (PetscInt i = 0; i < PetscLogMalloc; i++) {
8952d853995SBarry Smith       for (PetscInt j = 0; j < n; j++) {
8969566063dSJacob Faibussowitsch         PetscCall(PetscStrcmp(shortfunction[j], PetscLogMallocFunction[i], &match));
897e5c89e4eSSatish Balay         if (match) {
898e5c89e4eSSatish Balay           shortlength[j] += PetscLogMallocLength[i];
89959ffdab8SBarry Smith           shortcount[j]++;
900e5c89e4eSSatish Balay           goto foundit;
901e5c89e4eSSatish Balay         }
902e5c89e4eSSatish Balay       }
903e5c89e4eSSatish Balay       shortfunction[n] = PetscLogMallocFunction[i];
904e5c89e4eSSatish Balay       shortlength[n]   = PetscLogMallocLength[i];
90559ffdab8SBarry Smith       shortcount[n]    = 1;
906e5c89e4eSSatish Balay       n++;
907e5c89e4eSSatish Balay     foundit:;
908e5c89e4eSSatish Balay     }
909e5c89e4eSSatish Balay 
9109371c9d4SSatish Balay     perm = (PetscInt *)malloc(n * sizeof(PetscInt));
9119371c9d4SSatish Balay     PetscCheck(perm, PETSC_COMM_SELF, PETSC_ERR_MEM, "Out of memory");
9122d853995SBarry Smith     for (PetscInt i = 0; i < n; i++) perm[i] = i;
9139566063dSJacob Faibussowitsch     PetscCall(PetscSortStrWithPermutation(n, (const char **)shortfunction, perm));
914e5c89e4eSSatish Balay 
91592f119d6SBarry Smith     (void)fprintf(fp, "[%d] Memory usage sorted by function\n", rank);
9162d853995SBarry Smith     for (PetscInt i = 0; i < n; i++) (void)fprintf(fp, "[%d] %d %.0f %s()\n", rank, shortcount[perm[i]], (PetscLogDouble)shortlength[perm[i]], shortfunction[perm[i]]);
917e5c89e4eSSatish Balay     free(perm);
918e5c89e4eSSatish Balay     free(shortlength);
91959ffdab8SBarry Smith     free(shortcount);
920e5c89e4eSSatish Balay     free((char **)shortfunction);
921b13f2904SStefano Zampini   }
922c69effb2SJacob Faibussowitsch   PetscCall(PetscFFlush(fp));
9233ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
924e5c89e4eSSatish Balay }
925e5c89e4eSSatish Balay 
926dc37d89fSBarry Smith /*@
92792f119d6SBarry Smith   PetscMallocSetDebug - Set's PETSc memory debugging
928e5c89e4eSSatish Balay 
929e5c89e4eSSatish Balay   Not Collective
930e5c89e4eSSatish Balay 
931d8d19677SJose E. Roman   Input Parameters:
932811af0c4SBarry Smith + eachcall      - checks the entire heap of allocated memory for issues on each call to `PetscMalloc()` and `PetscFree()`, slow
9330ed210f4SBarry Smith - initializenan - initializes all memory with `NaN` to catch use of uninitialized floating point arrays
934e5c89e4eSSatish Balay 
935811af0c4SBarry Smith   Options Database Keys:
93679dccf82SBarry Smith + -malloc_debug <true or false> - turns on or off debugging
9370ed210f4SBarry Smith . -malloc_test                  - turns on all debugging if PETSc was configured with debugging including `-malloc_dump`, otherwise ignored
93879dccf82SBarry Smith . -malloc_view_threshold t      - log only allocations larger than t
93910450e9eSJacob Faibussowitsch - -malloc_dump <filename>       - print a list of all memory that has not been freed, in `PetscFinalize()`
940e5c89e4eSSatish Balay 
94192f119d6SBarry Smith   Level: developer
94292f119d6SBarry Smith 
943811af0c4SBarry Smith   Note:
944811af0c4SBarry Smith   This is called in `PetscInitialize()` and should not be called elsewhere
94592f119d6SBarry Smith 
9462d853995SBarry Smith .seealso: `CHKMEMQ`, `PetscMallocValidate()`, `PetscMallocGetDebug()`, `PetscMalloc()`, `PetscFree()`
947e5c89e4eSSatish Balay @*/
948d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscMallocSetDebug(PetscBool eachcall, PetscBool initializenan)
949d71ae5a4SJacob Faibussowitsch {
950e5c89e4eSSatish Balay   PetscFunctionBegin;
95108401ef6SPierre 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()");
9529566063dSJacob Faibussowitsch   PetscCall(PetscMallocSet(PetscTrMallocDefault, PetscTrFreeDefault, PetscTrReallocDefault));
95392f119d6SBarry Smith 
95492f119d6SBarry Smith   TRallocated           = 0;
95592f119d6SBarry Smith   TRfrags               = 0;
95692f119d6SBarry Smith   TRhead                = NULL;
95792f119d6SBarry Smith   TRid                  = 0;
9582d853995SBarry Smith   TRdebug               = eachcall;
95992f119d6SBarry Smith   TRMaxMem              = 0;
96092f119d6SBarry Smith   PetscLogMallocMax     = 10000;
96192f119d6SBarry Smith   PetscLogMalloc        = -1;
9622d4ee042Sprj-   TRdebugIinitializenan = initializenan;
9633ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
964e5c89e4eSSatish Balay }
9650acecf5bSBarry Smith 
966dc37d89fSBarry Smith /*@
96792f119d6SBarry Smith   PetscMallocGetDebug - Indicates what PETSc memory debugging it is doing.
9680acecf5bSBarry Smith 
9690acecf5bSBarry Smith   Not Collective
9700acecf5bSBarry Smith 
97192f119d6SBarry Smith   Output Parameters:
97292f119d6SBarry Smith + basic         - doing basic debugging
973811af0c4SBarry Smith . eachcall      - checks the entire memory heap at each `PetscMalloc()`/`PetscFree()`
9740ed210f4SBarry Smith - initializenan - initializes memory with `NaN`
9750acecf5bSBarry Smith 
9760acecf5bSBarry Smith   Level: intermediate
9770acecf5bSBarry Smith 
978811af0c4SBarry Smith   Note:
9792d853995SBarry Smith   By default, the debug configuration of PETSc always does some debugging unless you run with `-malloc_debug no`
9800acecf5bSBarry Smith 
9812d853995SBarry Smith .seealso: `CHKMEMQ`, `PetscMallocValidate()`, `PetscMallocSetDebug()`, `PetscMalloc()`, `PetscFree()`
9820acecf5bSBarry Smith @*/
983d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscMallocGetDebug(PetscBool *basic, PetscBool *eachcall, PetscBool *initializenan)
984d71ae5a4SJacob Faibussowitsch {
9850acecf5bSBarry Smith   PetscFunctionBegin;
98679dccf82SBarry Smith   if (basic) *basic = (PetscTrMalloc == PetscTrMallocDefault) ? PETSC_TRUE : PETSC_FALSE;
9872d853995SBarry Smith   if (eachcall) *eachcall = TRdebug;
9882d4ee042Sprj-   if (initializenan) *initializenan = TRdebugIinitializenan;
9893ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9900acecf5bSBarry Smith }
991608c71bfSMatthew G. Knepley 
992608c71bfSMatthew G. Knepley /*@
993608c71bfSMatthew G. Knepley   PetscMallocLogRequestedSizeSet - Whether to log the requested or aligned memory size
994608c71bfSMatthew G. Knepley 
995608c71bfSMatthew G. Knepley   Not Collective
996608c71bfSMatthew G. Knepley 
997608c71bfSMatthew G. Knepley   Input Parameter:
998811af0c4SBarry Smith . flg - `PETSC_TRUE` to log the requested memory size
999608c71bfSMatthew G. Knepley 
1000811af0c4SBarry Smith   Options Database Key:
1001608c71bfSMatthew G. Knepley . -malloc_requested_size <bool> - Sets this flag
1002608c71bfSMatthew G. Knepley 
1003608c71bfSMatthew G. Knepley   Level: developer
1004608c71bfSMatthew G. Knepley 
10050ed210f4SBarry Smith .seealso: `PetscMallocLogRequestedSizeGet()`, `PetscMallocViewSet()`, `PetscMalloc()`, `PetscFree()`
1006608c71bfSMatthew G. Knepley @*/
1007d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscMallocLogRequestedSizeSet(PetscBool flg)
1008d71ae5a4SJacob Faibussowitsch {
1009608c71bfSMatthew G. Knepley   PetscFunctionBegin;
1010608c71bfSMatthew G. Knepley   TRrequestedSize = flg;
10113ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1012608c71bfSMatthew G. Knepley }
1013608c71bfSMatthew G. Knepley 
1014608c71bfSMatthew G. Knepley /*@
1015608c71bfSMatthew G. Knepley   PetscMallocLogRequestedSizeGet - Whether to log the requested or aligned memory size
1016608c71bfSMatthew G. Knepley 
1017608c71bfSMatthew G. Knepley   Not Collective
1018608c71bfSMatthew G. Knepley 
1019608c71bfSMatthew G. Knepley   Output Parameter:
1020811af0c4SBarry Smith . flg - `PETSC_TRUE` if we log the requested memory size
1021608c71bfSMatthew G. Knepley 
1022608c71bfSMatthew G. Knepley   Level: developer
1023608c71bfSMatthew G. Knepley 
10240ed210f4SBarry Smith .seealso: `PetscMallocLogRequestedSizeSet()`, `PetscMallocViewSet()`, `PetscMalloc()`, `PetscFree()`
1025608c71bfSMatthew G. Knepley @*/
1026d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscMallocLogRequestedSizeGet(PetscBool *flg)
1027d71ae5a4SJacob Faibussowitsch {
1028608c71bfSMatthew G. Knepley   PetscFunctionBegin;
1029608c71bfSMatthew G. Knepley   *flg = TRrequestedSize;
10303ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1031608c71bfSMatthew G. Knepley }
1032