xref: /petsc/src/sys/memory/mtr.c (revision 9371c9d470a9602b6d10a8bf50c9b2280a79e45a)
1 
2 /*
3      Interface to malloc() and free(). This code allows for logging of memory usage and some error checking
4 */
5 #include <petsc/private/petscimpl.h> /*I "petscsys.h" I*/
6 #include <petscviewer.h>
7 #if defined(PETSC_HAVE_MALLOC_H)
8 #include <malloc.h>
9 #endif
10 
11 /*
12      These are defined in mal.c and ensure that malloced space is PetscScalar aligned
13 */
14 PETSC_EXTERN PetscErrorCode PetscMallocAlign(size_t, PetscBool, int, const char[], const char[], void **);
15 PETSC_EXTERN PetscErrorCode PetscFreeAlign(void *, int, const char[], const char[]);
16 PETSC_EXTERN PetscErrorCode PetscReallocAlign(size_t, int, const char[], const char[], void **);
17 
18 #define CLASSID_VALUE ((PetscClassId)0xf0e0d0c9)
19 #define ALREADY_FREED ((PetscClassId)0x0f0e0d9c)
20 
21 /*  this is the header put at the beginning of each malloc() using for tracking allocated space and checking of allocated space heap */
22 typedef struct _trSPACE {
23   size_t       size, rsize; /* Aligned size and requested size */
24   int          id;
25   int          lineno;
26   const char  *filename;
27   const char  *functionname;
28   PetscClassId classid;
29 #if defined(PETSC_USE_DEBUG)
30   PetscStack stack;
31 #endif
32   struct _trSPACE *next, *prev;
33 } TRSPACE;
34 
35 /* HEADER_BYTES is the number of bytes in a PetscMalloc() header.
36    It is sizeof(trSPACE) padded to be a multiple of PETSC_MEMALIGN.
37 */
38 #define HEADER_BYTES ((sizeof(TRSPACE) + (PETSC_MEMALIGN - 1)) & ~(PETSC_MEMALIGN - 1))
39 
40 /* This union is used to insure that the block passed to the user retains
41    a minimum alignment of PETSC_MEMALIGN.
42 */
43 typedef union
44 {
45   TRSPACE sp;
46   char    v[HEADER_BYTES];
47 } TrSPACE;
48 
49 #define MAXTRMAXMEMS 50
50 static size_t       TRallocated           = 0;
51 static int          TRfrags               = 0;
52 static TRSPACE     *TRhead                = NULL;
53 static int          TRid                  = 0;
54 static PetscBool    TRdebugLevel          = PETSC_FALSE;
55 static PetscBool    TRdebugIinitializenan = PETSC_FALSE;
56 static PetscBool    TRrequestedSize       = PETSC_FALSE;
57 static size_t       TRMaxMem              = 0;
58 static int          NumTRMaxMems          = 0;
59 static size_t       TRMaxMems[MAXTRMAXMEMS];
60 static int          TRMaxMemsEvents[MAXTRMAXMEMS];
61 /*
62       Arrays to log information on mallocs for PetscMallocView()
63 */
64 static int          PetscLogMallocMax       = 10000;
65 static int          PetscLogMalloc          = -1;
66 static size_t       PetscLogMallocThreshold = 0;
67 static size_t      *PetscLogMallocLength;
68 static const char **PetscLogMallocFile, **PetscLogMallocFunction;
69 static int          PetscLogMallocTrace          = -1;
70 static size_t       PetscLogMallocTraceThreshold = 0;
71 static PetscViewer  PetscLogMallocTraceViewer    = NULL;
72 
73 /*@C
74    PetscMallocValidate - Test the memory for corruption.  This can be called at any time between PetscInitialize() and PetscFinalize()
75 
76    Input Parameters:
77 +  line - line number where call originated.
78 .  function - name of function calling
79 -  file - file where function is
80 
81    Return value:
82    The number of errors detected.
83 
84    Options Database:.
85 +  -malloc_test - turns this feature on when PETSc was not configured with --with-debugging=0
86 -  -malloc_debug - turns this feature on anytime
87 
88    Output Effect:
89    Error messages are written to stdout.
90 
91    Level: advanced
92 
93    Notes:
94     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)
95 
96     You should generally use CHKMEMQ as a short cut for calling this  routine.
97 
98     The Fortran calling sequence is simply PetscMallocValidate(ierr)
99 
100    No output is generated if there are no problems detected.
101 
102    Developers Note:
103      Uses the flg TRdebugLevel (set as the first argument to PetscMallocSetDebug()) to determine if it should run
104 
105 .seealso: `CHKMEMQ`
106 
107 @*/
108 PetscErrorCode PetscMallocValidate(int line, const char function[], const char file[]) {
109   TRSPACE      *head, *lasthead;
110   char         *a;
111   PetscClassId *nend;
112 
113   if (!TRdebugLevel) return 0;
114   head     = TRhead;
115   lasthead = NULL;
116   if (head && head->prev) {
117     (*PetscErrorPrintf)("PetscMallocValidate: error detected in %s() at %s:%d\n", function, file, line);
118     (*PetscErrorPrintf)("Root memory header %p has invalid back pointer %p\n", head, head->prev);
119     return PETSC_ERR_MEMC;
120   }
121   while (head) {
122     if (head->classid != CLASSID_VALUE) {
123       (*PetscErrorPrintf)("PetscMallocValidate: error detected in %s() at %s:%d\n", function, file, line);
124       (*PetscErrorPrintf)("Memory at address %p is corrupted\n", head);
125       (*PetscErrorPrintf)("Probably write before beginning of or past end of array\n");
126       if (lasthead) {
127         a = (char *)(((TrSPACE *)head) + 1);
128         (*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);
129       }
130       abort();
131       return PETSC_ERR_MEMC;
132     }
133     a    = (char *)(((TrSPACE *)head) + 1);
134     nend = (PetscClassId *)(a + head->size);
135     if (*nend != CLASSID_VALUE) {
136       (*PetscErrorPrintf)("PetscMallocValidate: error detected in %s() at %s:%d\n", function, file, line);
137       if (*nend == ALREADY_FREED) {
138         (*PetscErrorPrintf)("Memory [id=%d(%.0f)] at address %p already freed\n", head->id, (PetscLogDouble)head->size, a);
139         return PETSC_ERR_MEMC;
140       } else {
141         (*PetscErrorPrintf)("Memory [id=%d(%.0f)] at address %p is corrupted (probably write past end of array)\n", head->id, (PetscLogDouble)head->size, a);
142         (*PetscErrorPrintf)("Memory originally allocated in %s() at %s:%d\n", head->functionname, head->filename, head->lineno);
143         return PETSC_ERR_MEMC;
144       }
145     }
146     if (head->prev && head->prev != lasthead) {
147       (*PetscErrorPrintf)("PetscMallocValidate: error detected in %s() at %s:%d\n", function, file, line);
148       (*PetscErrorPrintf)("Backpointer %p is invalid, should be %p\n", head->prev, lasthead);
149       (*PetscErrorPrintf)("Previous memory originally allocated in %s() at %s:%d\n", lasthead->functionname, lasthead->filename, lasthead->lineno);
150       (*PetscErrorPrintf)("Memory originally allocated in %s() at %s:%d\n", head->functionname, head->filename, head->lineno);
151       return PETSC_ERR_MEMC;
152     }
153     lasthead = head;
154     head     = head->next;
155   }
156   return 0;
157 }
158 
159 /*
160     PetscTrMallocDefault - Malloc with tracing.
161 
162     Input Parameters:
163 +   a   - number of bytes to allocate
164 .   lineno - line number where used.  Use __LINE__ for this
165 -   filename  - file name where used.  Use __FILE__ for this
166 
167     Returns:
168     double aligned pointer to requested storage, or null if not  available.
169  */
170 PetscErrorCode PetscTrMallocDefault(size_t a, PetscBool clear, int lineno, const char function[], const char filename[], void **result) {
171   TRSPACE       *head;
172   char          *inew;
173   size_t         nsize;
174   PetscErrorCode ierr;
175 
176   PetscFunctionBegin;
177   /* Do not try to handle empty blocks */
178   if (!a) {
179     *result = NULL;
180     PetscFunctionReturn(0);
181   }
182 
183   ierr = PetscMallocValidate(lineno, function, filename);
184   if (ierr) PetscFunctionReturn(ierr);
185 
186   nsize = (a + (PETSC_MEMALIGN - 1)) & ~(PETSC_MEMALIGN - 1);
187   PetscCall(PetscMallocAlign(nsize + sizeof(TrSPACE) + sizeof(PetscClassId), clear, lineno, function, filename, (void **)&inew));
188 
189   head = (TRSPACE *)inew;
190   inew += sizeof(TrSPACE);
191 
192   if (TRhead) TRhead->prev = head;
193   head->next   = TRhead;
194   TRhead       = head;
195   head->prev   = NULL;
196   head->size   = nsize;
197   head->rsize  = a;
198   head->id     = TRid++;
199   head->lineno = lineno;
200 
201   head->filename                  = filename;
202   head->functionname              = function;
203   head->classid                   = CLASSID_VALUE;
204   *(PetscClassId *)(inew + nsize) = CLASSID_VALUE;
205 
206   TRallocated += TRrequestedSize ? head->rsize : head->size;
207   if (TRallocated > TRMaxMem) TRMaxMem = TRallocated;
208   if (PetscLogMemory) {
209     PetscInt i;
210     for (i = 0; i < NumTRMaxMems; i++) {
211       if (TRallocated > TRMaxMems[i]) TRMaxMems[i] = TRallocated;
212     }
213   }
214   TRfrags++;
215 
216 #if defined(PETSC_USE_DEBUG)
217   PetscCall(PetscStackCopy(&petscstack, &head->stack));
218   /* fix the line number to where the malloc() was called, not the PetscFunctionBegin; */
219   head->stack.line[head->stack.currentsize - 2] = lineno;
220 #if defined(PETSC_USE_REAL_SINGLE) || defined(PETSC_USE_REAL_DOUBLE)
221   if (!clear && TRdebugIinitializenan) {
222     size_t     i, n = a / sizeof(PetscReal);
223     PetscReal *s = (PetscReal *)inew;
224     /* from https://www.doc.ic.ac.uk/~eedwards/compsys/float/nan.html */
225 #if defined(PETSC_USE_REAL_SINGLE)
226     int nas = 0x7F800002;
227 #else
228     PetscInt64 nas = 0x7FF0000000000002;
229 #endif
230     for (i = 0; i < n; i++) { memcpy(s + i, &nas, sizeof(PetscReal)); }
231   }
232 #endif
233 #endif
234 
235   /*
236          Allow logging of all mallocs made.
237          TODO: Currently this memory is never freed, it should be freed during PetscFinalize()
238   */
239   if (PetscLogMalloc > -1 && PetscLogMalloc < PetscLogMallocMax && a >= PetscLogMallocThreshold) {
240     if (!PetscLogMalloc) {
241       PetscLogMallocLength = (size_t *)malloc(PetscLogMallocMax * sizeof(size_t));
242       PetscCheck(PetscLogMallocLength, PETSC_COMM_SELF, PETSC_ERR_MEM, " ");
243 
244       PetscLogMallocFile = (const char **)malloc(PetscLogMallocMax * sizeof(char *));
245       PetscCheck(PetscLogMallocFile, PETSC_COMM_SELF, PETSC_ERR_MEM, " ");
246 
247       PetscLogMallocFunction = (const char **)malloc(PetscLogMallocMax * sizeof(char *));
248       PetscCheck(PetscLogMallocFunction, PETSC_COMM_SELF, PETSC_ERR_MEM, " ");
249     }
250     PetscLogMallocLength[PetscLogMalloc]     = nsize;
251     PetscLogMallocFile[PetscLogMalloc]       = filename;
252     PetscLogMallocFunction[PetscLogMalloc++] = function;
253   }
254   if (PetscLogMallocTrace > -1 && a >= PetscLogMallocTraceThreshold) { PetscCall(PetscViewerASCIIPrintf(PetscLogMallocTraceViewer, "Alloc %zu %s:%d (%s)\n", a, filename ? filename : "null", lineno, function ? function : "null")); }
255   *result = (void *)inew;
256   PetscFunctionReturn(0);
257 }
258 
259 /*
260    PetscTrFreeDefault - Free with tracing.
261 
262    Input Parameters:
263 .   a    - pointer to a block allocated with PetscTrMalloc
264 .   lineno - line number where used.  Use __LINE__ for this
265 .   filename  - file name where used.  Use __FILE__ for this
266  */
267 PetscErrorCode PetscTrFreeDefault(void *aa, int lineno, const char function[], const char filename[]) {
268   char         *a = (char *)aa;
269   TRSPACE      *head;
270   char         *ahead;
271   size_t        asize;
272   PetscClassId *nend;
273 
274   PetscFunctionBegin;
275   /* Do not try to handle empty blocks */
276   if (!a) PetscFunctionReturn(0);
277 
278   PetscCall(PetscMallocValidate(lineno, function, filename));
279 
280   ahead = a;
281   a     = a - sizeof(TrSPACE);
282   head  = (TRSPACE *)a;
283 
284   if (head->classid != CLASSID_VALUE) {
285     (*PetscErrorPrintf)("PetscTrFreeDefault() called from %s() at %s:%d\n", function, filename, lineno);
286     (*PetscErrorPrintf)("Block at address %p is corrupted; cannot free;\nmay be block not allocated with PetscMalloc()\n", a);
287     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_MEMC, "Bad location or corrupted memory");
288   }
289   nend = (PetscClassId *)(ahead + head->size);
290   if (*nend != CLASSID_VALUE) {
291     if (*nend == ALREADY_FREED) {
292       (*PetscErrorPrintf)("PetscTrFreeDefault() called from %s() at %s:%d\n", function, filename, lineno);
293       (*PetscErrorPrintf)("Block [id=%d(%.0f)] at address %p was already freed\n", head->id, (PetscLogDouble)head->size, a + sizeof(TrSPACE));
294       if (head->lineno > 0 && head->lineno < 50000 /* sanity check */) {
295         (*PetscErrorPrintf)("Block freed in %s() at %s:%d\n", head->functionname, head->filename, head->lineno);
296       } else {
297         (*PetscErrorPrintf)("Block allocated in %s() at %s:%d\n", head->functionname, head->filename, -head->lineno);
298       }
299       SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Memory already freed");
300     } else {
301       /* Damaged tail */
302       (*PetscErrorPrintf)("PetscTrFreeDefault() called from %s() at %s:%d\n", function, filename, lineno);
303       (*PetscErrorPrintf)("Block [id=%d(%.0f)] at address %p is corrupted (probably write past end of array)\n", head->id, (PetscLogDouble)head->size, a);
304       (*PetscErrorPrintf)("Block allocated in %s() at %s:%d\n", head->functionname, head->filename, head->lineno);
305       SETERRQ(PETSC_COMM_SELF, PETSC_ERR_MEMC, "Corrupted memory");
306     }
307   }
308   if (PetscLogMallocTrace > -1 && head->rsize >= PetscLogMallocTraceThreshold) {
309     PetscCall(PetscViewerASCIIPrintf(PetscLogMallocTraceViewer, "Free  %zu %s:%d (%s)\n", head->rsize, filename ? filename : "null", lineno, function ? function : "null"));
310   }
311   /* Mark the location freed */
312   *nend = ALREADY_FREED;
313   /* Save location where freed.  If we suspect the line number, mark as  allocated location */
314   if (lineno > 0 && lineno < 50000) {
315     head->lineno       = lineno;
316     head->filename     = filename;
317     head->functionname = function;
318   } else {
319     head->lineno = -head->lineno;
320   }
321   asize = TRrequestedSize ? head->rsize : head->size;
322   PetscCheck(TRallocated >= asize, PETSC_COMM_SELF, PETSC_ERR_MEMC, "TRallocate is smaller than memory just freed");
323   TRallocated -= asize;
324   TRfrags--;
325   if (head->prev) head->prev->next = head->next;
326   else TRhead = head->next;
327 
328   if (head->next) head->next->prev = head->prev;
329   PetscCall(PetscFreeAlign(a, lineno, function, filename));
330   PetscFunctionReturn(0);
331 }
332 
333 /*
334   PetscTrReallocDefault - Realloc with tracing.
335 
336   Input Parameters:
337 + len      - number of bytes to allocate
338 . lineno   - line number where used.  Use __LINE__ for this
339 . filename - file name where used.  Use __FILE__ for this
340 - result - original memory
341 
342   Output Parameter:
343 . result - double aligned pointer to requested storage, or null if not available.
344 
345   Level: developer
346 
347 .seealso: `PetscTrMallocDefault()`, `PetscTrFreeDefault()`
348 */
349 PetscErrorCode PetscTrReallocDefault(size_t len, int lineno, const char function[], const char filename[], void **result) {
350   char          *a = (char *)*result;
351   TRSPACE       *head;
352   char          *ahead, *inew;
353   PetscClassId  *nend;
354   size_t         nsize;
355   PetscErrorCode ierr;
356 
357   PetscFunctionBegin;
358   /* Realloc requests zero space so just free the current space */
359   if (!len) {
360     PetscCall(PetscTrFreeDefault(*result, lineno, function, filename));
361     *result = NULL;
362     PetscFunctionReturn(0);
363   }
364   /* If the orginal space was NULL just use the regular malloc() */
365   if (!*result) {
366     PetscCall(PetscTrMallocDefault(len, PETSC_FALSE, lineno, function, filename, result));
367     PetscFunctionReturn(0);
368   }
369 
370   ierr = PetscMallocValidate(lineno, function, filename);
371   if (ierr) PetscFunctionReturn(ierr);
372 
373   ahead = a;
374   a     = a - sizeof(TrSPACE);
375   head  = (TRSPACE *)a;
376   inew  = a;
377 
378   if (head->classid != CLASSID_VALUE) {
379     (*PetscErrorPrintf)("PetscTrReallocDefault() called from %s() at %s:%d\n", function, filename, lineno);
380     (*PetscErrorPrintf)("Block at address %p is corrupted; cannot free;\nmay be block not allocated with PetscMalloc()\n", a);
381     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_MEMC, "Bad location or corrupted memory");
382   }
383   nend = (PetscClassId *)(ahead + head->size);
384   if (*nend != CLASSID_VALUE) {
385     if (*nend == ALREADY_FREED) {
386       (*PetscErrorPrintf)("PetscTrReallocDefault() called from %s() at %s:%d\n", function, filename, lineno);
387       (*PetscErrorPrintf)("Block [id=%d(%.0f)] at address %p was already freed\n", head->id, (PetscLogDouble)head->size, a + sizeof(TrSPACE));
388       if (head->lineno > 0 && head->lineno < 50000 /* sanity check */) {
389         (*PetscErrorPrintf)("Block freed in %s() at %s:%d\n", head->functionname, head->filename, head->lineno);
390       } else {
391         (*PetscErrorPrintf)("Block allocated in %s() at %s:%d\n", head->functionname, head->filename, -head->lineno);
392       }
393       SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Memory already freed");
394     } else {
395       /* Damaged tail */
396       (*PetscErrorPrintf)("PetscTrReallocDefault() called from %s() at %s:%d\n", function, filename, lineno);
397       (*PetscErrorPrintf)("Block [id=%d(%.0f)] at address %p is corrupted (probably write past end of array)\n", head->id, (PetscLogDouble)head->size, a);
398       (*PetscErrorPrintf)("Block allocated in %s() at %s:%d\n", head->functionname, head->filename, head->lineno);
399       SETERRQ(PETSC_COMM_SELF, PETSC_ERR_MEMC, "Corrupted memory");
400     }
401   }
402 
403   /* remove original reference to the memory allocated from the PETSc debugging heap */
404   TRallocated -= TRrequestedSize ? head->rsize : head->size;
405   TRfrags--;
406   if (head->prev) head->prev->next = head->next;
407   else TRhead = head->next;
408   if (head->next) head->next->prev = head->prev;
409 
410   nsize = (len + (PETSC_MEMALIGN - 1)) & ~(PETSC_MEMALIGN - 1);
411   PetscCall(PetscReallocAlign(nsize + sizeof(TrSPACE) + sizeof(PetscClassId), lineno, function, filename, (void **)&inew));
412 
413   head = (TRSPACE *)inew;
414   inew += sizeof(TrSPACE);
415 
416   if (TRhead) TRhead->prev = head;
417   head->next   = TRhead;
418   TRhead       = head;
419   head->prev   = NULL;
420   head->size   = nsize;
421   head->rsize  = len;
422   head->id     = TRid++;
423   head->lineno = lineno;
424 
425   head->filename                  = filename;
426   head->functionname              = function;
427   head->classid                   = CLASSID_VALUE;
428   *(PetscClassId *)(inew + nsize) = CLASSID_VALUE;
429 
430   TRallocated += TRrequestedSize ? head->rsize : head->size;
431   if (TRallocated > TRMaxMem) TRMaxMem = TRallocated;
432   if (PetscLogMemory) {
433     PetscInt i;
434     for (i = 0; i < NumTRMaxMems; i++) {
435       if (TRallocated > TRMaxMems[i]) TRMaxMems[i] = TRallocated;
436     }
437   }
438   TRfrags++;
439 
440 #if defined(PETSC_USE_DEBUG)
441   PetscCall(PetscStackCopy(&petscstack, &head->stack));
442   /* fix the line number to where the malloc() was called, not the PetscFunctionBegin; */
443   head->stack.line[head->stack.currentsize - 2] = lineno;
444 #endif
445 
446   /*
447          Allow logging of all mallocs made. This adds a new entry to the list of allocated memory
448          and does not remove the previous entry to the list hence this memory is "double counted" in PetscMallocView()
449   */
450   if (PetscLogMalloc > -1 && PetscLogMalloc < PetscLogMallocMax && len >= PetscLogMallocThreshold) {
451     if (!PetscLogMalloc) {
452       PetscLogMallocLength = (size_t *)malloc(PetscLogMallocMax * sizeof(size_t));
453       PetscCheck(PetscLogMallocLength, PETSC_COMM_SELF, PETSC_ERR_MEM, " ");
454 
455       PetscLogMallocFile = (const char **)malloc(PetscLogMallocMax * sizeof(char *));
456       PetscCheck(PetscLogMallocFile, PETSC_COMM_SELF, PETSC_ERR_MEM, " ");
457 
458       PetscLogMallocFunction = (const char **)malloc(PetscLogMallocMax * sizeof(char *));
459       PetscCheck(PetscLogMallocFunction, PETSC_COMM_SELF, PETSC_ERR_MEM, " ");
460     }
461     PetscLogMallocLength[PetscLogMalloc]     = nsize;
462     PetscLogMallocFile[PetscLogMalloc]       = filename;
463     PetscLogMallocFunction[PetscLogMalloc++] = function;
464   }
465   *result = (void *)inew;
466   PetscFunctionReturn(0);
467 }
468 
469 /*@C
470     PetscMemoryView - Shows the amount of memory currently being used in a communicator.
471 
472     Collective on PetscViewer
473 
474     Input Parameters:
475 +    viewer - the viewer that defines the communicator
476 -    message - string printed before values
477 
478     Options Database:
479 +    -malloc_debug - have PETSc track how much memory it has allocated
480 -    -memory_view - during PetscFinalize() have this routine called
481 
482     Level: intermediate
483 
484 .seealso: `PetscMallocDump()`, `PetscMemoryGetCurrentUsage()`, `PetscMemorySetGetMaximumUsage()`, `PetscMallocView()`
485  @*/
486 PetscErrorCode PetscMemoryView(PetscViewer viewer, const char message[]) {
487   PetscLogDouble allocated, allocatedmax, resident, residentmax, gallocated, gallocatedmax, gresident, gresidentmax, maxgallocated, maxgallocatedmax, maxgresident, maxgresidentmax;
488   PetscLogDouble mingallocated, mingallocatedmax, mingresident, mingresidentmax;
489   MPI_Comm       comm;
490 
491   PetscFunctionBegin;
492   if (!viewer) viewer = PETSC_VIEWER_STDOUT_WORLD;
493   PetscCall(PetscMallocGetCurrentUsage(&allocated));
494   PetscCall(PetscMallocGetMaximumUsage(&allocatedmax));
495   PetscCall(PetscMemoryGetCurrentUsage(&resident));
496   PetscCall(PetscMemoryGetMaximumUsage(&residentmax));
497   if (residentmax > 0) residentmax = PetscMax(resident, residentmax);
498   PetscCall(PetscObjectGetComm((PetscObject)viewer, &comm));
499   PetscCall(PetscViewerASCIIPrintf(viewer, "%s", message));
500   if (resident && residentmax && allocated) {
501     PetscCallMPI(MPI_Reduce(&residentmax, &gresidentmax, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm));
502     PetscCallMPI(MPI_Reduce(&residentmax, &maxgresidentmax, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm));
503     PetscCallMPI(MPI_Reduce(&residentmax, &mingresidentmax, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm));
504     PetscCall(PetscViewerASCIIPrintf(viewer, "Maximum (over computational time) process memory:        total %5.4e max %5.4e min %5.4e\n", gresidentmax, maxgresidentmax, mingresidentmax));
505     PetscCallMPI(MPI_Reduce(&resident, &gresident, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm));
506     PetscCallMPI(MPI_Reduce(&resident, &maxgresident, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm));
507     PetscCallMPI(MPI_Reduce(&resident, &mingresident, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm));
508     PetscCall(PetscViewerASCIIPrintf(viewer, "Current process memory:                                  total %5.4e max %5.4e min %5.4e\n", gresident, maxgresident, mingresident));
509     PetscCallMPI(MPI_Reduce(&allocatedmax, &gallocatedmax, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm));
510     PetscCallMPI(MPI_Reduce(&allocatedmax, &maxgallocatedmax, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm));
511     PetscCallMPI(MPI_Reduce(&allocatedmax, &mingallocatedmax, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm));
512     PetscCall(PetscViewerASCIIPrintf(viewer, "Maximum (over computational time) space PetscMalloc()ed: total %5.4e max %5.4e min %5.4e\n", gallocatedmax, maxgallocatedmax, mingallocatedmax));
513     PetscCallMPI(MPI_Reduce(&allocated, &gallocated, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm));
514     PetscCallMPI(MPI_Reduce(&allocated, &maxgallocated, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm));
515     PetscCallMPI(MPI_Reduce(&allocated, &mingallocated, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm));
516     PetscCall(PetscViewerASCIIPrintf(viewer, "Current space PetscMalloc()ed:                           total %5.4e max %5.4e min %5.4e\n", gallocated, maxgallocated, mingallocated));
517   } else if (resident && residentmax) {
518     PetscCallMPI(MPI_Reduce(&residentmax, &gresidentmax, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm));
519     PetscCallMPI(MPI_Reduce(&residentmax, &maxgresidentmax, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm));
520     PetscCallMPI(MPI_Reduce(&residentmax, &mingresidentmax, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm));
521     PetscCall(PetscViewerASCIIPrintf(viewer, "Maximum (over computational time) process memory:        total %5.4e max %5.4e min %5.4e\n", gresidentmax, maxgresidentmax, mingresidentmax));
522     PetscCallMPI(MPI_Reduce(&resident, &gresident, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm));
523     PetscCallMPI(MPI_Reduce(&resident, &maxgresident, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm));
524     PetscCallMPI(MPI_Reduce(&resident, &mingresident, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm));
525     PetscCall(PetscViewerASCIIPrintf(viewer, "Current process memory:                                  total %5.4e max %5.4e min %5.4e\n", gresident, maxgresident, mingresident));
526   } else if (resident && allocated) {
527     PetscCallMPI(MPI_Reduce(&resident, &gresident, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm));
528     PetscCallMPI(MPI_Reduce(&resident, &maxgresident, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm));
529     PetscCallMPI(MPI_Reduce(&resident, &mingresident, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm));
530     PetscCall(PetscViewerASCIIPrintf(viewer, "Current process memory:                                  total %5.4e max %5.4e min %5.4e\n", gresident, maxgresident, mingresident));
531     PetscCallMPI(MPI_Reduce(&allocated, &gallocated, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm));
532     PetscCallMPI(MPI_Reduce(&allocated, &maxgallocated, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm));
533     PetscCallMPI(MPI_Reduce(&allocated, &mingallocated, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm));
534     PetscCall(PetscViewerASCIIPrintf(viewer, "Current space PetscMalloc()ed:                           total %5.4e max %5.4e min %5.4e\n", gallocated, maxgallocated, mingallocated));
535     PetscCall(PetscViewerASCIIPrintf(viewer, "Run with -memory_view to get maximum memory usage\n"));
536   } else if (allocated) {
537     PetscCallMPI(MPI_Reduce(&allocated, &gallocated, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm));
538     PetscCallMPI(MPI_Reduce(&allocated, &maxgallocated, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm));
539     PetscCallMPI(MPI_Reduce(&allocated, &mingallocated, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm));
540     PetscCall(PetscViewerASCIIPrintf(viewer, "Current space PetscMalloc()ed:                           total %5.4e max %5.4e min %5.4e\n", gallocated, maxgallocated, mingallocated));
541     PetscCall(PetscViewerASCIIPrintf(viewer, "Run with -memory_view to get maximum memory usage\n"));
542     PetscCall(PetscViewerASCIIPrintf(viewer, "OS cannot compute process memory\n"));
543   } else {
544     PetscCall(PetscViewerASCIIPrintf(viewer, "Run with -malloc_debug to get statistics on PetscMalloc() calls\nOS cannot compute process memory\n"));
545   }
546   PetscCall(PetscViewerFlush(viewer));
547   PetscFunctionReturn(0);
548 }
549 
550 /*@
551     PetscMallocGetCurrentUsage - gets the current amount of memory used that was PetscMalloc()ed
552 
553     Not Collective
554 
555     Output Parameters:
556 .   space - number of bytes currently allocated
557 
558     Level: intermediate
559 
560 .seealso: `PetscMallocDump()`, `PetscMallocGetMaximumUsage()`, `PetscMemoryGetCurrentUsage()`,
561           `PetscMemoryGetMaximumUsage()`
562  @*/
563 PetscErrorCode PetscMallocGetCurrentUsage(PetscLogDouble *space) {
564   PetscFunctionBegin;
565   *space = (PetscLogDouble)TRallocated;
566   PetscFunctionReturn(0);
567 }
568 
569 /*@
570     PetscMallocGetMaximumUsage - gets the maximum amount of memory used that was PetscMalloc()ed at any time
571         during this run.
572 
573     Not Collective
574 
575     Output Parameters:
576 .   space - maximum number of bytes ever allocated at one time
577 
578     Level: intermediate
579 
580 .seealso: `PetscMallocDump()`, `PetscMallocView()`, `PetscMallocGetMaximumUsage()`, `PetscMemoryGetCurrentUsage()`,
581           `PetscMallocPushMaximumUsage()`
582  @*/
583 PetscErrorCode PetscMallocGetMaximumUsage(PetscLogDouble *space) {
584   PetscFunctionBegin;
585   *space = (PetscLogDouble)TRMaxMem;
586   PetscFunctionReturn(0);
587 }
588 
589 /*@
590     PetscMallocPushMaximumUsage - Adds another event to collect the maximum memory usage over an event
591 
592     Not Collective
593 
594     Input Parameter:
595 .   event - an event id; this is just for error checking
596 
597     Level: developer
598 
599 .seealso: `PetscMallocDump()`, `PetscMallocView()`, `PetscMallocGetMaximumUsage()`, `PetscMemoryGetCurrentUsage()`,
600           `PetscMallocPopMaximumUsage()`
601  @*/
602 PetscErrorCode PetscMallocPushMaximumUsage(int event) {
603   PetscFunctionBegin;
604   if (++NumTRMaxMems > MAXTRMAXMEMS) PetscFunctionReturn(0);
605   TRMaxMems[NumTRMaxMems - 1]       = TRallocated;
606   TRMaxMemsEvents[NumTRMaxMems - 1] = event;
607   PetscFunctionReturn(0);
608 }
609 
610 /*@
611     PetscMallocPopMaximumUsage - collect the maximum memory usage over an event
612 
613     Not Collective
614 
615     Input Parameter:
616 .   event - an event id; this is just for error checking
617 
618     Output Parameter:
619 .   mu - maximum amount of memory malloced during this event; high water mark relative to the beginning of the event
620 
621     Level: developer
622 
623 .seealso: `PetscMallocDump()`, `PetscMallocView()`, `PetscMallocGetMaximumUsage()`, `PetscMemoryGetCurrentUsage()`,
624           `PetscMallocPushMaximumUsage()`
625  @*/
626 PetscErrorCode PetscMallocPopMaximumUsage(int event, PetscLogDouble *mu) {
627   PetscFunctionBegin;
628   *mu = 0;
629   if (NumTRMaxMems-- > MAXTRMAXMEMS) PetscFunctionReturn(0);
630   PetscCheck(TRMaxMemsEvents[NumTRMaxMems] == event, PETSC_COMM_SELF, PETSC_ERR_MEMC, "PetscMallocPush/PopMaximumUsage() are not nested");
631   *mu = TRMaxMems[NumTRMaxMems];
632   PetscFunctionReturn(0);
633 }
634 
635 #if defined(PETSC_USE_DEBUG)
636 /*@C
637    PetscMallocGetStack - returns a pointer to the stack for the location in the program a call to PetscMalloc() was used to obtain that memory
638 
639    Collective on PETSC_COMM_WORLD
640 
641    Input Parameter:
642 .    ptr - the memory location
643 
644    Output Parameter:
645 .    stack - the stack indicating where the program allocated this memory
646 
647    Level: intermediate
648 
649 .seealso: `PetscMallocGetCurrentUsage()`, `PetscMallocView()`
650 @*/
651 PetscErrorCode PetscMallocGetStack(void *ptr, PetscStack **stack) {
652   TRSPACE *head;
653 
654   PetscFunctionBegin;
655   head   = (TRSPACE *)(((char *)ptr) - HEADER_BYTES);
656   *stack = &head->stack;
657   PetscFunctionReturn(0);
658 }
659 #else
660 PetscErrorCode PetscMallocGetStack(void *ptr, void **stack) {
661   PetscFunctionBegin;
662   *stack = NULL;
663   PetscFunctionReturn(0);
664 }
665 #endif
666 
667 /*@C
668    PetscMallocDump - Dumps the currently allocated memory blocks to a file. The information
669    printed is: size of space (in bytes), address of space, id of space,
670    file in which space was allocated, and line number at which it was
671    allocated.
672 
673    Not Collective
674 
675    Input Parameter:
676 .  fp  - file pointer.  If fp is NULL, stdout is assumed.
677 
678    Options Database Key:
679 .  -malloc_dump <optional filename> - Dumps unfreed memory during call to PetscFinalize()
680 
681    Level: intermediate
682 
683    Fortran Note:
684    The calling sequence in Fortran is PetscMallocDump(integer ierr)
685    The fp defaults to stdout.
686 
687    Notes:
688      Uses MPI_COMM_WORLD to display rank, because this may be called in PetscFinalize() after PETSC_COMM_WORLD has been freed.
689 
690      When called in PetscFinalize() dumps only the allocations that have not been properly freed
691 
692      PetscMallocView() prints a list of all memory ever allocated
693 
694 .seealso: `PetscMallocGetCurrentUsage()`, `PetscMallocView()`, `PetscMallocViewSet()`, `PetscMallocValidate()`
695 @*/
696 PetscErrorCode PetscMallocDump(FILE *fp) {
697   TRSPACE    *head;
698   size_t      libAlloc = 0;
699   PetscMPIInt rank;
700 
701   PetscFunctionBegin;
702   PetscCallMPI(MPI_Comm_rank(MPI_COMM_WORLD, &rank));
703   if (!fp) fp = PETSC_STDOUT;
704   head = TRhead;
705   while (head) {
706     libAlloc += TRrequestedSize ? head->rsize : head->size;
707     head = head->next;
708   }
709   if (TRallocated - libAlloc > 0) fprintf(fp, "[%d]Total space allocated %.0f bytes\n", rank, (PetscLogDouble)TRallocated);
710   head = TRhead;
711   while (head) {
712     PetscBool isLib;
713 
714     PetscCall(PetscStrcmp(head->functionname, "PetscDLLibraryOpen", &isLib));
715     if (!isLib) {
716       fprintf(fp, "[%2d] %.0f bytes %s() at %s:%d\n", rank, (PetscLogDouble)(TRrequestedSize ? head->rsize : head->size), head->functionname, head->filename, head->lineno);
717 #if defined(PETSC_USE_DEBUG)
718       PetscCall(PetscStackPrint(&head->stack, fp));
719 #endif
720     }
721     head = head->next;
722   }
723   PetscFunctionReturn(0);
724 }
725 
726 /*@
727     PetscMallocViewSet - Activates logging of all calls to PetscMalloc() with a minimum size to view
728 
729     Not Collective
730 
731     Input Parameter:
732 .   logmin - minimum allocation size to log, or PETSC_DEFAULT
733 
734     Options Database Key:
735 +  -malloc_view <optional filename> - Activates PetscMallocView() in PetscFinalize()
736 .  -malloc_view_threshold <min> - Sets a minimum size if -malloc_view is used
737 -  -log_view_memory - view the memory usage also with the -log_view option
738 
739     Level: advanced
740 
741     Notes: Must be called after PetscMallocSetDebug()
742 
743     Uses MPI_COMM_WORLD to determine rank because PETSc communicators may not be available
744 
745 .seealso: `PetscMallocDump()`, `PetscMallocView()`, `PetscMallocViewSet()`, `PetscMallocTraceSet()`, `PetscMallocValidate()`
746 @*/
747 PetscErrorCode PetscMallocViewSet(PetscLogDouble logmin) {
748   PetscFunctionBegin;
749   PetscLogMalloc = 0;
750   PetscCall(PetscMemorySetGetMaximumUsage());
751   if (logmin < 0) logmin = 0.0; /* PETSC_DEFAULT or PETSC_DECIDE */
752   PetscLogMallocThreshold = (size_t)logmin;
753   PetscFunctionReturn(0);
754 }
755 
756 /*@
757     PetscMallocViewGet - Determine whether all calls to PetscMalloc() are being logged
758 
759     Not Collective
760 
761     Output Parameter
762 .   logging - PETSC_TRUE if logging is active
763 
764     Options Database Key:
765 .  -malloc_view <optional filename> - Activates PetscMallocView()
766 
767     Level: advanced
768 
769 .seealso: `PetscMallocDump()`, `PetscMallocView()`, `PetscMallocTraceGet()`
770 @*/
771 PetscErrorCode PetscMallocViewGet(PetscBool *logging) {
772   PetscFunctionBegin;
773   *logging = (PetscBool)(PetscLogMalloc >= 0);
774   PetscFunctionReturn(0);
775 }
776 
777 /*@
778   PetscMallocTraceSet - Trace all calls to PetscMalloc()
779 
780   Not Collective
781 
782   Input Parameters:
783 + viewer - The viewer to use for tracing, or NULL to use stdout
784 . active - Flag to activate or deactivate tracing
785 - logmin - The smallest memory size that will be logged
786 
787   Note:
788   The viewer should not be collective.
789 
790   Level: advanced
791 
792 .seealso: `PetscMallocTraceGet()`, `PetscMallocViewGet()`, `PetscMallocDump()`, `PetscMallocView()`
793 @*/
794 PetscErrorCode PetscMallocTraceSet(PetscViewer viewer, PetscBool active, PetscLogDouble logmin) {
795   PetscFunctionBegin;
796   if (!active) {
797     PetscLogMallocTrace = -1;
798     PetscFunctionReturn(0);
799   }
800   PetscLogMallocTraceViewer = !viewer ? PETSC_VIEWER_STDOUT_SELF : viewer;
801   PetscLogMallocTrace       = 0;
802   PetscCall(PetscMemorySetGetMaximumUsage());
803   if (logmin < 0) logmin = 0.0; /* PETSC_DEFAULT or PETSC_DECIDE */
804   PetscLogMallocTraceThreshold = (size_t)logmin;
805   PetscFunctionReturn(0);
806 }
807 
808 /*@
809   PetscMallocTraceGet - Determine whether all calls to PetscMalloc() are being traced
810 
811   Not Collective
812 
813   Output Parameter:
814 . logging - PETSC_TRUE if logging is active
815 
816   Options Database Key:
817 . -malloc_view <optional filename> - Activates PetscMallocView()
818 
819   Level: advanced
820 
821 .seealso: `PetscMallocTraceSet()`, `PetscMallocViewGet()`, `PetscMallocDump()`, `PetscMallocView()`
822 @*/
823 PetscErrorCode PetscMallocTraceGet(PetscBool *logging) {
824   PetscFunctionBegin;
825   *logging = (PetscBool)(PetscLogMallocTrace >= 0);
826   PetscFunctionReturn(0);
827 }
828 
829 /*@C
830     PetscMallocView - Saves the log of all calls to PetscMalloc(); also calls
831        PetscMemoryGetMaximumUsage()
832 
833     Not Collective
834 
835     Input Parameter:
836 .   fp - file pointer; or NULL
837 
838     Options Database Key:
839 .  -malloc_view <optional filename> - Activates PetscMallocView() in PetscFinalize()
840 
841     Level: advanced
842 
843    Fortran Note:
844    The calling sequence in Fortran is PetscMallocView(integer ierr)
845    The fp defaults to stdout.
846 
847    Notes:
848      PetscMallocDump() dumps only the currently unfreed memory, this dumps all memory ever allocated
849 
850      PetscMemoryView() gives a brief summary of current memory usage
851 
852 .seealso: `PetscMallocGetCurrentUsage()`, `PetscMallocDump()`, `PetscMallocViewSet()`, `PetscMemoryView()`
853 @*/
854 PetscErrorCode PetscMallocView(FILE *fp) {
855   PetscInt       i, j, n, *perm;
856   size_t        *shortlength;
857   int           *shortcount, err;
858   PetscMPIInt    rank;
859   PetscBool      match;
860   const char   **shortfunction;
861   PetscLogDouble rss;
862 
863   PetscFunctionBegin;
864   PetscCallMPI(MPI_Comm_rank(MPI_COMM_WORLD, &rank));
865   err = fflush(fp);
866   PetscCheck(!err, PETSC_COMM_SELF, PETSC_ERR_SYS, "fflush() failed on file");
867 
868   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()");
869 
870   if (!fp) fp = PETSC_STDOUT;
871   PetscCall(PetscMemoryGetMaximumUsage(&rss));
872   if (rss) {
873     (void)fprintf(fp, "[%d] Maximum memory PetscMalloc()ed %.0f maximum size of entire process %.0f\n", rank, (PetscLogDouble)TRMaxMem, rss);
874   } else {
875     (void)fprintf(fp, "[%d] Maximum memory PetscMalloc()ed %.0f OS cannot compute size of entire process\n", rank, (PetscLogDouble)TRMaxMem);
876   }
877   shortcount = (int *)malloc(PetscLogMalloc * sizeof(int));
878   PetscCheck(shortcount, PETSC_COMM_SELF, PETSC_ERR_MEM, "Out of memory");
879   shortlength = (size_t *)malloc(PetscLogMalloc * sizeof(size_t));
880   PetscCheck(shortlength, PETSC_COMM_SELF, PETSC_ERR_MEM, "Out of memory");
881   shortfunction = (const char **)malloc(PetscLogMalloc * sizeof(char *));
882   PetscCheck(shortfunction, PETSC_COMM_SELF, PETSC_ERR_MEM, "Out of memory");
883   for (i = 0, n = 0; i < PetscLogMalloc; i++) {
884     for (j = 0; j < n; j++) {
885       PetscCall(PetscStrcmp(shortfunction[j], PetscLogMallocFunction[i], &match));
886       if (match) {
887         shortlength[j] += PetscLogMallocLength[i];
888         shortcount[j]++;
889         goto foundit;
890       }
891     }
892     shortfunction[n] = PetscLogMallocFunction[i];
893     shortlength[n]   = PetscLogMallocLength[i];
894     shortcount[n]    = 1;
895     n++;
896   foundit:;
897   }
898 
899   perm = (PetscInt *)malloc(n * sizeof(PetscInt));
900   PetscCheck(perm, PETSC_COMM_SELF, PETSC_ERR_MEM, "Out of memory");
901   for (i = 0; i < n; i++) perm[i] = i;
902   PetscCall(PetscSortStrWithPermutation(n, (const char **)shortfunction, perm));
903 
904   (void)fprintf(fp, "[%d] Memory usage sorted by function\n", rank);
905   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]]); }
906   free(perm);
907   free(shortlength);
908   free(shortcount);
909   free((char **)shortfunction);
910   err = fflush(fp);
911   PetscCheck(!err, PETSC_COMM_SELF, PETSC_ERR_SYS, "fflush() failed on file");
912   PetscFunctionReturn(0);
913 }
914 
915 /* ---------------------------------------------------------------------------- */
916 
917 /*@
918     PetscMallocSetDebug - Set's PETSc memory debugging
919 
920     Not Collective
921 
922     Input Parameters:
923 +   eachcall - checks the entire heap of allocated memory for issues on each call to PetscMalloc() and PetscFree()
924 -   initializenan - initializes all memory with NaN to catch use of uninitialized floating point arrays
925 
926     Options Database:
927 +   -malloc_debug <true or false> - turns on or off debugging
928 .   -malloc_test - turns on all debugging if PETSc was configured with debugging including -malloc_dump, otherwise ignored
929 .   -malloc_view_threshold t - log only allocations larger than t
930 .   -malloc_dump <filename> - print a list of all memory that has not been freed
931 .   -malloc no - (deprecated) same as -malloc_debug no
932 -   -malloc_log - (deprecated) same as -malloc_view
933 
934    Level: developer
935 
936     Notes: This is called in PetscInitialize() and should not be called elsewhere
937 
938 .seealso: `CHKMEMQ()`, `PetscMallocValidate()`, `PetscMallocGetDebug()`
939 @*/
940 PetscErrorCode PetscMallocSetDebug(PetscBool eachcall, PetscBool initializenan) {
941   PetscFunctionBegin;
942   PetscCheck(PetscTrMalloc != PetscTrMallocDefault, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot call this routine more than once, it can only be called in PetscInitialize()");
943   PetscCall(PetscMallocSet(PetscTrMallocDefault, PetscTrFreeDefault, PetscTrReallocDefault));
944 
945   TRallocated           = 0;
946   TRfrags               = 0;
947   TRhead                = NULL;
948   TRid                  = 0;
949   TRdebugLevel          = eachcall;
950   TRMaxMem              = 0;
951   PetscLogMallocMax     = 10000;
952   PetscLogMalloc        = -1;
953   TRdebugIinitializenan = initializenan;
954   PetscFunctionReturn(0);
955 }
956 
957 /*@
958     PetscMallocGetDebug - Indicates what PETSc memory debugging it is doing.
959 
960     Not Collective
961 
962     Output Parameters:
963 +    basic - doing basic debugging
964 .    eachcall - checks the entire memory heap at each PetscMalloc()/PetscFree()
965 -    initializenan - initializes memory with NaN
966 
967    Level: intermediate
968 
969    Notes:
970      By default, the debug version always does some debugging unless you run with -malloc_debug no
971 
972 .seealso: `CHKMEMQ()`, `PetscMallocValidate()`, `PetscMallocSetDebug()`
973 @*/
974 PetscErrorCode PetscMallocGetDebug(PetscBool *basic, PetscBool *eachcall, PetscBool *initializenan) {
975   PetscFunctionBegin;
976   if (basic) *basic = (PetscTrMalloc == PetscTrMallocDefault) ? PETSC_TRUE : PETSC_FALSE;
977   if (eachcall) *eachcall = TRdebugLevel;
978   if (initializenan) *initializenan = TRdebugIinitializenan;
979   PetscFunctionReturn(0);
980 }
981 
982 /*@
983   PetscMallocLogRequestedSizeSet - Whether to log the requested or aligned memory size
984 
985   Not Collective
986 
987   Input Parameter:
988 . flg - PETSC_TRUE to log the requested memory size
989 
990   Options Database:
991 . -malloc_requested_size <bool> - Sets this flag
992 
993   Level: developer
994 
995 .seealso: `PetscMallocLogRequestedSizeGet()`, `PetscMallocViewSet()`
996 @*/
997 PetscErrorCode PetscMallocLogRequestedSizeSet(PetscBool flg) {
998   PetscFunctionBegin;
999   TRrequestedSize = flg;
1000   PetscFunctionReturn(0);
1001 }
1002 
1003 /*@
1004   PetscMallocLogRequestedSizeGet - Whether to log the requested or aligned memory size
1005 
1006   Not Collective
1007 
1008   Output Parameter:
1009 . flg - PETSC_TRUE if we log the requested memory size
1010 
1011   Level: developer
1012 
1013 .seealso: `PetscMallocLogRequestedSizeSetinalSizeSet()`, `PetscMallocViewSet()`
1014 @*/
1015 PetscErrorCode PetscMallocLogRequestedSizeGet(PetscBool *flg) {
1016   PetscFunctionBegin;
1017   *flg = TRrequestedSize;
1018   PetscFunctionReturn(0);
1019 }
1020