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