xref: /petsc/src/sys/memory/mtr.c (revision 811af0c4b09a35de4306c442f88bd09fdc09897d)
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
74*811af0c4SBarry 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 
84*811af0c4SBarry Smith    Options Database Keys:.
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:
94*811af0c4SBarry 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 
96*811af0c4SBarry Smith     You should generally use `CHKMEMQ` as a short cut for calling this  routine.
97e5c89e4eSSatish Balay 
98*811af0c4SBarry Smith     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:
103*811af0c4SBarry 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 @*/
1079371c9d4SSatish Balay PetscErrorCode PetscMallocValidate(int line, const char function[], const char file[]) {
1086c093d5bSvictor   TRSPACE      *head, *lasthead;
109e5c89e4eSSatish Balay   char         *a;
1100700a824SBarry Smith   PetscClassId *nend;
111e5c89e4eSSatish Balay 
11238548759SBarry Smith   if (!TRdebugLevel) return 0;
1139371c9d4SSatish Balay   head     = TRhead;
1149371c9d4SSatish Balay   lasthead = NULL;
1152cba8197SMatthew G. Knepley   if (head && head->prev) {
116ccd65f63SJunchao Zhang     (*PetscErrorPrintf)("PetscMallocValidate: error detected in %s() at %s:%d\n", function, file, line);
1172cba8197SMatthew G. Knepley     (*PetscErrorPrintf)("Root memory header %p has invalid back pointer %p\n", head, head->prev);
1184ed0ab5bSBarry Smith     return PETSC_ERR_MEMC;
1192cba8197SMatthew G. Knepley   }
120e5c89e4eSSatish Balay   while (head) {
1210700a824SBarry Smith     if (head->classid != CLASSID_VALUE) {
122ccd65f63SJunchao Zhang       (*PetscErrorPrintf)("PetscMallocValidate: error detected in %s() at %s:%d\n", function, file, line);
123e5c89e4eSSatish Balay       (*PetscErrorPrintf)("Memory at address %p is corrupted\n", head);
1244ed0ab5bSBarry Smith       (*PetscErrorPrintf)("Probably write before beginning of or past end of array\n");
125e269983cSBarry Smith       if (lasthead) {
126e269983cSBarry Smith         a = (char *)(((TrSPACE *)head) + 1);
127ccd65f63SJunchao 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);
128e269983cSBarry Smith       }
129e269983cSBarry Smith       abort();
1304ed0ab5bSBarry Smith       return PETSC_ERR_MEMC;
131e5c89e4eSSatish Balay     }
132e5c89e4eSSatish Balay     a    = (char *)(((TrSPACE *)head) + 1);
1330700a824SBarry Smith     nend = (PetscClassId *)(a + head->size);
1340700a824SBarry Smith     if (*nend != CLASSID_VALUE) {
135ccd65f63SJunchao Zhang       (*PetscErrorPrintf)("PetscMallocValidate: error detected in %s() at %s:%d\n", function, file, line);
136e5c89e4eSSatish Balay       if (*nend == ALREADY_FREED) {
137e5c89e4eSSatish Balay         (*PetscErrorPrintf)("Memory [id=%d(%.0f)] at address %p already freed\n", head->id, (PetscLogDouble)head->size, a);
1384ed0ab5bSBarry Smith         return PETSC_ERR_MEMC;
139e5c89e4eSSatish Balay       } else {
140e5c89e4eSSatish Balay         (*PetscErrorPrintf)("Memory [id=%d(%.0f)] at address %p is corrupted (probably write past end of array)\n", head->id, (PetscLogDouble)head->size, a);
141ccd65f63SJunchao Zhang         (*PetscErrorPrintf)("Memory originally allocated in %s() at %s:%d\n", head->functionname, head->filename, head->lineno);
1424ed0ab5bSBarry Smith         return PETSC_ERR_MEMC;
143e5c89e4eSSatish Balay       }
144e5c89e4eSSatish Balay     }
1452cba8197SMatthew G. Knepley     if (head->prev && head->prev != lasthead) {
146ccd65f63SJunchao Zhang       (*PetscErrorPrintf)("PetscMallocValidate: error detected in %s() at %s:%d\n", function, file, line);
1472cba8197SMatthew G. Knepley       (*PetscErrorPrintf)("Backpointer %p is invalid, should be %p\n", head->prev, lasthead);
148ccd65f63SJunchao Zhang       (*PetscErrorPrintf)("Previous memory originally allocated in %s() at %s:%d\n", lasthead->functionname, lasthead->filename, lasthead->lineno);
149ccd65f63SJunchao Zhang       (*PetscErrorPrintf)("Memory originally allocated in %s() at %s:%d\n", head->functionname, head->filename, head->lineno);
1504ed0ab5bSBarry Smith       return PETSC_ERR_MEMC;
1512cba8197SMatthew G. Knepley     }
1526c093d5bSvictor     lasthead = head;
153e5c89e4eSSatish Balay     head     = head->next;
154e5c89e4eSSatish Balay   }
1554ed0ab5bSBarry Smith   return 0;
156e5c89e4eSSatish Balay }
157e5c89e4eSSatish Balay 
158e5c89e4eSSatish Balay /*
159e5c89e4eSSatish Balay     PetscTrMallocDefault - Malloc with tracing.
160e5c89e4eSSatish Balay 
161e5c89e4eSSatish Balay     Input Parameters:
162e5c89e4eSSatish Balay +   a   - number of bytes to allocate
163e5c89e4eSSatish Balay .   lineno - line number where used.  Use __LINE__ for this
164efca3c55SSatish Balay -   filename  - file name where used.  Use __FILE__ for this
165e5c89e4eSSatish Balay 
166e5c89e4eSSatish Balay     Returns:
16792f119d6SBarry Smith     double aligned pointer to requested storage, or null if not  available.
168e5c89e4eSSatish Balay  */
1699371c9d4SSatish Balay PetscErrorCode PetscTrMallocDefault(size_t a, PetscBool clear, int lineno, const char function[], const char filename[], void **result) {
170e5c89e4eSSatish Balay   TRSPACE *head;
171e5c89e4eSSatish Balay   char    *inew;
172e5c89e4eSSatish Balay   size_t   nsize;
173e5c89e4eSSatish Balay 
174e5c89e4eSSatish Balay   PetscFunctionBegin;
175f0ba7cfcSLisandro Dalcin   /* Do not try to handle empty blocks */
1769371c9d4SSatish Balay   if (!a) {
1779371c9d4SSatish Balay     *result = NULL;
1789371c9d4SSatish Balay     PetscFunctionReturn(0);
1799371c9d4SSatish Balay   }
180f0ba7cfcSLisandro Dalcin 
18111cc89d2SBarry Smith   PetscCall(PetscMallocValidate(lineno, function, filename));
182e5c89e4eSSatish Balay 
18325b53cc9SJed Brown   nsize = (a + (PETSC_MEMALIGN - 1)) & ~(PETSC_MEMALIGN - 1);
1849566063dSJacob Faibussowitsch   PetscCall(PetscMallocAlign(nsize + sizeof(TrSPACE) + sizeof(PetscClassId), clear, lineno, function, filename, (void **)&inew));
185e3ed9ee7SBarry Smith 
186e5c89e4eSSatish Balay   head = (TRSPACE *)inew;
187e5c89e4eSSatish Balay   inew += sizeof(TrSPACE);
188e5c89e4eSSatish Balay 
189e5c89e4eSSatish Balay   if (TRhead) TRhead->prev = head;
190e5c89e4eSSatish Balay   head->next   = TRhead;
191e5c89e4eSSatish Balay   TRhead       = head;
192f0ba7cfcSLisandro Dalcin   head->prev   = NULL;
193e5c89e4eSSatish Balay   head->size   = nsize;
194608c71bfSMatthew G. Knepley   head->rsize  = a;
195e269983cSBarry Smith   head->id     = TRid++;
196e5c89e4eSSatish Balay   head->lineno = lineno;
197e5c89e4eSSatish Balay 
198e5c89e4eSSatish Balay   head->filename                  = filename;
199e5c89e4eSSatish Balay   head->functionname              = function;
2000700a824SBarry Smith   head->classid                   = CLASSID_VALUE;
2010700a824SBarry Smith   *(PetscClassId *)(inew + nsize) = CLASSID_VALUE;
202e5c89e4eSSatish Balay 
203608c71bfSMatthew G. Knepley   TRallocated += TRrequestedSize ? head->rsize : head->size;
204a297a907SKarl Rupp   if (TRallocated > TRMaxMem) TRMaxMem = TRallocated;
205e3ed9ee7SBarry Smith   if (PetscLogMemory) {
206e3ed9ee7SBarry Smith     PetscInt i;
207e3ed9ee7SBarry Smith     for (i = 0; i < NumTRMaxMems; i++) {
208e3ed9ee7SBarry Smith       if (TRallocated > TRMaxMems[i]) TRMaxMems[i] = TRallocated;
209e3ed9ee7SBarry Smith     }
210e3ed9ee7SBarry Smith   }
211e5c89e4eSSatish Balay   TRfrags++;
212e5c89e4eSSatish Balay 
2138bf1f09cSShri Abhyankar #if defined(PETSC_USE_DEBUG)
2149566063dSJacob Faibussowitsch   PetscCall(PetscStackCopy(&petscstack, &head->stack));
2152c9581d2SBarry Smith   /* fix the line number to where the malloc() was called, not the PetscFunctionBegin; */
2162c9581d2SBarry Smith   head->stack.line[head->stack.currentsize - 2] = lineno;
21792f119d6SBarry Smith #if defined(PETSC_USE_REAL_SINGLE) || defined(PETSC_USE_REAL_DOUBLE)
2182d4ee042Sprj-   if (!clear && TRdebugIinitializenan) {
21992f119d6SBarry Smith     size_t     i, n = a / sizeof(PetscReal);
22092f119d6SBarry Smith     PetscReal *s = (PetscReal *)inew;
22192f119d6SBarry Smith     /* from https://www.doc.ic.ac.uk/~eedwards/compsys/float/nan.html */
22292f119d6SBarry Smith #if defined(PETSC_USE_REAL_SINGLE)
223df282883SBarry Smith     int nas = 0x7F800002;
22492f119d6SBarry Smith #else
22592f119d6SBarry Smith     PetscInt64 nas = 0x7FF0000000000002;
22692f119d6SBarry Smith #endif
227ad540459SPierre Jolivet     for (i = 0; i < n; i++) memcpy(s + i, &nas, sizeof(PetscReal));
22892f119d6SBarry Smith   }
22992f119d6SBarry Smith #endif
230e5c89e4eSSatish Balay #endif
231e5c89e4eSSatish Balay 
232e5c89e4eSSatish Balay   /*
23392f119d6SBarry Smith          Allow logging of all mallocs made.
23492f119d6SBarry Smith          TODO: Currently this memory is never freed, it should be freed during PetscFinalize()
235e5c89e4eSSatish Balay   */
236574034a9SJed Brown   if (PetscLogMalloc > -1 && PetscLogMalloc < PetscLogMallocMax && a >= PetscLogMallocThreshold) {
237e5c89e4eSSatish Balay     if (!PetscLogMalloc) {
238e5c89e4eSSatish Balay       PetscLogMallocLength = (size_t *)malloc(PetscLogMallocMax * sizeof(size_t));
23928b400f6SJacob Faibussowitsch       PetscCheck(PetscLogMallocLength, PETSC_COMM_SELF, PETSC_ERR_MEM, " ");
240a297a907SKarl Rupp 
241a2ea699eSBarry Smith       PetscLogMallocFile = (const char **)malloc(PetscLogMallocMax * sizeof(char *));
24228b400f6SJacob Faibussowitsch       PetscCheck(PetscLogMallocFile, PETSC_COMM_SELF, PETSC_ERR_MEM, " ");
243a297a907SKarl Rupp 
244a2ea699eSBarry Smith       PetscLogMallocFunction = (const char **)malloc(PetscLogMallocMax * sizeof(char *));
24528b400f6SJacob Faibussowitsch       PetscCheck(PetscLogMallocFunction, PETSC_COMM_SELF, PETSC_ERR_MEM, " ");
246e5c89e4eSSatish Balay     }
247e5c89e4eSSatish Balay     PetscLogMallocLength[PetscLogMalloc]     = nsize;
248e5c89e4eSSatish Balay     PetscLogMallocFile[PetscLogMalloc]       = filename;
249e5c89e4eSSatish Balay     PetscLogMallocFunction[PetscLogMalloc++] = function;
250e5c89e4eSSatish Balay   }
25148a46eb9SPierre Jolivet   if (PetscLogMallocTrace > -1 && a >= PetscLogMallocTraceThreshold) PetscCall(PetscViewerASCIIPrintf(PetscLogMallocTraceViewer, "Alloc %zu %s:%d (%s)\n", a, filename ? filename : "null", lineno, function ? function : "null"));
252e5c89e4eSSatish Balay   *result = (void *)inew;
253e5c89e4eSSatish Balay   PetscFunctionReturn(0);
254e5c89e4eSSatish Balay }
255e5c89e4eSSatish Balay 
256e5c89e4eSSatish Balay /*
257e5c89e4eSSatish Balay    PetscTrFreeDefault - Free with tracing.
258e5c89e4eSSatish Balay 
259e5c89e4eSSatish Balay    Input Parameters:
260e5c89e4eSSatish Balay .   a    - pointer to a block allocated with PetscTrMalloc
261e5c89e4eSSatish Balay .   lineno - line number where used.  Use __LINE__ for this
262608c71bfSMatthew G. Knepley .   filename  - file name where used.  Use __FILE__ for this
263e5c89e4eSSatish Balay  */
2649371c9d4SSatish Balay PetscErrorCode PetscTrFreeDefault(void *aa, int lineno, const char function[], const char filename[]) {
265e5c89e4eSSatish Balay   char         *a = (char *)aa;
266e5c89e4eSSatish Balay   TRSPACE      *head;
267e5c89e4eSSatish Balay   char         *ahead;
268608c71bfSMatthew G. Knepley   size_t        asize;
2690700a824SBarry Smith   PetscClassId *nend;
270e5c89e4eSSatish Balay 
271e5c89e4eSSatish Balay   PetscFunctionBegin;
272e5c89e4eSSatish Balay   /* Do not try to handle empty blocks */
27349d7da52SJed Brown   if (!a) PetscFunctionReturn(0);
274e5c89e4eSSatish Balay 
2759566063dSJacob Faibussowitsch   PetscCall(PetscMallocValidate(lineno, function, filename));
276e5c89e4eSSatish Balay 
277e5c89e4eSSatish Balay   ahead = a;
278e5c89e4eSSatish Balay   a     = a - sizeof(TrSPACE);
279e5c89e4eSSatish Balay   head  = (TRSPACE *)a;
280e5c89e4eSSatish Balay 
2810700a824SBarry Smith   if (head->classid != CLASSID_VALUE) {
282ccd65f63SJunchao Zhang     (*PetscErrorPrintf)("PetscTrFreeDefault() called from %s() at %s:%d\n", function, filename, lineno);
283e5c89e4eSSatish Balay     (*PetscErrorPrintf)("Block at address %p is corrupted; cannot free;\nmay be block not allocated with PetscMalloc()\n", a);
284e32f2f54SBarry Smith     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_MEMC, "Bad location or corrupted memory");
285e5c89e4eSSatish Balay   }
2860700a824SBarry Smith   nend = (PetscClassId *)(ahead + head->size);
2870700a824SBarry Smith   if (*nend != CLASSID_VALUE) {
288e5c89e4eSSatish Balay     if (*nend == ALREADY_FREED) {
289ccd65f63SJunchao Zhang       (*PetscErrorPrintf)("PetscTrFreeDefault() called from %s() at %s:%d\n", function, filename, lineno);
290e5c89e4eSSatish Balay       (*PetscErrorPrintf)("Block [id=%d(%.0f)] at address %p was already freed\n", head->id, (PetscLogDouble)head->size, a + sizeof(TrSPACE));
291e5c89e4eSSatish Balay       if (head->lineno > 0 && head->lineno < 50000 /* sanity check */) {
292ccd65f63SJunchao Zhang         (*PetscErrorPrintf)("Block freed in %s() at %s:%d\n", head->functionname, head->filename, head->lineno);
293e5c89e4eSSatish Balay       } else {
294ccd65f63SJunchao Zhang         (*PetscErrorPrintf)("Block allocated in %s() at %s:%d\n", head->functionname, head->filename, -head->lineno);
295e5c89e4eSSatish Balay       }
296e32f2f54SBarry Smith       SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Memory already freed");
297e5c89e4eSSatish Balay     } else {
298e5c89e4eSSatish Balay       /* Damaged tail */
299ccd65f63SJunchao Zhang       (*PetscErrorPrintf)("PetscTrFreeDefault() called from %s() at %s:%d\n", function, filename, lineno);
300e5c89e4eSSatish Balay       (*PetscErrorPrintf)("Block [id=%d(%.0f)] at address %p is corrupted (probably write past end of array)\n", head->id, (PetscLogDouble)head->size, a);
301ccd65f63SJunchao Zhang       (*PetscErrorPrintf)("Block allocated in %s() at %s:%d\n", head->functionname, head->filename, head->lineno);
302e32f2f54SBarry Smith       SETERRQ(PETSC_COMM_SELF, PETSC_ERR_MEMC, "Corrupted memory");
303e5c89e4eSSatish Balay     }
304e5c89e4eSSatish Balay   }
305608c71bfSMatthew G. Knepley   if (PetscLogMallocTrace > -1 && head->rsize >= PetscLogMallocTraceThreshold) {
3069566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(PetscLogMallocTraceViewer, "Free  %zu %s:%d (%s)\n", head->rsize, filename ? filename : "null", lineno, function ? function : "null"));
307608c71bfSMatthew G. Knepley   }
308e5c89e4eSSatish Balay   /* Mark the location freed */
309e5c89e4eSSatish Balay   *nend = ALREADY_FREED;
310e5c89e4eSSatish Balay   /* Save location where freed.  If we suspect the line number, mark as  allocated location */
311608c71bfSMatthew G. Knepley   if (lineno > 0 && lineno < 50000) {
312608c71bfSMatthew G. Knepley     head->lineno       = lineno;
313608c71bfSMatthew G. Knepley     head->filename     = filename;
314e5c89e4eSSatish Balay     head->functionname = function;
315e5c89e4eSSatish Balay   } else {
316e5c89e4eSSatish Balay     head->lineno = -head->lineno;
317e5c89e4eSSatish Balay   }
318608c71bfSMatthew G. Knepley   asize = TRrequestedSize ? head->rsize : head->size;
31908401ef6SPierre Jolivet   PetscCheck(TRallocated >= asize, PETSC_COMM_SELF, PETSC_ERR_MEMC, "TRallocate is smaller than memory just freed");
320608c71bfSMatthew G. Knepley   TRallocated -= asize;
321e5c89e4eSSatish Balay   TRfrags--;
322e5c89e4eSSatish Balay   if (head->prev) head->prev->next = head->next;
323e5c89e4eSSatish Balay   else TRhead = head->next;
324e5c89e4eSSatish Balay 
325e5c89e4eSSatish Balay   if (head->next) head->next->prev = head->prev;
3269566063dSJacob Faibussowitsch   PetscCall(PetscFreeAlign(a, lineno, function, filename));
327e5c89e4eSSatish Balay   PetscFunctionReturn(0);
328e5c89e4eSSatish Balay }
329e5c89e4eSSatish Balay 
3303221ece2SMatthew G. Knepley /*
3313221ece2SMatthew G. Knepley   PetscTrReallocDefault - Realloc with tracing.
3323221ece2SMatthew G. Knepley 
3333221ece2SMatthew G. Knepley   Input Parameters:
3343221ece2SMatthew G. Knepley + len      - number of bytes to allocate
3353221ece2SMatthew G. Knepley . lineno   - line number where used.  Use __LINE__ for this
3363221ece2SMatthew G. Knepley . filename - file name where used.  Use __FILE__ for this
33792f119d6SBarry Smith - result - original memory
3383221ece2SMatthew G. Knepley 
3393221ece2SMatthew G. Knepley   Output Parameter:
3403221ece2SMatthew G. Knepley . result - double aligned pointer to requested storage, or null if not available.
3413221ece2SMatthew G. Knepley 
3423221ece2SMatthew G. Knepley   Level: developer
3433221ece2SMatthew G. Knepley 
344db781477SPatrick Sanan .seealso: `PetscTrMallocDefault()`, `PetscTrFreeDefault()`
3453221ece2SMatthew G. Knepley */
3469371c9d4SSatish Balay PetscErrorCode PetscTrReallocDefault(size_t len, int lineno, const char function[], const char filename[], void **result) {
3473221ece2SMatthew G. Knepley   char         *a = (char *)*result;
3483221ece2SMatthew G. Knepley   TRSPACE      *head;
3493221ece2SMatthew G. Knepley   char         *ahead, *inew;
3503221ece2SMatthew G. Knepley   PetscClassId *nend;
3513221ece2SMatthew G. Knepley   size_t        nsize;
3523221ece2SMatthew G. Knepley 
3533221ece2SMatthew G. Knepley   PetscFunctionBegin;
35492f119d6SBarry Smith   /* Realloc requests zero space so just free the current space */
355c22f1541SToby Isaac   if (!len) {
3569566063dSJacob Faibussowitsch     PetscCall(PetscTrFreeDefault(*result, lineno, function, filename));
357c22f1541SToby Isaac     *result = NULL;
358c22f1541SToby Isaac     PetscFunctionReturn(0);
359c22f1541SToby Isaac   }
36092f119d6SBarry Smith   /* If the orginal space was NULL just use the regular malloc() */
361f590eff4SLisandro Dalcin   if (!*result) {
3629566063dSJacob Faibussowitsch     PetscCall(PetscTrMallocDefault(len, PETSC_FALSE, lineno, function, filename, result));
363f590eff4SLisandro Dalcin     PetscFunctionReturn(0);
364f590eff4SLisandro Dalcin   }
3653221ece2SMatthew G. Knepley 
36611cc89d2SBarry Smith   PetscCall(PetscMallocValidate(lineno, function, filename));
3673221ece2SMatthew G. Knepley 
3683221ece2SMatthew G. Knepley   ahead = a;
3693221ece2SMatthew G. Knepley   a     = a - sizeof(TrSPACE);
3703221ece2SMatthew G. Knepley   head  = (TRSPACE *)a;
3713221ece2SMatthew G. Knepley   inew  = a;
3723221ece2SMatthew G. Knepley 
3733221ece2SMatthew G. Knepley   if (head->classid != CLASSID_VALUE) {
374ccd65f63SJunchao Zhang     (*PetscErrorPrintf)("PetscTrReallocDefault() called from %s() at %s:%d\n", function, filename, lineno);
3753221ece2SMatthew G. Knepley     (*PetscErrorPrintf)("Block at address %p is corrupted; cannot free;\nmay be block not allocated with PetscMalloc()\n", a);
3763221ece2SMatthew G. Knepley     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_MEMC, "Bad location or corrupted memory");
3773221ece2SMatthew G. Knepley   }
3783221ece2SMatthew G. Knepley   nend = (PetscClassId *)(ahead + head->size);
3793221ece2SMatthew G. Knepley   if (*nend != CLASSID_VALUE) {
3803221ece2SMatthew G. Knepley     if (*nend == ALREADY_FREED) {
381ccd65f63SJunchao Zhang       (*PetscErrorPrintf)("PetscTrReallocDefault() called from %s() at %s:%d\n", function, filename, lineno);
3823221ece2SMatthew G. Knepley       (*PetscErrorPrintf)("Block [id=%d(%.0f)] at address %p was already freed\n", head->id, (PetscLogDouble)head->size, a + sizeof(TrSPACE));
3833221ece2SMatthew G. Knepley       if (head->lineno > 0 && head->lineno < 50000 /* sanity check */) {
384ccd65f63SJunchao Zhang         (*PetscErrorPrintf)("Block freed in %s() at %s:%d\n", head->functionname, head->filename, head->lineno);
3853221ece2SMatthew G. Knepley       } else {
386ccd65f63SJunchao Zhang         (*PetscErrorPrintf)("Block allocated in %s() at %s:%d\n", head->functionname, head->filename, -head->lineno);
3873221ece2SMatthew G. Knepley       }
3883221ece2SMatthew G. Knepley       SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Memory already freed");
3893221ece2SMatthew G. Knepley     } else {
3903221ece2SMatthew G. Knepley       /* Damaged tail */
391ccd65f63SJunchao Zhang       (*PetscErrorPrintf)("PetscTrReallocDefault() called from %s() at %s:%d\n", function, filename, lineno);
3923221ece2SMatthew 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);
393ccd65f63SJunchao Zhang       (*PetscErrorPrintf)("Block allocated in %s() at %s:%d\n", head->functionname, head->filename, head->lineno);
3943221ece2SMatthew G. Knepley       SETERRQ(PETSC_COMM_SELF, PETSC_ERR_MEMC, "Corrupted memory");
3953221ece2SMatthew G. Knepley     }
3963221ece2SMatthew G. Knepley   }
3973221ece2SMatthew G. Knepley 
39892f119d6SBarry Smith   /* remove original reference to the memory allocated from the PETSc debugging heap */
399608c71bfSMatthew G. Knepley   TRallocated -= TRrequestedSize ? head->rsize : head->size;
4003221ece2SMatthew G. Knepley   TRfrags--;
4013221ece2SMatthew G. Knepley   if (head->prev) head->prev->next = head->next;
4023221ece2SMatthew G. Knepley   else TRhead = head->next;
4033221ece2SMatthew G. Knepley   if (head->next) head->next->prev = head->prev;
4043221ece2SMatthew G. Knepley 
4053221ece2SMatthew G. Knepley   nsize = (len + (PETSC_MEMALIGN - 1)) & ~(PETSC_MEMALIGN - 1);
4069566063dSJacob Faibussowitsch   PetscCall(PetscReallocAlign(nsize + sizeof(TrSPACE) + sizeof(PetscClassId), lineno, function, filename, (void **)&inew));
4073221ece2SMatthew G. Knepley 
4083221ece2SMatthew G. Knepley   head = (TRSPACE *)inew;
4093221ece2SMatthew G. Knepley   inew += sizeof(TrSPACE);
4103221ece2SMatthew G. Knepley 
4113221ece2SMatthew G. Knepley   if (TRhead) TRhead->prev = head;
4123221ece2SMatthew G. Knepley   head->next   = TRhead;
4133221ece2SMatthew G. Knepley   TRhead       = head;
4143221ece2SMatthew G. Knepley   head->prev   = NULL;
4153221ece2SMatthew G. Knepley   head->size   = nsize;
416608c71bfSMatthew G. Knepley   head->rsize  = len;
417e269983cSBarry Smith   head->id     = TRid++;
4183221ece2SMatthew G. Knepley   head->lineno = lineno;
4193221ece2SMatthew G. Knepley 
4203221ece2SMatthew G. Knepley   head->filename                  = filename;
4213221ece2SMatthew G. Knepley   head->functionname              = function;
4223221ece2SMatthew G. Knepley   head->classid                   = CLASSID_VALUE;
4233221ece2SMatthew G. Knepley   *(PetscClassId *)(inew + nsize) = CLASSID_VALUE;
4243221ece2SMatthew G. Knepley 
425608c71bfSMatthew G. Knepley   TRallocated += TRrequestedSize ? head->rsize : head->size;
4263221ece2SMatthew G. Knepley   if (TRallocated > TRMaxMem) TRMaxMem = TRallocated;
427e3ed9ee7SBarry Smith   if (PetscLogMemory) {
428e3ed9ee7SBarry Smith     PetscInt i;
429e3ed9ee7SBarry Smith     for (i = 0; i < NumTRMaxMems; i++) {
430e3ed9ee7SBarry Smith       if (TRallocated > TRMaxMems[i]) TRMaxMems[i] = TRallocated;
431e3ed9ee7SBarry Smith     }
432e3ed9ee7SBarry Smith   }
4333221ece2SMatthew G. Knepley   TRfrags++;
4343221ece2SMatthew G. Knepley 
4353221ece2SMatthew G. Knepley #if defined(PETSC_USE_DEBUG)
4369566063dSJacob Faibussowitsch   PetscCall(PetscStackCopy(&petscstack, &head->stack));
4373221ece2SMatthew G. Knepley   /* fix the line number to where the malloc() was called, not the PetscFunctionBegin; */
4383221ece2SMatthew G. Knepley   head->stack.line[head->stack.currentsize - 2] = lineno;
4393221ece2SMatthew G. Knepley #endif
4403221ece2SMatthew G. Knepley 
4413221ece2SMatthew G. Knepley   /*
44292f119d6SBarry Smith          Allow logging of all mallocs made. This adds a new entry to the list of allocated memory
44392f119d6SBarry Smith          and does not remove the previous entry to the list hence this memory is "double counted" in PetscMallocView()
4443221ece2SMatthew G. Knepley   */
4453221ece2SMatthew G. Knepley   if (PetscLogMalloc > -1 && PetscLogMalloc < PetscLogMallocMax && len >= PetscLogMallocThreshold) {
4463221ece2SMatthew G. Knepley     if (!PetscLogMalloc) {
4473221ece2SMatthew G. Knepley       PetscLogMallocLength = (size_t *)malloc(PetscLogMallocMax * sizeof(size_t));
44828b400f6SJacob Faibussowitsch       PetscCheck(PetscLogMallocLength, PETSC_COMM_SELF, PETSC_ERR_MEM, " ");
4493221ece2SMatthew G. Knepley 
4503221ece2SMatthew G. Knepley       PetscLogMallocFile = (const char **)malloc(PetscLogMallocMax * sizeof(char *));
45128b400f6SJacob Faibussowitsch       PetscCheck(PetscLogMallocFile, PETSC_COMM_SELF, PETSC_ERR_MEM, " ");
4523221ece2SMatthew G. Knepley 
4533221ece2SMatthew G. Knepley       PetscLogMallocFunction = (const char **)malloc(PetscLogMallocMax * sizeof(char *));
45428b400f6SJacob Faibussowitsch       PetscCheck(PetscLogMallocFunction, PETSC_COMM_SELF, PETSC_ERR_MEM, " ");
4553221ece2SMatthew G. Knepley     }
4563221ece2SMatthew G. Knepley     PetscLogMallocLength[PetscLogMalloc]     = nsize;
4573221ece2SMatthew G. Knepley     PetscLogMallocFile[PetscLogMalloc]       = filename;
4583221ece2SMatthew G. Knepley     PetscLogMallocFunction[PetscLogMalloc++] = function;
4593221ece2SMatthew G. Knepley   }
4603221ece2SMatthew G. Knepley   *result = (void *)inew;
4613221ece2SMatthew G. Knepley   PetscFunctionReturn(0);
4623221ece2SMatthew G. Knepley }
4633221ece2SMatthew G. Knepley 
464fe7fb379SMatthew Knepley /*@C
46592f119d6SBarry Smith     PetscMemoryView - Shows the amount of memory currently being used in a communicator.
466e5c89e4eSSatish Balay 
467*811af0c4SBarry Smith     Collective on viewer
468e5c89e4eSSatish Balay 
469d8d19677SJose E. Roman     Input Parameters:
470e5c89e4eSSatish Balay +    viewer - the viewer that defines the communicator
471e5c89e4eSSatish Balay -    message - string printed before values
472e5c89e4eSSatish Balay 
473*811af0c4SBarry Smith     Options Database Keys:
47492f119d6SBarry Smith +    -malloc_debug - have PETSc track how much memory it has allocated
475*811af0c4SBarry Smith .    -log_view_memory - print memory usage per event
4760841954dSBarry Smith -    -memory_view - during PetscFinalize() have this routine called
4770841954dSBarry Smith 
478e5c89e4eSSatish Balay     Level: intermediate
479e5c89e4eSSatish Balay 
480db781477SPatrick Sanan .seealso: `PetscMallocDump()`, `PetscMemoryGetCurrentUsage()`, `PetscMemorySetGetMaximumUsage()`, `PetscMallocView()`
481e5c89e4eSSatish Balay  @*/
4829371c9d4SSatish Balay PetscErrorCode PetscMemoryView(PetscViewer viewer, const char message[]) {
4830841954dSBarry Smith   PetscLogDouble allocated, allocatedmax, resident, residentmax, gallocated, gallocatedmax, gresident, gresidentmax, maxgallocated, maxgallocatedmax, maxgresident, maxgresidentmax;
4840841954dSBarry Smith   PetscLogDouble mingallocated, mingallocatedmax, mingresident, mingresidentmax;
485e5c89e4eSSatish Balay   MPI_Comm       comm;
486e5c89e4eSSatish Balay 
487e5c89e4eSSatish Balay   PetscFunctionBegin;
488e5c89e4eSSatish Balay   if (!viewer) viewer = PETSC_VIEWER_STDOUT_WORLD;
4899566063dSJacob Faibussowitsch   PetscCall(PetscMallocGetCurrentUsage(&allocated));
4909566063dSJacob Faibussowitsch   PetscCall(PetscMallocGetMaximumUsage(&allocatedmax));
4919566063dSJacob Faibussowitsch   PetscCall(PetscMemoryGetCurrentUsage(&resident));
4929566063dSJacob Faibussowitsch   PetscCall(PetscMemoryGetMaximumUsage(&residentmax));
493e5c89e4eSSatish Balay   if (residentmax > 0) residentmax = PetscMax(resident, residentmax);
4949566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)viewer, &comm));
4959566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPrintf(viewer, "%s", message));
496e5c89e4eSSatish Balay   if (resident && residentmax && allocated) {
4979566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&residentmax, &gresidentmax, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm));
4989566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&residentmax, &maxgresidentmax, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm));
4999566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&residentmax, &mingresidentmax, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm));
5009566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "Maximum (over computational time) process memory:        total %5.4e max %5.4e min %5.4e\n", gresidentmax, maxgresidentmax, mingresidentmax));
5019566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&resident, &gresident, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm));
5029566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&resident, &maxgresident, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm));
5039566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&resident, &mingresident, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm));
5049566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "Current process memory:                                  total %5.4e max %5.4e min %5.4e\n", gresident, maxgresident, mingresident));
5059566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&allocatedmax, &gallocatedmax, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm));
5069566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&allocatedmax, &maxgallocatedmax, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm));
5079566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&allocatedmax, &mingallocatedmax, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm));
5089566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "Maximum (over computational time) space PetscMalloc()ed: total %5.4e max %5.4e min %5.4e\n", gallocatedmax, maxgallocatedmax, mingallocatedmax));
5099566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&allocated, &gallocated, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm));
5109566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&allocated, &maxgallocated, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm));
5119566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&allocated, &mingallocated, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm));
5129566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "Current space PetscMalloc()ed:                           total %5.4e max %5.4e min %5.4e\n", gallocated, maxgallocated, mingallocated));
513e5c89e4eSSatish Balay   } else if (resident && residentmax) {
5149566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&residentmax, &gresidentmax, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm));
5159566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&residentmax, &maxgresidentmax, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm));
5169566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&residentmax, &mingresidentmax, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm));
5179566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "Maximum (over computational time) process memory:        total %5.4e max %5.4e min %5.4e\n", gresidentmax, maxgresidentmax, mingresidentmax));
5189566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&resident, &gresident, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm));
5199566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&resident, &maxgresident, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm));
5209566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&resident, &mingresident, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm));
5219566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "Current process memory:                                  total %5.4e max %5.4e min %5.4e\n", gresident, maxgresident, mingresident));
522e5c89e4eSSatish Balay   } else if (resident && allocated) {
5239566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&resident, &gresident, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm));
5249566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&resident, &maxgresident, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm));
5259566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&resident, &mingresident, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm));
5269566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "Current process memory:                                  total %5.4e max %5.4e min %5.4e\n", gresident, maxgresident, mingresident));
5279566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&allocated, &gallocated, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm));
5289566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&allocated, &maxgallocated, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm));
5299566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&allocated, &mingallocated, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm));
5309566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "Current space PetscMalloc()ed:                           total %5.4e max %5.4e min %5.4e\n", gallocated, maxgallocated, mingallocated));
5319566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "Run with -memory_view to get maximum memory usage\n"));
532e5c89e4eSSatish Balay   } else if (allocated) {
5339566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&allocated, &gallocated, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm));
5349566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&allocated, &maxgallocated, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm));
5359566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&allocated, &mingallocated, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm));
5369566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "Current space PetscMalloc()ed:                           total %5.4e max %5.4e min %5.4e\n", gallocated, maxgallocated, mingallocated));
5379566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "Run with -memory_view to get maximum memory usage\n"));
5389566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "OS cannot compute process memory\n"));
539e5c89e4eSSatish Balay   } else {
5409566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "Run with -malloc_debug to get statistics on PetscMalloc() calls\nOS cannot compute process memory\n"));
541e5c89e4eSSatish Balay   }
5429566063dSJacob Faibussowitsch   PetscCall(PetscViewerFlush(viewer));
543e5c89e4eSSatish Balay   PetscFunctionReturn(0);
544e5c89e4eSSatish Balay }
545e5c89e4eSSatish Balay 
54646eb3923SBarry Smith /*@
547*811af0c4SBarry Smith     PetscMallocGetCurrentUsage - gets the current amount of memory used that was allocated with `PetscMalloc()`
548e5c89e4eSSatish Balay 
549e5c89e4eSSatish Balay     Not Collective
550e5c89e4eSSatish Balay 
551e5c89e4eSSatish Balay     Output Parameters:
552e5c89e4eSSatish Balay .   space - number of bytes currently allocated
553e5c89e4eSSatish Balay 
554e5c89e4eSSatish Balay     Level: intermediate
555e5c89e4eSSatish Balay 
556db781477SPatrick Sanan .seealso: `PetscMallocDump()`, `PetscMallocGetMaximumUsage()`, `PetscMemoryGetCurrentUsage()`,
557db781477SPatrick Sanan           `PetscMemoryGetMaximumUsage()`
558e5c89e4eSSatish Balay  @*/
5599371c9d4SSatish Balay PetscErrorCode PetscMallocGetCurrentUsage(PetscLogDouble *space) {
560e5c89e4eSSatish Balay   PetscFunctionBegin;
561e5c89e4eSSatish Balay   *space = (PetscLogDouble)TRallocated;
562e5c89e4eSSatish Balay   PetscFunctionReturn(0);
563e5c89e4eSSatish Balay }
564e5c89e4eSSatish Balay 
565dc37d89fSBarry Smith /*@
566*811af0c4SBarry Smith     PetscMallocGetMaximumUsage - gets the maximum amount of memory used that was obtained with `PetscMalloc()` at any time
567*811af0c4SBarry Smith         during this run, the high water mark.
568e5c89e4eSSatish Balay 
569e5c89e4eSSatish Balay     Not Collective
570e5c89e4eSSatish Balay 
571e5c89e4eSSatish Balay     Output Parameters:
572e5c89e4eSSatish Balay .   space - maximum number of bytes ever allocated at one time
573e5c89e4eSSatish Balay 
574e5c89e4eSSatish Balay     Level: intermediate
575e5c89e4eSSatish Balay 
576db781477SPatrick Sanan .seealso: `PetscMallocDump()`, `PetscMallocView()`, `PetscMallocGetMaximumUsage()`, `PetscMemoryGetCurrentUsage()`,
577db781477SPatrick Sanan           `PetscMallocPushMaximumUsage()`
578e5c89e4eSSatish Balay  @*/
5799371c9d4SSatish Balay PetscErrorCode PetscMallocGetMaximumUsage(PetscLogDouble *space) {
580e5c89e4eSSatish Balay   PetscFunctionBegin;
581e5c89e4eSSatish Balay   *space = (PetscLogDouble)TRMaxMem;
582e5c89e4eSSatish Balay   PetscFunctionReturn(0);
583e5c89e4eSSatish Balay }
584e5c89e4eSSatish Balay 
585e3ed9ee7SBarry Smith /*@
586e3ed9ee7SBarry Smith     PetscMallocPushMaximumUsage - Adds another event to collect the maximum memory usage over an event
587e3ed9ee7SBarry Smith 
588e3ed9ee7SBarry Smith     Not Collective
589e3ed9ee7SBarry Smith 
590e3ed9ee7SBarry Smith     Input Parameter:
591e3ed9ee7SBarry Smith .   event - an event id; this is just for error checking
592e3ed9ee7SBarry Smith 
593e3ed9ee7SBarry Smith     Level: developer
594e3ed9ee7SBarry Smith 
595db781477SPatrick Sanan .seealso: `PetscMallocDump()`, `PetscMallocView()`, `PetscMallocGetMaximumUsage()`, `PetscMemoryGetCurrentUsage()`,
596db781477SPatrick Sanan           `PetscMallocPopMaximumUsage()`
597e3ed9ee7SBarry Smith  @*/
5989371c9d4SSatish Balay PetscErrorCode PetscMallocPushMaximumUsage(int event) {
599e3ed9ee7SBarry Smith   PetscFunctionBegin;
600e3ed9ee7SBarry Smith   if (++NumTRMaxMems > MAXTRMAXMEMS) PetscFunctionReturn(0);
601e3ed9ee7SBarry Smith   TRMaxMems[NumTRMaxMems - 1]       = TRallocated;
602e3ed9ee7SBarry Smith   TRMaxMemsEvents[NumTRMaxMems - 1] = event;
603e3ed9ee7SBarry Smith   PetscFunctionReturn(0);
604e3ed9ee7SBarry Smith }
605e3ed9ee7SBarry Smith 
606e3ed9ee7SBarry Smith /*@
607e3ed9ee7SBarry Smith     PetscMallocPopMaximumUsage - collect the maximum memory usage over an event
608e3ed9ee7SBarry Smith 
609e3ed9ee7SBarry Smith     Not Collective
610e3ed9ee7SBarry Smith 
611e3ed9ee7SBarry Smith     Input Parameter:
612e3ed9ee7SBarry Smith .   event - an event id; this is just for error checking
613e3ed9ee7SBarry Smith 
614e3ed9ee7SBarry Smith     Output Parameter:
615e3ed9ee7SBarry Smith .   mu - maximum amount of memory malloced during this event; high water mark relative to the beginning of the event
616e3ed9ee7SBarry Smith 
617e3ed9ee7SBarry Smith     Level: developer
618e3ed9ee7SBarry Smith 
619db781477SPatrick Sanan .seealso: `PetscMallocDump()`, `PetscMallocView()`, `PetscMallocGetMaximumUsage()`, `PetscMemoryGetCurrentUsage()`,
620db781477SPatrick Sanan           `PetscMallocPushMaximumUsage()`
621e3ed9ee7SBarry Smith  @*/
6229371c9d4SSatish Balay PetscErrorCode PetscMallocPopMaximumUsage(int event, PetscLogDouble *mu) {
623e3ed9ee7SBarry Smith   PetscFunctionBegin;
624e3ed9ee7SBarry Smith   *mu = 0;
625e3ed9ee7SBarry Smith   if (NumTRMaxMems-- > MAXTRMAXMEMS) PetscFunctionReturn(0);
62608401ef6SPierre Jolivet   PetscCheck(TRMaxMemsEvents[NumTRMaxMems] == event, PETSC_COMM_SELF, PETSC_ERR_MEMC, "PetscMallocPush/PopMaximumUsage() are not nested");
627e3ed9ee7SBarry Smith   *mu = TRMaxMems[NumTRMaxMems];
628e3ed9ee7SBarry Smith   PetscFunctionReturn(0);
629e3ed9ee7SBarry Smith }
630e3ed9ee7SBarry Smith 
631a64a8e02SBarry Smith #if defined(PETSC_USE_DEBUG)
632a64a8e02SBarry Smith /*@C
633*811af0c4SBarry Smith    PetscMallocGetStack - returns a pointer to the stack for the location in the program a call to `PetscMalloc()` was used to obtain that memory
634a64a8e02SBarry Smith 
635*811af0c4SBarry Smith    Collective on `PETSC_COMM_WORLD`
636a64a8e02SBarry Smith 
637a64a8e02SBarry Smith    Input Parameter:
638a64a8e02SBarry Smith .    ptr - the memory location
639a64a8e02SBarry Smith 
640fd292e60Sprj-    Output Parameter:
641a64a8e02SBarry Smith .    stack - the stack indicating where the program allocated this memory
642a64a8e02SBarry Smith 
643a64a8e02SBarry Smith    Level: intermediate
644a64a8e02SBarry Smith 
645db781477SPatrick Sanan .seealso: `PetscMallocGetCurrentUsage()`, `PetscMallocView()`
646a64a8e02SBarry Smith @*/
6479371c9d4SSatish Balay PetscErrorCode PetscMallocGetStack(void *ptr, PetscStack **stack) {
648a64a8e02SBarry Smith   TRSPACE *head;
649a64a8e02SBarry Smith 
650a64a8e02SBarry Smith   PetscFunctionBegin;
651a64a8e02SBarry Smith   head   = (TRSPACE *)(((char *)ptr) - HEADER_BYTES);
652a64a8e02SBarry Smith   *stack = &head->stack;
653a64a8e02SBarry Smith   PetscFunctionReturn(0);
654a64a8e02SBarry Smith }
65576386721SLisandro Dalcin #else
6569371c9d4SSatish Balay PetscErrorCode PetscMallocGetStack(void *ptr, void **stack) {
65776386721SLisandro Dalcin   PetscFunctionBegin;
658f0ba7cfcSLisandro Dalcin   *stack = NULL;
65976386721SLisandro Dalcin   PetscFunctionReturn(0);
66076386721SLisandro Dalcin }
661a64a8e02SBarry Smith #endif
662a64a8e02SBarry Smith 
663e5c89e4eSSatish Balay /*@C
66492f119d6SBarry Smith    PetscMallocDump - Dumps the currently allocated memory blocks to a file. The information
665e5c89e4eSSatish Balay    printed is: size of space (in bytes), address of space, id of space,
666e5c89e4eSSatish Balay    file in which space was allocated, and line number at which it was
667e5c89e4eSSatish Balay    allocated.
668e5c89e4eSSatish Balay 
66992f119d6SBarry Smith    Not Collective
670e5c89e4eSSatish Balay 
671e5c89e4eSSatish Balay    Input Parameter:
672e5c89e4eSSatish Balay .  fp  - file pointer.  If fp is NULL, stdout is assumed.
673e5c89e4eSSatish Balay 
674e5c89e4eSSatish Balay    Options Database Key:
675*811af0c4SBarry Smith .  -malloc_dump <optional filename> - Dumps unfreed memory during call to `PetscFinalize()`
676e5c89e4eSSatish Balay 
677e5c89e4eSSatish Balay    Level: intermediate
678e5c89e4eSSatish Balay 
679e5c89e4eSSatish Balay    Fortran Note:
680e5c89e4eSSatish Balay    The calling sequence in Fortran is PetscMallocDump(integer ierr)
681e5c89e4eSSatish Balay    The fp defaults to stdout.
682e5c89e4eSSatish Balay 
68395452b02SPatrick Sanan    Notes:
684*811af0c4SBarry Smith      Uses `MPI_COMM_WORLD` to display rank, because this may be called in `PetscFinalize()` after `PETSC_COMM_WORLD` has been freed.
685e5c89e4eSSatish Balay 
686*811af0c4SBarry Smith      When called in `PetscFinalize()` dumps only the allocations that have not been properly freed
68792f119d6SBarry Smith 
688*811af0c4SBarry Smith      `PetscMallocView()` prints a list of all memory ever allocated
68992f119d6SBarry Smith 
690db781477SPatrick Sanan .seealso: `PetscMallocGetCurrentUsage()`, `PetscMallocView()`, `PetscMallocViewSet()`, `PetscMallocValidate()`
691e5c89e4eSSatish Balay @*/
6929371c9d4SSatish Balay PetscErrorCode PetscMallocDump(FILE *fp) {
693e5c89e4eSSatish Balay   TRSPACE    *head;
694e3ed9ee7SBarry Smith   size_t      libAlloc = 0;
695e5c89e4eSSatish Balay   PetscMPIInt rank;
696e5c89e4eSSatish Balay 
697e5c89e4eSSatish Balay   PetscFunctionBegin;
6989566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(MPI_COMM_WORLD, &rank));
699da9f1d6bSBarry Smith   if (!fp) fp = PETSC_STDOUT;
700e5c89e4eSSatish Balay   head = TRhead;
701e5c89e4eSSatish Balay   while (head) {
702608c71bfSMatthew G. Knepley     libAlloc += TRrequestedSize ? head->rsize : head->size;
7035486ca60SMatthew G. Knepley     head = head->next;
7045486ca60SMatthew G. Knepley   }
7055486ca60SMatthew G. Knepley   if (TRallocated - libAlloc > 0) fprintf(fp, "[%d]Total space allocated %.0f bytes\n", rank, (PetscLogDouble)TRallocated);
7065486ca60SMatthew G. Knepley   head = TRhead;
7075486ca60SMatthew G. Knepley   while (head) {
7085486ca60SMatthew G. Knepley     PetscBool isLib;
7095486ca60SMatthew G. Knepley 
7109566063dSJacob Faibussowitsch     PetscCall(PetscStrcmp(head->functionname, "PetscDLLibraryOpen", &isLib));
7115486ca60SMatthew G. Knepley     if (!isLib) {
712ccd65f63SJunchao Zhang       fprintf(fp, "[%2d] %.0f bytes %s() at %s:%d\n", rank, (PetscLogDouble)(TRrequestedSize ? head->rsize : head->size), head->functionname, head->filename, head->lineno);
7138bf1f09cSShri Abhyankar #if defined(PETSC_USE_DEBUG)
7149566063dSJacob Faibussowitsch       PetscCall(PetscStackPrint(&head->stack, fp));
715e5c89e4eSSatish Balay #endif
7165486ca60SMatthew G. Knepley     }
717e5c89e4eSSatish Balay     head = head->next;
718e5c89e4eSSatish Balay   }
719e5c89e4eSSatish Balay   PetscFunctionReturn(0);
720e5c89e4eSSatish Balay }
721e5c89e4eSSatish Balay 
722dc37d89fSBarry Smith /*@
723*811af0c4SBarry Smith     PetscMallocViewSet - Activates logging of all calls to `PetscMalloc()` with a minimum size to view
724574034a9SJed Brown 
725574034a9SJed Brown     Not Collective
726574034a9SJed Brown 
7274165533cSJose E. Roman     Input Parameter:
728*811af0c4SBarry Smith .   logmin - minimum allocation size to log, or `PETSC_DEFAULT`
729574034a9SJed Brown 
730574034a9SJed Brown     Options Database Key:
731*811af0c4SBarry Smith +  -malloc_view <optional filename> - Activates `PetscMallocView()` in `PetscFinalize()`
7328b254c29SBarry Smith .  -malloc_view_threshold <min> - Sets a minimum size if -malloc_view is used
7338b254c29SBarry Smith -  -log_view_memory - view the memory usage also with the -log_view option
734574034a9SJed Brown 
735574034a9SJed Brown     Level: advanced
736574034a9SJed Brown 
737*811af0c4SBarry Smith     Notes:
738*811af0c4SBarry Smith     Must be called after `PetscMallocSetDebug()`
73992f119d6SBarry Smith 
740*811af0c4SBarry Smith     Uses `MPI_COMM_WORLD` to determine rank because PETSc communicators may not be available
74192f119d6SBarry Smith 
742db781477SPatrick Sanan .seealso: `PetscMallocDump()`, `PetscMallocView()`, `PetscMallocViewSet()`, `PetscMallocTraceSet()`, `PetscMallocValidate()`
743574034a9SJed Brown @*/
7449371c9d4SSatish Balay PetscErrorCode PetscMallocViewSet(PetscLogDouble logmin) {
745574034a9SJed Brown   PetscFunctionBegin;
74692f119d6SBarry Smith   PetscLogMalloc = 0;
7479566063dSJacob Faibussowitsch   PetscCall(PetscMemorySetGetMaximumUsage());
748574034a9SJed Brown   if (logmin < 0) logmin = 0.0; /* PETSC_DEFAULT or PETSC_DECIDE */
749574034a9SJed Brown   PetscLogMallocThreshold = (size_t)logmin;
750574034a9SJed Brown   PetscFunctionReturn(0);
751574034a9SJed Brown }
752574034a9SJed Brown 
753dc37d89fSBarry Smith /*@
754*811af0c4SBarry Smith     PetscMallocViewGet - Determine whether calls to `PetscMalloc()` are being logged
75518a2528dSJed Brown 
75618a2528dSJed Brown     Not Collective
75718a2528dSJed Brown 
7584165533cSJose E. Roman     Output Parameter
759*811af0c4SBarry Smith .   logging - `PETSC_TRUE` if logging is active
76018a2528dSJed Brown 
76118a2528dSJed Brown     Options Database Key:
762*811af0c4SBarry Smith .  -malloc_view <optional filename> - Activates `PetscMallocView()`
76318a2528dSJed Brown 
76418a2528dSJed Brown     Level: advanced
76518a2528dSJed Brown 
766db781477SPatrick Sanan .seealso: `PetscMallocDump()`, `PetscMallocView()`, `PetscMallocTraceGet()`
76718a2528dSJed Brown @*/
7689371c9d4SSatish Balay PetscErrorCode PetscMallocViewGet(PetscBool *logging) {
76918a2528dSJed Brown   PetscFunctionBegin;
77018a2528dSJed Brown   *logging = (PetscBool)(PetscLogMalloc >= 0);
77118a2528dSJed Brown   PetscFunctionReturn(0);
77218a2528dSJed Brown }
77318a2528dSJed Brown 
774608c71bfSMatthew G. Knepley /*@
775*811af0c4SBarry Smith   PetscMallocTraceSet - Trace all calls to `PetscMalloc()`
776608c71bfSMatthew G. Knepley 
777608c71bfSMatthew G. Knepley   Not Collective
778608c71bfSMatthew G. Knepley 
7794165533cSJose E. Roman   Input Parameters:
780608c71bfSMatthew G. Knepley + viewer - The viewer to use for tracing, or NULL to use stdout
781608c71bfSMatthew G. Knepley . active - Flag to activate or deactivate tracing
782608c71bfSMatthew G. Knepley - logmin - The smallest memory size that will be logged
783608c71bfSMatthew G. Knepley 
784608c71bfSMatthew G. Knepley   Note:
785608c71bfSMatthew G. Knepley   The viewer should not be collective.
786608c71bfSMatthew G. Knepley 
787608c71bfSMatthew G. Knepley   Level: advanced
788608c71bfSMatthew G. Knepley 
789db781477SPatrick Sanan .seealso: `PetscMallocTraceGet()`, `PetscMallocViewGet()`, `PetscMallocDump()`, `PetscMallocView()`
790608c71bfSMatthew G. Knepley @*/
7919371c9d4SSatish Balay PetscErrorCode PetscMallocTraceSet(PetscViewer viewer, PetscBool active, PetscLogDouble logmin) {
792608c71bfSMatthew G. Knepley   PetscFunctionBegin;
7939371c9d4SSatish Balay   if (!active) {
7949371c9d4SSatish Balay     PetscLogMallocTrace = -1;
7959371c9d4SSatish Balay     PetscFunctionReturn(0);
7969371c9d4SSatish Balay   }
797608c71bfSMatthew G. Knepley   PetscLogMallocTraceViewer = !viewer ? PETSC_VIEWER_STDOUT_SELF : viewer;
798608c71bfSMatthew G. Knepley   PetscLogMallocTrace       = 0;
7999566063dSJacob Faibussowitsch   PetscCall(PetscMemorySetGetMaximumUsage());
800608c71bfSMatthew G. Knepley   if (logmin < 0) logmin = 0.0; /* PETSC_DEFAULT or PETSC_DECIDE */
801608c71bfSMatthew G. Knepley   PetscLogMallocTraceThreshold = (size_t)logmin;
802608c71bfSMatthew G. Knepley   PetscFunctionReturn(0);
803608c71bfSMatthew G. Knepley }
804608c71bfSMatthew G. Knepley 
805608c71bfSMatthew G. Knepley /*@
806*811af0c4SBarry Smith   PetscMallocTraceGet - Determine whether all calls to `PetscMalloc()` are being traced
807608c71bfSMatthew G. Knepley 
808608c71bfSMatthew G. Knepley   Not Collective
809608c71bfSMatthew G. Knepley 
8104165533cSJose E. Roman   Output Parameter:
811*811af0c4SBarry Smith . logging - `PETSC_TRUE` if logging is active
812608c71bfSMatthew G. Knepley 
813608c71bfSMatthew G. Knepley   Options Database Key:
814608c71bfSMatthew G. Knepley . -malloc_view <optional filename> - Activates PetscMallocView()
815608c71bfSMatthew G. Knepley 
816608c71bfSMatthew G. Knepley   Level: advanced
817608c71bfSMatthew G. Knepley 
818db781477SPatrick Sanan .seealso: `PetscMallocTraceSet()`, `PetscMallocViewGet()`, `PetscMallocDump()`, `PetscMallocView()`
819608c71bfSMatthew G. Knepley @*/
8209371c9d4SSatish Balay PetscErrorCode PetscMallocTraceGet(PetscBool *logging) {
821608c71bfSMatthew G. Knepley   PetscFunctionBegin;
822608c71bfSMatthew G. Knepley   *logging = (PetscBool)(PetscLogMallocTrace >= 0);
823608c71bfSMatthew G. Knepley   PetscFunctionReturn(0);
824608c71bfSMatthew G. Knepley }
825608c71bfSMatthew G. Knepley 
826e5c89e4eSSatish Balay /*@C
827*811af0c4SBarry Smith     PetscMallocView - Saves the log of all calls to `PetscMalloc()`; also calls
828*811af0c4SBarry Smith        `PetscMemoryGetMaximumUsage()`
829e5c89e4eSSatish Balay 
83092f119d6SBarry Smith     Not Collective
831e5c89e4eSSatish Balay 
832e5c89e4eSSatish Balay     Input Parameter:
8330298fd71SBarry Smith .   fp - file pointer; or NULL
834e5c89e4eSSatish Balay 
835e5c89e4eSSatish Balay     Options Database Key:
836*811af0c4SBarry Smith .  -malloc_view <optional filename> - Activates `PetscMallocView()` in `PetscFinalize()`
837e5c89e4eSSatish Balay 
838e5c89e4eSSatish Balay     Level: advanced
839e5c89e4eSSatish Balay 
840e5c89e4eSSatish Balay    Fortran Note:
84192f119d6SBarry Smith    The calling sequence in Fortran is PetscMallocView(integer ierr)
842e5c89e4eSSatish Balay    The fp defaults to stdout.
843e5c89e4eSSatish Balay 
84492f119d6SBarry Smith    Notes:
845*811af0c4SBarry Smith      `PetscMallocDump()` dumps only the currently unfreed memory, this dumps all memory ever allocated
84692f119d6SBarry Smith 
847*811af0c4SBarry Smith      `PetscMemoryView()` gives a brief summary of current memory usage
84892f119d6SBarry Smith 
849db781477SPatrick Sanan .seealso: `PetscMallocGetCurrentUsage()`, `PetscMallocDump()`, `PetscMallocViewSet()`, `PetscMemoryView()`
850e5c89e4eSSatish Balay @*/
8519371c9d4SSatish Balay PetscErrorCode PetscMallocView(FILE *fp) {
85292f119d6SBarry Smith   PetscInt       i, j, n, *perm;
853e5c89e4eSSatish Balay   size_t        *shortlength;
854f56c2debSBarry Smith   int           *shortcount, err;
85592f119d6SBarry Smith   PetscMPIInt    rank;
856ace3abfcSBarry Smith   PetscBool      match;
857e5c89e4eSSatish Balay   const char   **shortfunction;
858e5c89e4eSSatish Balay   PetscLogDouble rss;
859e5c89e4eSSatish Balay 
860e5c89e4eSSatish Balay   PetscFunctionBegin;
8619566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(MPI_COMM_WORLD, &rank));
862f56c2debSBarry Smith   err = fflush(fp);
86328b400f6SJacob Faibussowitsch   PetscCheck(!err, PETSC_COMM_SELF, PETSC_ERR_SYS, "fflush() failed on file");
864f56c2debSBarry Smith 
86508401ef6SPierre 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()");
866768aa557SSatish Balay 
867da9f1d6bSBarry Smith   if (!fp) fp = PETSC_STDOUT;
8689566063dSJacob Faibussowitsch   PetscCall(PetscMemoryGetMaximumUsage(&rss));
869e5c89e4eSSatish Balay   if (rss) {
87092f119d6SBarry Smith     (void)fprintf(fp, "[%d] Maximum memory PetscMalloc()ed %.0f maximum size of entire process %.0f\n", rank, (PetscLogDouble)TRMaxMem, rss);
871e5c89e4eSSatish Balay   } else {
87292f119d6SBarry Smith     (void)fprintf(fp, "[%d] Maximum memory PetscMalloc()ed %.0f OS cannot compute size of entire process\n", rank, (PetscLogDouble)TRMaxMem);
873e5c89e4eSSatish Balay   }
8749371c9d4SSatish Balay   shortcount = (int *)malloc(PetscLogMalloc * sizeof(int));
8759371c9d4SSatish Balay   PetscCheck(shortcount, PETSC_COMM_SELF, PETSC_ERR_MEM, "Out of memory");
8769371c9d4SSatish Balay   shortlength = (size_t *)malloc(PetscLogMalloc * sizeof(size_t));
8779371c9d4SSatish Balay   PetscCheck(shortlength, PETSC_COMM_SELF, PETSC_ERR_MEM, "Out of memory");
8789371c9d4SSatish Balay   shortfunction = (const char **)malloc(PetscLogMalloc * sizeof(char *));
8799371c9d4SSatish Balay   PetscCheck(shortfunction, PETSC_COMM_SELF, PETSC_ERR_MEM, "Out of memory");
88097b9d747SJed Brown   for (i = 0, n = 0; i < PetscLogMalloc; i++) {
881e5c89e4eSSatish Balay     for (j = 0; j < n; j++) {
8829566063dSJacob Faibussowitsch       PetscCall(PetscStrcmp(shortfunction[j], PetscLogMallocFunction[i], &match));
883e5c89e4eSSatish Balay       if (match) {
884e5c89e4eSSatish Balay         shortlength[j] += PetscLogMallocLength[i];
88559ffdab8SBarry Smith         shortcount[j]++;
886e5c89e4eSSatish Balay         goto foundit;
887e5c89e4eSSatish Balay       }
888e5c89e4eSSatish Balay     }
889e5c89e4eSSatish Balay     shortfunction[n] = PetscLogMallocFunction[i];
890e5c89e4eSSatish Balay     shortlength[n]   = PetscLogMallocLength[i];
89159ffdab8SBarry Smith     shortcount[n]    = 1;
892e5c89e4eSSatish Balay     n++;
893e5c89e4eSSatish Balay   foundit:;
894e5c89e4eSSatish Balay   }
895e5c89e4eSSatish Balay 
8969371c9d4SSatish Balay   perm = (PetscInt *)malloc(n * sizeof(PetscInt));
8979371c9d4SSatish Balay   PetscCheck(perm, PETSC_COMM_SELF, PETSC_ERR_MEM, "Out of memory");
898e5c89e4eSSatish Balay   for (i = 0; i < n; i++) perm[i] = i;
8999566063dSJacob Faibussowitsch   PetscCall(PetscSortStrWithPermutation(n, (const char **)shortfunction, perm));
900e5c89e4eSSatish Balay 
90192f119d6SBarry Smith   (void)fprintf(fp, "[%d] Memory usage sorted by function\n", rank);
902ad540459SPierre Jolivet   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]]);
903e5c89e4eSSatish Balay   free(perm);
904e5c89e4eSSatish Balay   free(shortlength);
90559ffdab8SBarry Smith   free(shortcount);
906e5c89e4eSSatish Balay   free((char **)shortfunction);
907f56c2debSBarry Smith   err = fflush(fp);
90828b400f6SJacob Faibussowitsch   PetscCheck(!err, PETSC_COMM_SELF, PETSC_ERR_SYS, "fflush() failed on file");
909e5c89e4eSSatish Balay   PetscFunctionReturn(0);
910e5c89e4eSSatish Balay }
911e5c89e4eSSatish Balay 
912e5c89e4eSSatish Balay /* ---------------------------------------------------------------------------- */
913e5c89e4eSSatish Balay 
914dc37d89fSBarry Smith /*@
91592f119d6SBarry Smith     PetscMallocSetDebug - Set's PETSc memory debugging
916e5c89e4eSSatish Balay 
917e5c89e4eSSatish Balay     Not Collective
918e5c89e4eSSatish Balay 
919d8d19677SJose E. Roman     Input Parameters:
920*811af0c4SBarry Smith +   eachcall - checks the entire heap of allocated memory for issues on each call to `PetscMalloc()` and `PetscFree()`, slow
9212d4ee042Sprj- -   initializenan - initializes all memory with NaN to catch use of uninitialized floating point arrays
922e5c89e4eSSatish Balay 
923*811af0c4SBarry Smith     Options Database Keys:
92479dccf82SBarry Smith +   -malloc_debug <true or false> - turns on or off debugging
92592f119d6SBarry Smith .   -malloc_test - turns on all debugging if PETSc was configured with debugging including -malloc_dump, otherwise ignored
92679dccf82SBarry Smith .   -malloc_view_threshold t - log only allocations larger than t
92792f119d6SBarry Smith .   -malloc_dump <filename> - print a list of all memory that has not been freed
92879dccf82SBarry Smith .   -malloc no - (deprecated) same as -malloc_debug no
92979dccf82SBarry Smith -   -malloc_log - (deprecated) same as -malloc_view
930e5c89e4eSSatish Balay 
93192f119d6SBarry Smith    Level: developer
93292f119d6SBarry Smith 
933*811af0c4SBarry Smith     Note:
934*811af0c4SBarry Smith     This is called in `PetscInitialize()` and should not be called elsewhere
93592f119d6SBarry Smith 
936db781477SPatrick Sanan .seealso: `CHKMEMQ()`, `PetscMallocValidate()`, `PetscMallocGetDebug()`
937e5c89e4eSSatish Balay @*/
9389371c9d4SSatish Balay PetscErrorCode PetscMallocSetDebug(PetscBool eachcall, PetscBool initializenan) {
939e5c89e4eSSatish Balay   PetscFunctionBegin;
94008401ef6SPierre 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()");
9419566063dSJacob Faibussowitsch   PetscCall(PetscMallocSet(PetscTrMallocDefault, PetscTrFreeDefault, PetscTrReallocDefault));
94292f119d6SBarry Smith 
94392f119d6SBarry Smith   TRallocated           = 0;
94492f119d6SBarry Smith   TRfrags               = 0;
94592f119d6SBarry Smith   TRhead                = NULL;
94692f119d6SBarry Smith   TRid                  = 0;
94792f119d6SBarry Smith   TRdebugLevel          = eachcall;
94892f119d6SBarry Smith   TRMaxMem              = 0;
94992f119d6SBarry Smith   PetscLogMallocMax     = 10000;
95092f119d6SBarry Smith   PetscLogMalloc        = -1;
9512d4ee042Sprj-   TRdebugIinitializenan = initializenan;
952e5c89e4eSSatish Balay   PetscFunctionReturn(0);
953e5c89e4eSSatish Balay }
9540acecf5bSBarry Smith 
955dc37d89fSBarry Smith /*@
95692f119d6SBarry Smith     PetscMallocGetDebug - Indicates what PETSc memory debugging it is doing.
9570acecf5bSBarry Smith 
9580acecf5bSBarry Smith     Not Collective
9590acecf5bSBarry Smith 
96092f119d6SBarry Smith     Output Parameters:
96192f119d6SBarry Smith +    basic - doing basic debugging
962*811af0c4SBarry Smith .    eachcall - checks the entire memory heap at each `PetscMalloc()`/`PetscFree()`
96379dccf82SBarry Smith -    initializenan - initializes memory with NaN
9640acecf5bSBarry Smith 
9650acecf5bSBarry Smith    Level: intermediate
9660acecf5bSBarry Smith 
967*811af0c4SBarry Smith    Note:
96879dccf82SBarry Smith      By default, the debug version always does some debugging unless you run with -malloc_debug no
9690acecf5bSBarry Smith 
970db781477SPatrick Sanan .seealso: `CHKMEMQ()`, `PetscMallocValidate()`, `PetscMallocSetDebug()`
9710acecf5bSBarry Smith @*/
9729371c9d4SSatish Balay PetscErrorCode PetscMallocGetDebug(PetscBool *basic, PetscBool *eachcall, PetscBool *initializenan) {
9730acecf5bSBarry Smith   PetscFunctionBegin;
97479dccf82SBarry Smith   if (basic) *basic = (PetscTrMalloc == PetscTrMallocDefault) ? PETSC_TRUE : PETSC_FALSE;
97579dccf82SBarry Smith   if (eachcall) *eachcall = TRdebugLevel;
9762d4ee042Sprj-   if (initializenan) *initializenan = TRdebugIinitializenan;
9770acecf5bSBarry Smith   PetscFunctionReturn(0);
9780acecf5bSBarry Smith }
979608c71bfSMatthew G. Knepley 
980608c71bfSMatthew G. Knepley /*@
981608c71bfSMatthew G. Knepley   PetscMallocLogRequestedSizeSet - Whether to log the requested or aligned memory size
982608c71bfSMatthew G. Knepley 
983608c71bfSMatthew G. Knepley   Not Collective
984608c71bfSMatthew G. Knepley 
985608c71bfSMatthew G. Knepley   Input Parameter:
986*811af0c4SBarry Smith . flg - `PETSC_TRUE` to log the requested memory size
987608c71bfSMatthew G. Knepley 
988*811af0c4SBarry Smith   Options Database Key:
989608c71bfSMatthew G. Knepley . -malloc_requested_size <bool> - Sets this flag
990608c71bfSMatthew G. Knepley 
991608c71bfSMatthew G. Knepley   Level: developer
992608c71bfSMatthew G. Knepley 
993db781477SPatrick Sanan .seealso: `PetscMallocLogRequestedSizeGet()`, `PetscMallocViewSet()`
994608c71bfSMatthew G. Knepley @*/
9959371c9d4SSatish Balay PetscErrorCode PetscMallocLogRequestedSizeSet(PetscBool flg) {
996608c71bfSMatthew G. Knepley   PetscFunctionBegin;
997608c71bfSMatthew G. Knepley   TRrequestedSize = flg;
998608c71bfSMatthew G. Knepley   PetscFunctionReturn(0);
999608c71bfSMatthew G. Knepley }
1000608c71bfSMatthew G. Knepley 
1001608c71bfSMatthew G. Knepley /*@
1002608c71bfSMatthew G. Knepley   PetscMallocLogRequestedSizeGet - Whether to log the requested or aligned memory size
1003608c71bfSMatthew G. Knepley 
1004608c71bfSMatthew G. Knepley   Not Collective
1005608c71bfSMatthew G. Knepley 
1006608c71bfSMatthew G. Knepley   Output Parameter:
1007*811af0c4SBarry Smith . flg - `PETSC_TRUE` if we log the requested memory size
1008608c71bfSMatthew G. Knepley 
1009608c71bfSMatthew G. Knepley   Level: developer
1010608c71bfSMatthew G. Knepley 
1011db781477SPatrick Sanan .seealso: `PetscMallocLogRequestedSizeSetinalSizeSet()`, `PetscMallocViewSet()`
1012608c71bfSMatthew G. Knepley @*/
10139371c9d4SSatish Balay PetscErrorCode PetscMallocLogRequestedSizeGet(PetscBool *flg) {
1014608c71bfSMatthew G. Knepley   PetscFunctionBegin;
1015608c71bfSMatthew G. Knepley   *flg = TRrequestedSize;
1016608c71bfSMatthew G. Knepley   PetscFunctionReturn(0);
1017608c71bfSMatthew G. Knepley }
1018