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