xref: /petsc/src/sys/memory/mtr.c (revision 5b6bfdb9644f185dbf5e5a09b808ec241507e1e7)
1 
2 /*
3      Interface to malloc() and free(). This code allows for
4   logging of memory usage and some error checking
5 */
6 #include <petscsys.h>           /*I "petscsys.h" I*/
7 #include <petscviewer.h>
8 #if defined(PETSC_HAVE_MALLOC_H)
9 #include <malloc.h>
10 #endif
11 
12 
13 /*
14      These are defined in mal.c and ensure that malloced space is PetscScalar aligned
15 */
16 extern PetscErrorCode  PetscMallocAlign(size_t,int,const char[],const char[],void**);
17 extern PetscErrorCode  PetscFreeAlign(void*,int,const char[],const char[]);
18 extern PetscErrorCode  PetscReallocAlign(size_t,int,const char[],const char[],void**);
19 extern PetscErrorCode  PetscTrMallocDefault(size_t,int,const char[],const char[],void**);
20 extern PetscErrorCode  PetscTrFreeDefault(void*,int,const char[],const char[]);
21 extern PetscErrorCode  PetscTrReallocDefault(size_t,int,const char[],const char[],void**);
22 
23 
24 #define CLASSID_VALUE  ((PetscClassId) 0xf0e0d0c9)
25 #define ALREADY_FREED  ((PetscClassId) 0x0f0e0d9c)
26 
27 typedef struct _trSPACE {
28   size_t       size;
29   int          id;
30   int          lineno;
31   const char   *filename;
32   const char   *functionname;
33   PetscClassId classid;
34 #if defined(PETSC_USE_DEBUG)
35   PetscStack   stack;
36 #endif
37   struct _trSPACE *next,*prev;
38 } TRSPACE;
39 
40 /* HEADER_BYTES is the number of bytes in a PetscMalloc() header.
41    It is sizeof(TRSPACE) padded to be a multiple of PETSC_MEMALIGN.
42 */
43 
44 #define HEADER_BYTES  ((sizeof(TRSPACE)+(PETSC_MEMALIGN-1)) & ~(PETSC_MEMALIGN-1))
45 
46 
47 /* This union is used to insure that the block passed to the user retains
48    a minimum alignment of PETSC_MEMALIGN.
49 */
50 typedef union {
51   TRSPACE sp;
52   char    v[HEADER_BYTES];
53 } TrSPACE;
54 
55 
56 static size_t    TRallocated  = 0;
57 static int       TRfrags      = 0;
58 static TRSPACE   *TRhead      = NULL;
59 static int       TRid         = 0;
60 static PetscBool TRdebugLevel = PETSC_FALSE;
61 static size_t    TRMaxMem     = 0;
62 /*
63       Arrays to log information on all Mallocs
64 */
65 static int        PetscLogMallocMax       = 10000;
66 static int        PetscLogMalloc          = -1;
67 static size_t     PetscLogMallocThreshold = 0;
68 static size_t     *PetscLogMallocLength;
69 static const char **PetscLogMallocFile,**PetscLogMallocFunction;
70 
71 PetscErrorCode PetscSetUseTrMalloc_Private(void)
72 {
73   PetscErrorCode ierr;
74 
75   PetscFunctionBegin;
76   ierr = PetscMallocSet(PetscTrMallocDefault,PetscTrFreeDefault);CHKERRQ(ierr);
77   PetscTrRealloc = PetscTrReallocDefault;
78 
79   TRallocated       = 0;
80   TRfrags           = 0;
81   TRhead            = NULL;
82   TRid              = 0;
83   TRdebugLevel      = PETSC_FALSE;
84   TRMaxMem          = 0;
85   PetscLogMallocMax = 10000;
86   PetscLogMalloc    = -1;
87   PetscFunctionReturn(0);
88 }
89 
90 /*@C
91    PetscMallocValidate - Test the memory for corruption.  This can be used to
92    check for memory overwrites.
93 
94    Input Parameter:
95 +  line - line number where call originated.
96 .  function - name of function calling
97 -  file - file where function is
98 
99    Return value:
100    The number of errors detected.
101 
102    Output Effect:
103    Error messages are written to stdout.
104 
105    Level: advanced
106 
107    Notes:
108     You should generally use CHKMEMQ as a short cut for calling this
109     routine.
110 
111     The line, function, file are given by the C preprocessor as
112 
113     The Fortran calling sequence is simply PetscMallocValidate(ierr)
114 
115    No output is generated if there are no problems detected.
116 
117 .seealso: CHKMEMQ
118 
119 @*/
120 PetscErrorCode  PetscMallocValidate(int line,const char function[],const char file[])
121 {
122   TRSPACE      *head,*lasthead;
123   char         *a;
124   PetscClassId *nend;
125 
126   PetscFunctionBegin;
127   head = TRhead; lasthead = NULL;
128   while (head) {
129     if (head->classid != CLASSID_VALUE) {
130       (*PetscErrorPrintf)("PetscMallocValidate: error detected at  %s() line %d in %s\n",function,line,file);
131       (*PetscErrorPrintf)("Memory at address %p is corrupted\n",head);
132       (*PetscErrorPrintf)("Probably write past beginning or end of array\n");
133       if (lasthead) (*PetscErrorPrintf)("Last intact block allocated in %s() line %d in %s\n",lasthead->functionname,lasthead->lineno,lasthead->filename);
134       SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEMC," ");
135     }
136     a    = (char*)(((TrSPACE*)head) + 1);
137     nend = (PetscClassId*)(a + head->size);
138     if (*nend != CLASSID_VALUE) {
139       (*PetscErrorPrintf)("PetscMallocValidate: error detected at %s() line %d in %s\n",function,line,file);
140       if (*nend == ALREADY_FREED) {
141         (*PetscErrorPrintf)("Memory [id=%d(%.0f)] at address %p already freed\n",head->id,(PetscLogDouble)head->size,a);
142         SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEMC," ");
143       } else {
144         (*PetscErrorPrintf)("Memory [id=%d(%.0f)] at address %p is corrupted (probably write past end of array)\n",head->id,(PetscLogDouble)head->size,a);
145         (*PetscErrorPrintf)("Memory originally allocated in %s() line %d in %s\n",head->functionname,head->lineno,head->filename);
146         SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEMC," ");
147       }
148     }
149     lasthead = head;
150     head     = head->next;
151   }
152   PetscFunctionReturn(0);
153 }
154 
155 /*
156     PetscTrMallocDefault - Malloc with tracing.
157 
158     Input Parameters:
159 +   a   - number of bytes to allocate
160 .   lineno - line number where used.  Use __LINE__ for this
161 -   filename  - file name where used.  Use __FILE__ for this
162 
163     Returns:
164     double aligned pointer to requested storage, or null if not
165     available.
166  */
167 PetscErrorCode  PetscTrMallocDefault(size_t a,int lineno,const char function[],const char filename[],void **result)
168 {
169   TRSPACE        *head;
170   char           *inew;
171   size_t         nsize;
172   PetscErrorCode ierr;
173 
174   PetscFunctionBegin;
175   /* Do not try to handle empty blocks */
176   if (!a) { *result = NULL; PetscFunctionReturn(0); }
177 
178   if (TRdebugLevel) {
179     ierr = PetscMallocValidate(lineno,function,filename); if (ierr) PetscFunctionReturn(ierr);
180   }
181 
182   nsize = (a + (PETSC_MEMALIGN-1)) & ~(PETSC_MEMALIGN-1);
183   ierr  = PetscMallocAlign(nsize+sizeof(TrSPACE)+sizeof(PetscClassId),lineno,function,filename,(void**)&inew);CHKERRQ(ierr);
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->id     = TRid;
194   head->lineno = lineno;
195 
196   head->filename                 = filename;
197   head->functionname             = function;
198   head->classid                  = CLASSID_VALUE;
199   *(PetscClassId*)(inew + nsize) = CLASSID_VALUE;
200 
201   TRallocated += nsize;
202   if (TRallocated > TRMaxMem) TRMaxMem = TRallocated;
203   TRfrags++;
204 
205 #if defined(PETSC_USE_DEBUG)
206   if (PetscStackActive()) {
207     ierr = PetscStackCopy(petscstack,&head->stack);CHKERRQ(ierr);
208     /* fix the line number to where the malloc() was called, not the PetscFunctionBegin; */
209     head->stack.line[head->stack.currentsize-2] = lineno;
210   } else {
211     head->stack.currentsize = 0;
212   }
213 #endif
214 
215   /*
216          Allow logging of all mallocs made
217   */
218   if (PetscLogMalloc > -1 && PetscLogMalloc < PetscLogMallocMax && a >= PetscLogMallocThreshold) {
219     if (!PetscLogMalloc) {
220       PetscLogMallocLength = (size_t*)malloc(PetscLogMallocMax*sizeof(size_t));
221       if (!PetscLogMallocLength) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM," ");
222 
223       PetscLogMallocFile = (const char**)malloc(PetscLogMallocMax*sizeof(char*));
224       if (!PetscLogMallocFile) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM," ");
225 
226       PetscLogMallocFunction = (const char**)malloc(PetscLogMallocMax*sizeof(char*));
227       if (!PetscLogMallocFunction) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM," ");
228     }
229     PetscLogMallocLength[PetscLogMalloc]     = nsize;
230     PetscLogMallocFile[PetscLogMalloc]       = filename;
231     PetscLogMallocFunction[PetscLogMalloc++] = function;
232   }
233   *result = (void*)inew;
234   PetscFunctionReturn(0);
235 }
236 
237 
238 /*
239    PetscTrFreeDefault - Free with tracing.
240 
241    Input Parameters:
242 .   a    - pointer to a block allocated with PetscTrMalloc
243 .   lineno - line number where used.  Use __LINE__ for this
244 .   file  - file name where used.  Use __FILE__ for this
245  */
246 PetscErrorCode  PetscTrFreeDefault(void *aa,int line,const char function[],const char file[])
247 {
248   char           *a = (char*)aa;
249   TRSPACE        *head;
250   char           *ahead;
251   PetscErrorCode ierr;
252   PetscClassId   *nend;
253 
254   PetscFunctionBegin;
255   /* Do not try to handle empty blocks */
256   if (!a) PetscFunctionReturn(0);
257 
258   if (TRdebugLevel) {
259     ierr = PetscMallocValidate(line,function,file);CHKERRQ(ierr);
260   }
261 
262   ahead = a;
263   a     = a - sizeof(TrSPACE);
264   head  = (TRSPACE*)a;
265 
266   if (head->classid != CLASSID_VALUE) {
267     (*PetscErrorPrintf)("PetscTrFreeDefault() called from %s() line %d in %s\n",function,line,file);
268     (*PetscErrorPrintf)("Block at address %p is corrupted; cannot free;\nmay be block not allocated with PetscMalloc()\n",a);
269     SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEMC,"Bad location or corrupted memory");
270   }
271   nend = (PetscClassId*)(ahead + head->size);
272   if (*nend != CLASSID_VALUE) {
273     if (*nend == ALREADY_FREED) {
274       (*PetscErrorPrintf)("PetscTrFreeDefault() called from %s() line %d in %s\n",function,line,file);
275       (*PetscErrorPrintf)("Block [id=%d(%.0f)] at address %p was already freed\n",head->id,(PetscLogDouble)head->size,a + sizeof(TrSPACE));
276       if (head->lineno > 0 && head->lineno < 50000 /* sanity check */) {
277         (*PetscErrorPrintf)("Block freed in %s() line %d in %s\n",head->functionname,head->lineno,head->filename);
278       } else {
279         (*PetscErrorPrintf)("Block allocated in %s() line %d in %s\n",head->functionname,-head->lineno,head->filename);
280       }
281       SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Memory already freed");
282     } else {
283       /* Damaged tail */
284       (*PetscErrorPrintf)("PetscTrFreeDefault() called from %s() line %d in %s\n",function,line,file);
285       (*PetscErrorPrintf)("Block [id=%d(%.0f)] at address %p is corrupted (probably write past end of array)\n",head->id,(PetscLogDouble)head->size,a);
286       (*PetscErrorPrintf)("Block allocated in %s() line %d in %s\n",head->functionname,head->lineno,head->filename);
287       SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEMC,"Corrupted memory");
288     }
289   }
290   /* Mark the location freed */
291   *nend = ALREADY_FREED;
292   /* Save location where freed.  If we suspect the line number, mark as  allocated location */
293   if (line > 0 && line < 50000) {
294     head->lineno       = line;
295     head->filename     = file;
296     head->functionname = function;
297   } else {
298     head->lineno = -head->lineno;
299   }
300   /* zero out memory - helps to find some reuse of already freed memory */
301   ierr = PetscMemzero(aa,head->size);CHKERRQ(ierr);
302 
303   TRallocated -= head->size;
304   TRfrags--;
305   if (head->prev) head->prev->next = head->next;
306   else TRhead = head->next;
307 
308   if (head->next) head->next->prev = head->prev;
309   ierr = PetscFreeAlign(a,line,function,file);CHKERRQ(ierr);
310   PetscFunctionReturn(0);
311 }
312 
313 
314 
315 /*
316   PetscTrReallocDefault - Realloc with tracing.
317 
318   Input Parameters:
319 + len      - number of bytes to allocate
320 . lineno   - line number where used.  Use __LINE__ for this
321 . filename - file name where used.  Use __FILE__ for this
322 - result   - double aligned pointer to initial storage.
323 
324   Output Parameter:
325 . result - double aligned pointer to requested storage, or null if not available.
326 
327   Level: developer
328 
329 .seealso: PetscTrMallocDefault(), PetscTrFreeDefault()
330 */
331 PetscErrorCode PetscTrReallocDefault(size_t len, int lineno, const char function[], const char filename[], void **result)
332 {
333   char           *a = (char *) *result;
334   TRSPACE        *head;
335   char           *ahead, *inew;
336   PetscClassId   *nend;
337   size_t         nsize;
338   PetscErrorCode ierr;
339 
340   PetscFunctionBegin;
341   /* Realloc to zero = free */
342   if (!len) {
343     ierr = PetscTrFreeDefault(*result,lineno,function,filename);CHKERRQ(ierr);
344     *result = NULL;
345     PetscFunctionReturn(0);
346   }
347 
348   if (TRdebugLevel) {ierr = PetscMallocValidate(lineno,function,filename); if (ierr) PetscFunctionReturn(ierr);}
349 
350   ahead = a;
351   a     = a - sizeof(TrSPACE);
352   head  = (TRSPACE *) a;
353   inew  = a;
354 
355   if (head->classid != CLASSID_VALUE) {
356     (*PetscErrorPrintf)("PetscTrReallocDefault() called from %s() line %d in %s\n",function,lineno,filename);
357     (*PetscErrorPrintf)("Block at address %p is corrupted; cannot free;\nmay be block not allocated with PetscMalloc()\n",a);
358     SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEMC,"Bad location or corrupted memory");
359   }
360   nend = (PetscClassId *)(ahead + head->size);
361   if (*nend != CLASSID_VALUE) {
362     if (*nend == ALREADY_FREED) {
363       (*PetscErrorPrintf)("PetscTrReallocDefault() called from %s() line %d in %s\n",function,lineno,filename);
364       (*PetscErrorPrintf)("Block [id=%d(%.0f)] at address %p was already freed\n",head->id,(PetscLogDouble)head->size,a + sizeof(TrSPACE));
365       if (head->lineno > 0 && head->lineno < 50000 /* sanity check */) {
366         (*PetscErrorPrintf)("Block freed in %s() line %d in %s\n",head->functionname,head->lineno,head->filename);
367       } else {
368         (*PetscErrorPrintf)("Block allocated in %s() line %d in %s\n",head->functionname,-head->lineno,head->filename);
369       }
370       SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Memory already freed");
371     } else {
372       /* Damaged tail */
373       (*PetscErrorPrintf)("PetscTrReallocDefault() called from %s() line %d in %s\n",function,lineno,filename);
374       (*PetscErrorPrintf)("Block [id=%d(%.0f)] at address %p is corrupted (probably write past end of array)\n",head->id,(PetscLogDouble)head->size,a);
375       (*PetscErrorPrintf)("Block allocated in %s() line %d in %s\n",head->functionname,head->lineno,head->filename);
376       SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEMC,"Corrupted memory");
377     }
378   }
379 
380   TRallocated -= head->size;
381   TRfrags--;
382   if (head->prev) head->prev->next = head->next;
383   else TRhead = head->next;
384   if (head->next) head->next->prev = head->prev;
385 
386   nsize = (len + (PETSC_MEMALIGN-1)) & ~(PETSC_MEMALIGN-1);
387   ierr  = PetscReallocAlign(nsize+sizeof(TrSPACE)+sizeof(PetscClassId),lineno,function,filename,(void**)&inew);CHKERRQ(ierr);
388 
389   head  = (TRSPACE*)inew;
390   inew += sizeof(TrSPACE);
391 
392   if (TRhead) TRhead->prev = head;
393   head->next   = TRhead;
394   TRhead       = head;
395   head->prev   = NULL;
396   head->size   = nsize;
397   head->id     = TRid;
398   head->lineno = lineno;
399 
400   head->filename                 = filename;
401   head->functionname             = function;
402   head->classid                  = CLASSID_VALUE;
403   *(PetscClassId*)(inew + nsize) = CLASSID_VALUE;
404 
405   TRallocated += nsize;
406   if (TRallocated > TRMaxMem) TRMaxMem = TRallocated;
407   TRfrags++;
408 
409 #if defined(PETSC_USE_DEBUG)
410   if (PetscStackActive()) {
411     ierr = PetscStackCopy(petscstack,&head->stack);CHKERRQ(ierr);
412     /* fix the line number to where the malloc() was called, not the PetscFunctionBegin; */
413     head->stack.line[head->stack.currentsize-2] = lineno;
414   } else {
415     head->stack.currentsize = 0;
416   }
417 #endif
418 
419   /*
420          Allow logging of all mallocs made
421   */
422   if (PetscLogMalloc > -1 && PetscLogMalloc < PetscLogMallocMax && len >= PetscLogMallocThreshold) {
423     if (!PetscLogMalloc) {
424       PetscLogMallocLength = (size_t*)malloc(PetscLogMallocMax*sizeof(size_t));
425       if (!PetscLogMallocLength) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM," ");
426 
427       PetscLogMallocFile = (const char**)malloc(PetscLogMallocMax*sizeof(char*));
428       if (!PetscLogMallocFile) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM," ");
429 
430       PetscLogMallocFunction = (const char**)malloc(PetscLogMallocMax*sizeof(char*));
431       if (!PetscLogMallocFunction) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM," ");
432     }
433     PetscLogMallocLength[PetscLogMalloc]     = nsize;
434     PetscLogMallocFile[PetscLogMalloc]       = filename;
435     PetscLogMallocFunction[PetscLogMalloc++] = function;
436   }
437   *result = (void*)inew;
438   PetscFunctionReturn(0);
439 }
440 
441 
442 /*@C
443     PetscMemoryView - Shows the amount of memory currently being used
444         in a communicator.
445 
446     Collective on PetscViewer
447 
448     Input Parameter:
449 +    viewer - the viewer that defines the communicator
450 -    message - string printed before values
451 
452     Options Database:
453 +    -malloc - have PETSc track how much memory it has allocated
454 -    -memory_view - during PetscFinalize() have this routine called
455 
456     Level: intermediate
457 
458     Concepts: memory usage
459 
460 .seealso: PetscMallocDump(), PetscMemoryGetCurrentUsage(), PetscMemorySetGetMaximumUsage()
461  @*/
462 PetscErrorCode  PetscMemoryView(PetscViewer viewer,const char message[])
463 {
464   PetscLogDouble allocated,allocatedmax,resident,residentmax,gallocated,gallocatedmax,gresident,gresidentmax,maxgallocated,maxgallocatedmax,maxgresident,maxgresidentmax;
465   PetscLogDouble mingallocated,mingallocatedmax,mingresident,mingresidentmax;
466   PetscErrorCode ierr;
467   MPI_Comm       comm;
468 
469   PetscFunctionBegin;
470   if (!viewer) viewer = PETSC_VIEWER_STDOUT_WORLD;
471   ierr = PetscMallocGetCurrentUsage(&allocated);CHKERRQ(ierr);
472   ierr = PetscMallocGetMaximumUsage(&allocatedmax);CHKERRQ(ierr);
473   ierr = PetscMemoryGetCurrentUsage(&resident);CHKERRQ(ierr);
474   ierr = PetscMemoryGetMaximumUsage(&residentmax);CHKERRQ(ierr);
475   if (residentmax > 0) residentmax = PetscMax(resident,residentmax);
476   ierr = PetscObjectGetComm((PetscObject)viewer,&comm);CHKERRQ(ierr);
477   ierr = PetscViewerASCIIPrintf(viewer,message);CHKERRQ(ierr);
478   if (resident && residentmax && allocated) {
479     ierr = MPI_Reduce(&residentmax,&gresidentmax,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);CHKERRQ(ierr);
480     ierr = MPI_Reduce(&residentmax,&maxgresidentmax,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);CHKERRQ(ierr);
481     ierr = MPI_Reduce(&residentmax,&mingresidentmax,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);CHKERRQ(ierr);
482     ierr = PetscViewerASCIIPrintf(viewer,"Maximum (over computational time) process memory:        total %5.4e max %5.4e min %5.4e\n",gresidentmax,maxgresidentmax,mingresidentmax);CHKERRQ(ierr);
483     ierr = MPI_Reduce(&resident,&gresident,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);CHKERRQ(ierr);
484     ierr = MPI_Reduce(&resident,&maxgresident,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);CHKERRQ(ierr);
485     ierr = MPI_Reduce(&resident,&mingresident,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);CHKERRQ(ierr);
486     ierr = PetscViewerASCIIPrintf(viewer,"Current process memory:                                  total %5.4e max %5.4e min %5.4e\n",gresident,maxgresident,mingresident);CHKERRQ(ierr);
487     ierr = MPI_Reduce(&allocatedmax,&gallocatedmax,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);CHKERRQ(ierr);
488     ierr = MPI_Reduce(&allocatedmax,&maxgallocatedmax,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);CHKERRQ(ierr);
489     ierr = MPI_Reduce(&allocatedmax,&mingallocatedmax,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);CHKERRQ(ierr);
490     ierr = PetscViewerASCIIPrintf(viewer,"Maximum (over computational time) space PetscMalloc()ed: total %5.4e max %5.4e min %5.4e\n",gallocatedmax,maxgallocatedmax,mingallocatedmax);CHKERRQ(ierr);
491     ierr = MPI_Reduce(&allocated,&gallocated,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);CHKERRQ(ierr);
492     ierr = MPI_Reduce(&allocated,&maxgallocated,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);CHKERRQ(ierr);
493     ierr = MPI_Reduce(&allocated,&mingallocated,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);CHKERRQ(ierr);
494     ierr = PetscViewerASCIIPrintf(viewer,"Current space PetscMalloc()ed:                           total %5.4e max %5.4e min %5.4e\n",gallocated,maxgallocated,mingallocated);CHKERRQ(ierr);
495   } else if (resident && residentmax) {
496     ierr = MPI_Reduce(&residentmax,&gresidentmax,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);CHKERRQ(ierr);
497     ierr = MPI_Reduce(&residentmax,&maxgresidentmax,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);CHKERRQ(ierr);
498     ierr = MPI_Reduce(&residentmax,&mingresidentmax,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);CHKERRQ(ierr);
499     ierr = PetscViewerASCIIPrintf(viewer,"Maximum (over computational time) process memory:        total %5.4e max %5.4e min %5.4e\n",gresidentmax,maxgresidentmax,mingresidentmax);CHKERRQ(ierr);
500     ierr = MPI_Reduce(&resident,&gresident,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);CHKERRQ(ierr);
501     ierr = MPI_Reduce(&resident,&maxgresident,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);CHKERRQ(ierr);
502     ierr = MPI_Reduce(&resident,&mingresident,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);CHKERRQ(ierr);
503     ierr = PetscViewerASCIIPrintf(viewer,"Current process memory:                                  total %5.4e max %5.4e min %5.4e\n",gresident,maxgresident,mingresident);CHKERRQ(ierr);
504   } else if (resident && allocated) {
505     ierr = MPI_Reduce(&resident,&gresident,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);CHKERRQ(ierr);
506     ierr = MPI_Reduce(&resident,&maxgresident,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);CHKERRQ(ierr);
507     ierr = MPI_Reduce(&resident,&mingresident,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);CHKERRQ(ierr);
508     ierr = PetscViewerASCIIPrintf(viewer,"Current process memory:                                  total %5.4e max %5.4e min %5.4e\n",gresident,maxgresident,mingresident);CHKERRQ(ierr);
509     ierr = MPI_Reduce(&allocated,&gallocated,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);CHKERRQ(ierr);
510     ierr = MPI_Reduce(&allocated,&maxgallocated,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);CHKERRQ(ierr);
511     ierr = MPI_Reduce(&allocated,&mingallocated,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);CHKERRQ(ierr);
512     ierr = PetscViewerASCIIPrintf(viewer,"Current space PetscMalloc()ed:                           total %5.4e max %5.4e min %5.4e\n",gallocated,maxgallocated,mingallocated);CHKERRQ(ierr);
513     ierr = PetscViewerASCIIPrintf(viewer,"Run with -memory_view to get maximum memory usage\n");CHKERRQ(ierr);
514   } else if (allocated) {
515     ierr = MPI_Reduce(&allocated,&gallocated,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);CHKERRQ(ierr);
516     ierr = MPI_Reduce(&allocated,&maxgallocated,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);CHKERRQ(ierr);
517     ierr = MPI_Reduce(&allocated,&mingallocated,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);CHKERRQ(ierr);
518     ierr = PetscViewerASCIIPrintf(viewer,"Current space PetscMalloc()ed:                           total %5.4e max %5.4e min %5.4e\n",gallocated,maxgallocated,mingallocated);CHKERRQ(ierr);
519     ierr = PetscViewerASCIIPrintf(viewer,"Run with -memory_view to get maximum memory usage\n");CHKERRQ(ierr);
520     ierr = PetscViewerASCIIPrintf(viewer,"OS cannot compute process memory\n");CHKERRQ(ierr);
521   } else {
522     ierr = PetscViewerASCIIPrintf(viewer,"Run with -malloc to get statistics on PetscMalloc() calls\nOS cannot compute process memory\n");CHKERRQ(ierr);
523   }
524   ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
525   PetscFunctionReturn(0);
526 }
527 
528 /*@
529     PetscMallocGetCurrentUsage - gets the current amount of memory used that was PetscMalloc()ed
530 
531     Not Collective
532 
533     Output Parameters:
534 .   space - number of bytes currently allocated
535 
536     Level: intermediate
537 
538     Concepts: memory usage
539 
540 .seealso: PetscMallocDump(), PetscMallocDumpLog(), PetscMallocGetMaximumUsage(), PetscMemoryGetCurrentUsage(),
541           PetscMemoryGetMaximumUsage()
542  @*/
543 PetscErrorCode  PetscMallocGetCurrentUsage(PetscLogDouble *space)
544 {
545   PetscFunctionBegin;
546   *space = (PetscLogDouble) TRallocated;
547   PetscFunctionReturn(0);
548 }
549 
550 /*@
551     PetscMallocGetMaximumUsage - gets the maximum amount of memory used that was PetscMalloc()ed at any time
552         during this run.
553 
554     Not Collective
555 
556     Output Parameters:
557 .   space - maximum number of bytes ever allocated at one time
558 
559     Level: intermediate
560 
561     Concepts: memory usage
562 
563 .seealso: PetscMallocDump(), PetscMallocDumpLog(), PetscMallocGetMaximumUsage(), PetscMemoryGetCurrentUsage(),
564           PetscMemoryGetCurrentUsage()
565  @*/
566 PetscErrorCode  PetscMallocGetMaximumUsage(PetscLogDouble *space)
567 {
568   PetscFunctionBegin;
569   *space = (PetscLogDouble) TRMaxMem;
570   PetscFunctionReturn(0);
571 }
572 
573 #if defined(PETSC_USE_DEBUG)
574 /*@C
575    PetscMallocGetStack - returns a pointer to the stack for the location in the program a call to PetscMalloc() was used to obtain that memory
576 
577    Collective on PETSC_COMM_WORLD
578 
579    Input Parameter:
580 .    ptr - the memory location
581 
582    Output Paramter:
583 .    stack - the stack indicating where the program allocated this memory
584 
585    Level: intermediate
586 
587 .seealso:  PetscMallocGetCurrentUsage(), PetscMallocDumpLog()
588 @*/
589 PetscErrorCode  PetscMallocGetStack(void *ptr,PetscStack **stack)
590 {
591   TRSPACE *head;
592 
593   PetscFunctionBegin;
594   head   = (TRSPACE*) (((char*)ptr) - HEADER_BYTES);
595   *stack = &head->stack;
596   PetscFunctionReturn(0);
597 }
598 #else
599 PetscErrorCode  PetscMallocGetStack(void *ptr,void **stack)
600 {
601   PetscFunctionBegin;
602   *stack = NULL;
603   PetscFunctionReturn(0);
604 }
605 #endif
606 
607 /*@C
608    PetscMallocDump - Dumps the allocated memory blocks to a file. The information
609    printed is: size of space (in bytes), address of space, id of space,
610    file in which space was allocated, and line number at which it was
611    allocated.
612 
613    Collective on PETSC_COMM_WORLD
614 
615    Input Parameter:
616 .  fp  - file pointer.  If fp is NULL, stdout is assumed.
617 
618    Options Database Key:
619 .  -malloc_dump - Dumps unfreed memory during call to PetscFinalize()
620 
621    Level: intermediate
622 
623    Fortran Note:
624    The calling sequence in Fortran is PetscMallocDump(integer ierr)
625    The fp defaults to stdout.
626 
627    Notes: uses MPI_COMM_WORLD, because this may be called in PetscFinalize() after PETSC_COMM_WORLD
628           has been freed.
629 
630    Concepts: memory usage
631    Concepts: memory bleeding
632    Concepts: bleeding memory
633 
634 .seealso:  PetscMallocGetCurrentUsage(), PetscMallocDumpLog()
635 @*/
636 PetscErrorCode  PetscMallocDump(FILE *fp)
637 {
638   TRSPACE        *head;
639   PetscInt       libAlloc = 0;
640   PetscErrorCode ierr;
641   PetscMPIInt    rank;
642 
643   PetscFunctionBegin;
644   ierr = MPI_Comm_rank(MPI_COMM_WORLD,&rank);CHKERRQ(ierr);
645   if (!fp) fp = PETSC_STDOUT;
646   head = TRhead;
647   while (head) {
648     PetscBool isLib;
649 
650     ierr = PetscStrcmp(head->functionname, "PetscDLLibraryOpen", &isLib);CHKERRQ(ierr);
651     libAlloc += head->size;
652     head = head->next;
653   }
654   if (TRallocated - libAlloc > 0) fprintf(fp,"[%d]Total space allocated %.0f bytes\n",rank,(PetscLogDouble)TRallocated);
655   head = TRhead;
656   while (head) {
657     PetscBool isLib;
658 
659     ierr = PetscStrcmp(head->functionname, "PetscDLLibraryOpen", &isLib);CHKERRQ(ierr);
660     if (!isLib) {
661       fprintf(fp,"[%2d]%.0f bytes %s() line %d in %s\n",rank,(PetscLogDouble)head->size,head->functionname,head->lineno,head->filename);
662 #if defined(PETSC_USE_DEBUG)
663       ierr = PetscStackPrint(&head->stack,fp);CHKERRQ(ierr);
664 #endif
665     }
666     head = head->next;
667   }
668   PetscFunctionReturn(0);
669 }
670 
671 /* ---------------------------------------------------------------------------- */
672 
673 /*@
674     PetscMallocSetDumpLog - Activates logging of all calls to PetscMalloc().
675 
676     Not Collective
677 
678     Options Database Key:
679 +  -malloc_log <filename> - Activates PetscMallocDumpLog()
680 -  -malloc_log_threshold <min> - Activates logging and sets a minimum size
681 
682     Level: advanced
683 
684 .seealso: PetscMallocDump(), PetscMallocDumpLog(), PetscMallocSetDumpLogThreshold()
685 @*/
686 PetscErrorCode PetscMallocSetDumpLog(void)
687 {
688   PetscErrorCode ierr;
689 
690   PetscFunctionBegin;
691   PetscLogMalloc = 0;
692 
693   ierr = PetscMemorySetGetMaximumUsage();CHKERRQ(ierr);
694   PetscFunctionReturn(0);
695 }
696 
697 /*@
698     PetscMallocSetDumpLogThreshold - Activates logging of all calls to PetscMalloc().
699 
700     Not Collective
701 
702     Input Arguments:
703 .   logmin - minimum allocation size to log, or PETSC_DEFAULT
704 
705     Options Database Key:
706 +  -malloc_log <filename> - Activates PetscMallocDumpLog()
707 -  -malloc_log_threshold <min> - Activates logging and sets a minimum size
708 
709     Level: advanced
710 
711 .seealso: PetscMallocDump(), PetscMallocDumpLog(), PetscMallocSetDumpLog()
712 @*/
713 PetscErrorCode PetscMallocSetDumpLogThreshold(PetscLogDouble logmin)
714 {
715   PetscErrorCode ierr;
716 
717   PetscFunctionBegin;
718   ierr = PetscMallocSetDumpLog();CHKERRQ(ierr);
719   if (logmin < 0) logmin = 0.0; /* PETSC_DEFAULT or PETSC_DECIDE */
720   PetscLogMallocThreshold = (size_t)logmin;
721   PetscFunctionReturn(0);
722 }
723 
724 /*@
725     PetscMallocGetDumpLog - Determine whether all calls to PetscMalloc() are being logged
726 
727     Not Collective
728 
729     Output Arguments
730 .   logging - PETSC_TRUE if logging is active
731 
732     Options Database Key:
733 .  -malloc_log - Activates PetscMallocDumpLog()
734 
735     Level: advanced
736 
737 .seealso: PetscMallocDump(), PetscMallocDumpLog()
738 @*/
739 PetscErrorCode PetscMallocGetDumpLog(PetscBool *logging)
740 {
741 
742   PetscFunctionBegin;
743   *logging = (PetscBool)(PetscLogMalloc >= 0);
744   PetscFunctionReturn(0);
745 }
746 
747 /*@C
748     PetscMallocDumpLog - Dumps the log of all calls to PetscMalloc(); also calls
749        PetscMemoryGetMaximumUsage()
750 
751     Collective on PETSC_COMM_WORLD
752 
753     Input Parameter:
754 .   fp - file pointer; or NULL
755 
756     Options Database Key:
757 .  -malloc_log - Activates PetscMallocDumpLog()
758 
759     Level: advanced
760 
761    Fortran Note:
762    The calling sequence in Fortran is PetscMallocDumpLog(integer ierr)
763    The fp defaults to stdout.
764 
765 .seealso: PetscMallocGetCurrentUsage(), PetscMallocDump(), PetscMallocSetDumpLog()
766 @*/
767 PetscErrorCode  PetscMallocDumpLog(FILE *fp)
768 {
769   PetscInt       i,j,n,dummy,*perm;
770   size_t         *shortlength;
771   int            *shortcount,err;
772   PetscMPIInt    rank,size,tag = 1212 /* very bad programming */;
773   PetscBool      match;
774   const char     **shortfunction;
775   PetscLogDouble rss;
776   MPI_Status     status;
777   PetscErrorCode ierr;
778 
779   PetscFunctionBegin;
780   ierr = MPI_Comm_rank(MPI_COMM_WORLD,&rank);CHKERRQ(ierr);
781   ierr = MPI_Comm_size(MPI_COMM_WORLD,&size);CHKERRQ(ierr);
782   /*
783        Try to get the data printed in order by processor. This will only sometimes work
784   */
785   err = fflush(fp);
786   if (err) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"fflush() failed on file");
787 
788   ierr = MPI_Barrier(MPI_COMM_WORLD);CHKERRQ(ierr);
789   if (rank) {
790     ierr = MPI_Recv(&dummy,1,MPIU_INT,rank-1,tag,MPI_COMM_WORLD,&status);CHKERRQ(ierr);
791   }
792 
793   if (PetscLogMalloc < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"PetscMallocDumpLog() called without call to PetscMallocSetDumpLog() this is often due to\n                      setting the option -malloc_log AFTER PetscInitialize() with PetscOptionsInsert() or PetscOptionsInsertFile()");
794 
795   if (!fp) fp = PETSC_STDOUT;
796   ierr = PetscMemoryGetMaximumUsage(&rss);CHKERRQ(ierr);
797   if (rss) {
798     ierr = PetscFPrintf(MPI_COMM_WORLD,fp,"[%d] Maximum memory PetscMalloc()ed %.0f maximum size of entire process %.0f\n",rank,(PetscLogDouble)TRMaxMem,rss);CHKERRQ(ierr);
799   } else {
800     ierr = PetscFPrintf(MPI_COMM_WORLD,fp,"[%d] Maximum memory PetscMalloc()ed %.0f OS cannot compute size of entire process\n",rank,(PetscLogDouble)TRMaxMem);CHKERRQ(ierr);
801   }
802   shortcount    = (int*)malloc(PetscLogMalloc*sizeof(int));if (!shortcount) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM,"Out of memory");
803   shortlength   = (size_t*)malloc(PetscLogMalloc*sizeof(size_t));if (!shortlength) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM,"Out of memory");
804   shortfunction = (const char**)malloc(PetscLogMalloc*sizeof(char*));if (!shortfunction) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM,"Out of memory");
805   for (i=0,n=0; i<PetscLogMalloc; i++) {
806     for (j=0; j<n; j++) {
807       ierr = PetscStrcmp(shortfunction[j],PetscLogMallocFunction[i],&match);CHKERRQ(ierr);
808       if (match) {
809         shortlength[j] += PetscLogMallocLength[i];
810         shortcount[j]++;
811         goto foundit;
812       }
813     }
814     shortfunction[n] = PetscLogMallocFunction[i];
815     shortlength[n]   = PetscLogMallocLength[i];
816     shortcount[n]    = 1;
817     n++;
818 foundit:;
819   }
820 
821   perm = (PetscInt*)malloc(n*sizeof(PetscInt));if (!perm) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM,"Out of memory");
822   for (i=0; i<n; i++) perm[i] = i;
823   ierr = PetscSortStrWithPermutation(n,(const char**)shortfunction,perm);CHKERRQ(ierr);
824 
825   ierr = PetscFPrintf(MPI_COMM_WORLD,fp,"[%d] Memory usage sorted by function\n",rank);CHKERRQ(ierr);
826   for (i=0; i<n; i++) {
827     ierr = PetscFPrintf(MPI_COMM_WORLD,fp,"[%d] %d %.0f %s()\n",rank,shortcount[perm[i]],(PetscLogDouble)shortlength[perm[i]],shortfunction[perm[i]]);CHKERRQ(ierr);
828   }
829   free(perm);
830   free(shortlength);
831   free(shortcount);
832   free((char**)shortfunction);
833   err = fflush(fp);
834   if (err) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"fflush() failed on file");
835   if (rank != size-1) {
836     ierr = MPI_Send(&dummy,1,MPIU_INT,rank+1,tag,MPI_COMM_WORLD);CHKERRQ(ierr);
837   }
838   PetscFunctionReturn(0);
839 }
840 
841 /* ---------------------------------------------------------------------------- */
842 
843 /*@
844     PetscMallocDebug - Turns on/off debugging for the memory management routines.
845 
846     Not Collective
847 
848     Input Parameter:
849 .   level - PETSC_TRUE or PETSC_FALSE
850 
851    Level: intermediate
852 
853 .seealso: CHKMEMQ(), PetscMallocValidate()
854 @*/
855 PetscErrorCode  PetscMallocDebug(PetscBool level)
856 {
857   PetscFunctionBegin;
858   TRdebugLevel = level;
859   PetscFunctionReturn(0);
860 }
861 
862 /*@
863     PetscMallocGetDebug - Indicates if any PETSc is doing ANY memory debugging.
864 
865     Not Collective
866 
867     Output Parameter:
868 .    flg - PETSC_TRUE if any debugger
869 
870    Level: intermediate
871 
872     Note that by default, the debug version always does some debugging unless you run with -malloc no
873 
874 
875 .seealso: CHKMEMQ(), PetscMallocValidate()
876 @*/
877 PetscErrorCode  PetscMallocGetDebug(PetscBool *flg)
878 {
879   PetscFunctionBegin;
880   if (PetscTrMalloc == PetscTrMallocDefault) *flg = PETSC_TRUE;
881   else *flg = PETSC_FALSE;
882   PetscFunctionReturn(0);
883 }
884