xref: /petsc/src/sys/memory/mtr.c (revision 487a658c8b32ba712a1dc8280daad2fd70c1dcd9)
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 PETSC_EXTERN PetscErrorCode PetscMallocAlign(size_t,int,const char[],const char[],void**);
17 PETSC_EXTERN PetscErrorCode PetscFreeAlign(void*,int,const char[],const char[]);
18 PETSC_EXTERN PetscErrorCode PetscReallocAlign(size_t,int,const char[],const char[],void**);
19 PETSC_EXTERN PetscErrorCode PetscTrMallocDefault(size_t,int,const char[],const char[],void**);
20 PETSC_EXTERN PetscErrorCode PetscTrFreeDefault(void*,int,const char[],const char[]);
21 PETSC_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 PETSC_INTERN 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:
628     uses MPI_COMM_WORLD, because this may be called in PetscFinalize() after PETSC_COMM_WORLD
629           has been freed.
630 
631    Concepts: memory usage
632    Concepts: memory bleeding
633    Concepts: bleeding memory
634 
635 .seealso:  PetscMallocGetCurrentUsage(), PetscMallocDumpLog()
636 @*/
637 PetscErrorCode  PetscMallocDump(FILE *fp)
638 {
639   TRSPACE        *head;
640   PetscInt       libAlloc = 0;
641   PetscErrorCode ierr;
642   PetscMPIInt    rank;
643 
644   PetscFunctionBegin;
645   ierr = MPI_Comm_rank(MPI_COMM_WORLD,&rank);CHKERRQ(ierr);
646   if (!fp) fp = PETSC_STDOUT;
647   head = TRhead;
648   while (head) {
649     PetscBool isLib;
650 
651     ierr = PetscStrcmp(head->functionname, "PetscDLLibraryOpen", &isLib);CHKERRQ(ierr);
652     libAlloc += head->size;
653     head = head->next;
654   }
655   if (TRallocated - libAlloc > 0) fprintf(fp,"[%d]Total space allocated %.0f bytes\n",rank,(PetscLogDouble)TRallocated);
656   head = TRhead;
657   while (head) {
658     PetscBool isLib;
659 
660     ierr = PetscStrcmp(head->functionname, "PetscDLLibraryOpen", &isLib);CHKERRQ(ierr);
661     if (!isLib) {
662       fprintf(fp,"[%2d]%.0f bytes %s() line %d in %s\n",rank,(PetscLogDouble)head->size,head->functionname,head->lineno,head->filename);
663 #if defined(PETSC_USE_DEBUG)
664       ierr = PetscStackPrint(&head->stack,fp);CHKERRQ(ierr);
665 #endif
666     }
667     head = head->next;
668   }
669   PetscFunctionReturn(0);
670 }
671 
672 /* ---------------------------------------------------------------------------- */
673 
674 /*@
675     PetscMallocSetDumpLog - Activates logging of all calls to PetscMalloc().
676 
677     Not Collective
678 
679     Options Database Key:
680 +  -malloc_log <filename> - Activates PetscMallocDumpLog()
681 -  -malloc_log_threshold <min> - Activates logging and sets a minimum size
682 
683     Level: advanced
684 
685 .seealso: PetscMallocDump(), PetscMallocDumpLog(), PetscMallocSetDumpLogThreshold()
686 @*/
687 PetscErrorCode PetscMallocSetDumpLog(void)
688 {
689   PetscErrorCode ierr;
690 
691   PetscFunctionBegin;
692   PetscLogMalloc = 0;
693 
694   ierr = PetscMemorySetGetMaximumUsage();CHKERRQ(ierr);
695   PetscFunctionReturn(0);
696 }
697 
698 /*@
699     PetscMallocSetDumpLogThreshold - Activates logging of all calls to PetscMalloc().
700 
701     Not Collective
702 
703     Input Arguments:
704 .   logmin - minimum allocation size to log, or PETSC_DEFAULT
705 
706     Options Database Key:
707 +  -malloc_log <filename> - Activates PetscMallocDumpLog()
708 -  -malloc_log_threshold <min> - Activates logging and sets a minimum size
709 
710     Level: advanced
711 
712 .seealso: PetscMallocDump(), PetscMallocDumpLog(), PetscMallocSetDumpLog()
713 @*/
714 PetscErrorCode PetscMallocSetDumpLogThreshold(PetscLogDouble logmin)
715 {
716   PetscErrorCode ierr;
717 
718   PetscFunctionBegin;
719   ierr = PetscMallocSetDumpLog();CHKERRQ(ierr);
720   if (logmin < 0) logmin = 0.0; /* PETSC_DEFAULT or PETSC_DECIDE */
721   PetscLogMallocThreshold = (size_t)logmin;
722   PetscFunctionReturn(0);
723 }
724 
725 /*@
726     PetscMallocGetDumpLog - Determine whether all calls to PetscMalloc() are being logged
727 
728     Not Collective
729 
730     Output Arguments
731 .   logging - PETSC_TRUE if logging is active
732 
733     Options Database Key:
734 .  -malloc_log - Activates PetscMallocDumpLog()
735 
736     Level: advanced
737 
738 .seealso: PetscMallocDump(), PetscMallocDumpLog()
739 @*/
740 PetscErrorCode PetscMallocGetDumpLog(PetscBool *logging)
741 {
742 
743   PetscFunctionBegin;
744   *logging = (PetscBool)(PetscLogMalloc >= 0);
745   PetscFunctionReturn(0);
746 }
747 
748 /*@C
749     PetscMallocDumpLog - Dumps the log of all calls to PetscMalloc(); also calls
750        PetscMemoryGetMaximumUsage()
751 
752     Collective on PETSC_COMM_WORLD
753 
754     Input Parameter:
755 .   fp - file pointer; or NULL
756 
757     Options Database Key:
758 .  -malloc_log - Activates PetscMallocDumpLog()
759 
760     Level: advanced
761 
762    Fortran Note:
763    The calling sequence in Fortran is PetscMallocDumpLog(integer ierr)
764    The fp defaults to stdout.
765 
766 .seealso: PetscMallocGetCurrentUsage(), PetscMallocDump(), PetscMallocSetDumpLog()
767 @*/
768 PetscErrorCode  PetscMallocDumpLog(FILE *fp)
769 {
770   PetscInt       i,j,n,dummy,*perm;
771   size_t         *shortlength;
772   int            *shortcount,err;
773   PetscMPIInt    rank,size,tag = 1212 /* very bad programming */;
774   PetscBool      match;
775   const char     **shortfunction;
776   PetscLogDouble rss;
777   MPI_Status     status;
778   PetscErrorCode ierr;
779 
780   PetscFunctionBegin;
781   ierr = MPI_Comm_rank(MPI_COMM_WORLD,&rank);CHKERRQ(ierr);
782   ierr = MPI_Comm_size(MPI_COMM_WORLD,&size);CHKERRQ(ierr);
783   /*
784        Try to get the data printed in order by processor. This will only sometimes work
785   */
786   err = fflush(fp);
787   if (err) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"fflush() failed on file");
788 
789   ierr = MPI_Barrier(MPI_COMM_WORLD);CHKERRQ(ierr);
790   if (rank) {
791     ierr = MPI_Recv(&dummy,1,MPIU_INT,rank-1,tag,MPI_COMM_WORLD,&status);CHKERRQ(ierr);
792   }
793 
794   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()");
795 
796   if (!fp) fp = PETSC_STDOUT;
797   ierr = PetscMemoryGetMaximumUsage(&rss);CHKERRQ(ierr);
798   if (rss) {
799     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);
800   } else {
801     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);
802   }
803   shortcount    = (int*)malloc(PetscLogMalloc*sizeof(int));if (!shortcount) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM,"Out of memory");
804   shortlength   = (size_t*)malloc(PetscLogMalloc*sizeof(size_t));if (!shortlength) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM,"Out of memory");
805   shortfunction = (const char**)malloc(PetscLogMalloc*sizeof(char*));if (!shortfunction) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM,"Out of memory");
806   for (i=0,n=0; i<PetscLogMalloc; i++) {
807     for (j=0; j<n; j++) {
808       ierr = PetscStrcmp(shortfunction[j],PetscLogMallocFunction[i],&match);CHKERRQ(ierr);
809       if (match) {
810         shortlength[j] += PetscLogMallocLength[i];
811         shortcount[j]++;
812         goto foundit;
813       }
814     }
815     shortfunction[n] = PetscLogMallocFunction[i];
816     shortlength[n]   = PetscLogMallocLength[i];
817     shortcount[n]    = 1;
818     n++;
819 foundit:;
820   }
821 
822   perm = (PetscInt*)malloc(n*sizeof(PetscInt));if (!perm) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM,"Out of memory");
823   for (i=0; i<n; i++) perm[i] = i;
824   ierr = PetscSortStrWithPermutation(n,(const char**)shortfunction,perm);CHKERRQ(ierr);
825 
826   ierr = PetscFPrintf(MPI_COMM_WORLD,fp,"[%d] Memory usage sorted by function\n",rank);CHKERRQ(ierr);
827   for (i=0; i<n; i++) {
828     ierr = PetscFPrintf(MPI_COMM_WORLD,fp,"[%d] %d %.0f %s()\n",rank,shortcount[perm[i]],(PetscLogDouble)shortlength[perm[i]],shortfunction[perm[i]]);CHKERRQ(ierr);
829   }
830   free(perm);
831   free(shortlength);
832   free(shortcount);
833   free((char**)shortfunction);
834   err = fflush(fp);
835   if (err) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"fflush() failed on file");
836   if (rank != size-1) {
837     ierr = MPI_Send(&dummy,1,MPIU_INT,rank+1,tag,MPI_COMM_WORLD);CHKERRQ(ierr);
838   }
839   PetscFunctionReturn(0);
840 }
841 
842 /* ---------------------------------------------------------------------------- */
843 
844 /*@
845     PetscMallocDebug - Turns on/off debugging for the memory management routines.
846 
847     Not Collective
848 
849     Input Parameter:
850 .   level - PETSC_TRUE or PETSC_FALSE
851 
852    Level: intermediate
853 
854 .seealso: CHKMEMQ(), PetscMallocValidate()
855 @*/
856 PetscErrorCode  PetscMallocDebug(PetscBool level)
857 {
858   PetscFunctionBegin;
859   TRdebugLevel = level;
860   PetscFunctionReturn(0);
861 }
862 
863 /*@
864     PetscMallocGetDebug - Indicates if any PETSc is doing ANY memory debugging.
865 
866     Not Collective
867 
868     Output Parameter:
869 .    flg - PETSC_TRUE if any debugger
870 
871    Level: intermediate
872 
873     Note that by default, the debug version always does some debugging unless you run with -malloc no
874 
875 
876 .seealso: CHKMEMQ(), PetscMallocValidate()
877 @*/
878 PetscErrorCode  PetscMallocGetDebug(PetscBool *flg)
879 {
880   PetscFunctionBegin;
881   if (PetscTrMalloc == PetscTrMallocDefault) *flg = PETSC_TRUE;
882   else *flg = PETSC_FALSE;
883   PetscFunctionReturn(0);
884 }
885