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